我不确定硒中的脚本(自动测试)执行情况。 我想过程如下:
我想这就是过程。请在错误之处纠正我。
答案 0 :(得分:2)
是的,就是这样。
粗体中的框中是代理方,斜体中的箭头中是所使用的协议。
当您想与浏览器进行交互时,
selenium
)(Java, Python,Ruby等)。 流始终是端到端的(例如,浏览器从不直接与您的代码通信:)),并且是双向的。故障/异常通常仅流向您的代码。
该图中的“ 浏览器的网络驱动程序”是二进制(程序)-Firefox 的“ geckodriver”(在Windows上带有“ .exe” ),“ chromedriver”,“ safaridriver”,“ edgedriver.exe” (始终与“ .exe”一起使用:))。它充当代理-一方面接受并理解Webdriver协议中的命令,另一方面-知道如何与浏览器进行通信。
webdriver始终是HTTP服务器-所有命令都封装在HTTP中,并使用常用的方法get / post / delete / put (关闭,如果与常规REST不同,则关闭)。它implements the webdriver protocol,因此客户端(硒和钴)具有定义良好的API与之通信。因此,它也可以称为“ webdriver服务器”-它侦听命令,将命令代理到浏览器,然后将响应返回给客户端。 (没有人这样称呼它:),但是它使得区分“ webdriver可执行文件”和“ webdriver协议”更加容易)
作为服务器,它会绑定并侦听本地计算机或远程计算机上的随机网络端口。如果您在本地运行,这就是其二进制文件必须位于您的path
变量中的原因-初始化时Selenium启动它(因此它必须能够找到它)并获取它正在上监听的网络端口(以供进一步交流)。如果您使用的是远程连接,则必须a)知道远程webdriver服务器的IP:port,或b)使用“ Selenium Hub”,它在其域下跟踪此信息并与您共享。 / p>
网络驱动程序服务器和浏览器之间的通信通常是二进制rpc,并且非常特定于浏览器-它使用内部API,网络驱动程序知道如何最好地控制此特定浏览器。因此,驱动程序由浏览器供应商提供。这始终是本地(在同一台机器/操作系统中)通讯(至少据我所知)。
如果您使用的是更高级别的框架,例如Robot Framework,Cucumber,JBehave等,它位于该图中“您的代码”之前,试图使您免受某些selenium调用的干扰。
“一张图片值得一千个单词”,所以代码必须是740之类的? :)理论足够,这是一个实际示例:
from selenium import webdriver # importing selenium bindings
wd = webdriver.Firefox() # connect to the "webdriver server", a local one
element = wd.find_element_by_css_selector('#my-id') # locate an element
the_text = element.text # get is text
assert(text == 'My awesome text!') # verify it's the expected one
整个清单在第一部分中是您的代码-为完成工作而执行的不同指令,流程控制和检查。在第1行上,导入了Python的selenium
库以供进一步使用。
Selenium是实现Webdriver协议的最受欢迎的框架;它具有针对不同语言的实现(即绑定),此处python,java,ruby,javascript等。它努力做到的是为所有人提供统一的接口-Java中的getText()
在Python中也可以以.text
的形式提供,依此类推。通过此接口,它可以将客户端与实际的WebDriver协议隔离开-用户键入.text
,无需关心该协议的实际执行方式,也不必在协议更改时更改其代码。
在第3行上实例化一个webdriver
对象;由于这里是一台本地服务器,因此实例化过程将通过前面所述的本地步骤-运行“ webdriver服务器”,其端口现在已知为(并存储在对象中),并且通信可以开始。
第4行使用selenium
方法在页面中定位特定元素。在后台,该库将POST http请求发送到webdriver服务器,以查找元素。
为什么要发布?因为一旦成功找到,服务器就会为其分配一个内部ID,此后将使用该ID。并将ID返回给客户端,客户端将其存储为element
对象(*请参见脚注)的属性。
Webdriver服务器如何定位该元素?没办法-它通过专有协议与浏览器进行通讯,说:“嘿,使用您的呈现和评估引擎,在DOM中找到与该CSS选择器匹配的元素,并给我一个可供我们将来重用的参考。 ” (即“魔术”:)。因此,是由浏览器来完成工作,Webdriver服务器只是代理通信。
让我们开始讨论-第5行执行命令.text
,显然,该命令返回元素的文本(如果您不知道python,请不要会被警告,这是一个命令,但是最后没有()
-这是一种语言怪癖,别名方法作为对象属性,非常方便)。
此时会发生什么:硒python绑定将此命令与它的公共接口中的getElementText
匹配;然后将其与webdriver protocol command (打开链接,很有趣,我保证)相匹配-它是GET类型,其参数是this and that。
它将打开到此端点的“ localhost:the_know_port”的网络连接:
GET /session/2cce72b7-c748-48bc-b350-6dd6730b5a69/element/5/text
第一个“随机”字符串是会话ID-一个WebDriver服务器可被许多客户端使用,您的服务器已建立并存储在第3行。第二个参数(“ 5”)为元素的ID,在第4行中建立。然后出现“文本”-您正在请求的子资源,该元素是受支持的子资源之一。
这就是臭名昭著的Webdriver协议/ API-特定访问方案的知识(您可以在会话中获取已建立元素的“文本”)和流程(您必须首先建立共享会话,然后是对元素的引用,最后得到“文本”)。。
然后,网络驱动程序服务器使浏览器从其DOM (“魔术”)中获取信息,然后通过网络将其发送回客户端(selenium
实例) :
{"sessionId":"2cce72b7-c748-48bc-b350-6dd6730b5a69","status":0,"value":"My awesome text!"}
您的selenium
实例正在等待响应,从有效负载中获取并解析信息,然后将该值返回到您的代码-变量the_text
现在具有值“ My awesome text!”。
然后-完成,周期code -> webdriver client -> webdriver server -> browser -> webdriver server -> webdriver client -> code
现已完成。
(*)-这是令人恐惧的StaleElementReferenceException
的真实原因:这三个-客户端,WebDriver服务器和浏览器都引用DOM中的元素。
但是在某个特定的时刻,第三方-在浏览器中运行的javascript代码,更改/删除了该元素,非常高兴地没有意识到某些引用已经使它现在使无效(来想一想,这是非常邪恶的行为: D)。
客户端下一次尝试通过Webdriver服务器在浏览器中与引用进行交互时,该元素将不再存在。当然,交互会失败,失败会返回到客户端,直到异常为止。它的文本消息是“元素不再连接到DOM”-希望现在有点神秘,这很有意义。