硒浏览器自动化中的执行流程

时间:2019-01-24 08:29:47

标签: selenium testing automation webdriver automated-tests

我不确定硒中的脚本(自动测试)执行情况。 我想过程如下:

  • 开始执行。
  • 一个硒命令被转换为HTTP请求。
  • 浏览器驱动程序的HTTP服务器收到HTTP请求。
  • 浏览器驱动程序确定实现
    所需的步骤 命令。
  • 浏览器驱动程序在浏览器上执行它们。
  • 执行状态发送回浏览器的HTTP服务器 驱动程序,然后转到脚本(IDE)。

我想这就是过程。请在错误之处纠正我。

1 个答案:

答案 0 :(得分:2)

是的,就是这样。

理论

webdriver calls flow

粗体中的框中是代理方,斜体中的箭头中是所使用的协议。

当您想与浏览器进行交互时,

  1. 您的代码使用您使用的语言中的 webdriver客户端(通常是库,例如selenium)(Java, Python,Ruby等)。
  2. 该客户端与 webdriver服务器进行通信,并按照 webdriver协议发送和接收数据;该协议封装在 http 中,以便于传输和控制。
  3. 网络驱动程序服务器将其转换为浏览器的实际命令-使其(浏览器)与页面进行交互或从中获取数据。

流始终是端到端的(例如,浏览器从不直接与您的代码通信:)),并且是双向的。故障/异常通常仅流向您的代码


一些详细信息

该图中的“ 浏览器的网络驱动程序”是二进制(程序)-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协议的最受欢迎的框架;它具有针对不同语言的实现(即绑定),此处pythonjavarubyjavascript等。它努力做到的是为所有人提供统一的接口-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”-希望现在有点神秘,这很有意义。