我不确定硒中的脚本(自动测试)执行情况。我
想这个过程如下:
在大胆和在箱子里是行动之人士,在斜体和箭头所使用的
协议。
当您想与浏览器互动时,
您的代码使用您所使用的语言(Java,Python,Ruby等)使用一个webdriver客户端(通常是一个库,例如)。selenium
该客户端与WebDriver服务器通信,并按照WebDriver协议发送和接收数据;该协议封装在http中,以便于传输和控制。
该webdriver的服务器将其转换为实际命令到浏览器 -所以它(浏览器)与页面交互,或者从中获取数据。
该流始终是端到端的(例如,浏览器从不直接
与您的代码通信:)),并且是双向的。故障/异常通常
只出现在代码的上游。
一些细节
该图中的“ 浏览器的webdriver ”是二进制文件(程序)
-Firefox 的“ geckodriver” (在Windows上带有“ .exe”),“ chromedriver”,
“ safaridriver”,“ edgedriver.exe” (始终与“ .exe” :))。它充当
代理-一方面接受并理解WebDriver
协议中的命令,另一方面-知道如何与浏览器进行通信。
webdriver始终是HTTP服务器-所有命令都封装在
HTTP中,并使用常规方法get / post / delete / put (如果与
常规REST 不同,则关闭)。它实现了webdriver
协议,因此客户端(selenium&co)具有
定义良好的API与之通信。因此,它也可以称为
“ WebDriver服务器”-它侦听命令,将其代理到浏览器,然后
将响应返回给客户端。(没有人这样称呼它:),但是它
使得区分“ webdriver可执行文件”和
“ webdriver协议” 变得更加容易。
作为服务器,它在本地 计算机或远程计算机上的随机网络端口上进行绑定和侦听
。如果您在本地运行,这就是
其二进制文件必须位于path变量中的原因-初始化时Selenium
启动它(因此它必须能够找到它)并获取它正在
侦听的网络端口(以进行进一步的通信)。如果您使用的是远程
连接,则必须a)知道远程webdriver
服务器的IP:port ,或b)使用“ Selenium Hub”,它在其
域下跟踪此信息并与您共享。
网络驱动程序服务器和浏览器之间的通信通常是二进制
rpc,并且非常特定于浏览器-它使用内部API,网络驱动程序
知道如何最好地控制此特定浏览器。因此,
驱动程序由浏览器供应商提供。这始终是本地(在
同一台机器/ OS中)通信(至少据我所知)。
如果您使用的是更高级别的框架,例如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行,将selenium导入python的库以供进一步使用。
Selenium是
实现Webdriver协议的最流行的框架。它具有针对
不同语言的实现(即绑定)- 此处的
python ,
java ,
ruby 和
javascript
等。它努力做到的是为所有
这些接口提供统一的接口- getText()在Java中,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协议命令 相匹配(打开链接,这很有趣,我保证) -它是GET类型,
其参数是this和that。
它打开到此端点的“ localhost:the_know_port”网络连接:
GET /session/2cce72b7-c748-48bc-b350-6dd6730b5a69/element/5/text
第一个“随机”字符串是会话ID-一个WebDriver服务器可以被
许多客户端使用,您的服务器将在第3行建立并存储。第二个
参数(“ 5”)是元素的ID,在第4行建立。出现
“文本”-您正在请求的子资源,该元素是受支持
的子资源之一。
这就是臭名昭著的Webdriver协议/ API-特定
访问方案的知识(您可以在
会话中获取已建立元素的“文本” )和流程(必须首先建立共享会话,然后再
引用元素) ,因此最终获得“文本”)。
之后,WebDriver服务器使浏览器从其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中的元素保持引用。
但是在某个特定的时刻,第3方-在浏览器中运行的javascript代码会更改/删除该元素,非常高兴地没有意识到某些引用现在使该引用无效(来考虑一下,这是很邪恶的行为:D)。
客户端下次尝试通过WebDriver服务器在浏览器中与引用进行交互时,该元素将不再存在。自然地,交互失败,失败返回上游到客户端,并且出现异常。其短信为“元素不再希望可以将它附加到DOM上。”
我正在尝试自动化与一个网站的一些互动。我正在使用Chropath查找各种元素的绝对XPath,然后在Selenium中与它们交互。但是,有一个按钮,selenium用“消息:stale element reference:element is not attached to the page document”来响应。如果我打开一个新的chrome浏览器并导航到该按钮,Chropath会显示一个有
问题内容: 因此,我已经开始创建一些使用Selenium RC来直接在浏览器中测试我的Web应用程序的Ruby单元测试。我正在将Selenum- Client 用于红宝石。我已经为所有其他selenium测试创建了基类。 这将创建许多SeleniumDriver实例,并且在每个实例上调用所有缺少的方法。这实际上是并行运行测试。 别人如何做到这一点? 这是我的实现: 这可以工作,但是如果一个浏览器失
我不清楚浏览器是在脚本运行时还是在执行后启动回流。因此,基本上,如果我有一个循环(100次迭代),将一个元素插入DOM,浏览器会停止脚本执行,用插入的元素重新计算布局,在每一步中重新绘制?然后下一步是什么?或者它不停地插入100个元件,然后再回流? 要将其转换为代码,这两个代码之间是否存在性能差异? 还是更好? 或者,有没有更好、更有效的解决方案,可以在DOM中插入大量元素(10000个或更多),
问题内容: 这是A0.txt A0.html文件 此代码在命令中执行,但在任何浏览器中均不执行 问题答案: 正如其他人所评论的那样,您确实不想这样做。 只需在服务器端创建一个Web服务(可以是普通的servlet),然后在applet中使用它。 基本Servlet示例: 小程序基本示例: 但是要小心SQL注入。绝对不要将原始SQL查询作为请求参数或pathinfo传递,并始终使用DAO代码。 作为
我将@DataProvider用于Selenium on Java and TestNg项目,特别是用于实现saucelabs所需功能的TestBase类。我担心的是,这段代码返回“NullPointerException”错误,因为数据提供程序值从未被接受。有人能指出我的代码有什么问题吗(使用与示例相同的代码:https://github.com/saucelabs-sample-test-fr
When webpack-dev-server is running it will watch your files for changes. When that happens it rebundles your project and notifies browsers listening to refresh. To trigger this behavior you need to ch