在使用Selenium WebDriver实现web自动化测试的过程中,有一个场景:需要在一个自动化用例中,操作其他用例已经打开的浏览器即接着上一个用例的操作,继续执行。
Selenium Webdriver是使用server-client结构实现的,server端使用浏览器驱动程序来启动浏览器并且创建一个命令执行器,client端实现一个http的客户端与命令执行器通信,将按照selenium定义的格式的http请求和参数发送给命令执行器,命令执行器识别这些命令后对浏览器进行操作,而server的命令执行器和client之间的通信凭证就是sessionid。
使用python
from selenium import webdriver
driver = webdriver.Chrome()
print driver.command_exector._url
print driver.session_id
执行后,输出
http://127.0.0.1:23417 // 命令执行器的url
fe6fda53626f08b1cde42e76f05f47 // session id
此时,可以看到已经打开了一个浏览器,且我们的程序已经执行结束了。
接下来,在这个已经打开的浏览器里,打开 百度 的首页,使用postman 发送post请求
url: http://127.0.0.1:23417/session/fe6fda53626f08b1cde42e76f05f47/url
body json/application
{
"url":"https://www.baidu.com"
}
发送请求后,可以看到在之前打开的浏览器上,已经打开了百度的首页。
至于别的操作,可以查看文档来发送对应的请求。
参考:https://www.w3.org/TR/webdriver/
上面的方式,要求我们去查询文档,来发送相应请求来实现相应目的。这样工作量太大,太繁琐,不易维护。接下来我们从编码上直接去实现。
假设:已知 executor_url = “http://127.0.0.1:23417”
session_id = “fe6fda53626f08b1cde42e76f05f47”
使用python
from selenium import webdriver
executor = "http://127.0.0.1:23417"
session_id = "fe6fda53626f08b1cde42e76f05f47"
driver = webdriver.Remote(command_executor=executor , desired_capabilities={
})
driver.session_id = session_id
print driver.current_url
执行之后,有的版本可以实现,有何版本能够重新连接上一个会话,但却打开了一个新的空白会话。
查看Remote类的源码,发现每次实例化都会调用start_session这个方法新建一个会话。
解决方法:集成并重现这个类,自定义一个ReuseChrome这个类重写start_session方法使它不再新建session,使用传入的session_id
from selenium.webdriver import Remote
from selenium.webdriver.chrome import options
from selenium.common.exceptions import InvalidArgumentException
class ReuseChrome(Remote):
def __init__(self, command_executor, session_id):
self.r_session_id = session_id
Remote.__init__(self, command_executor=command_executor, desired_capabilities={
})
def start_session(self, capabilities, browser_profile=None):
"""
重写start_session方法
"""
if not isinstance(capabilities, dict):
raise InvalidArgumentException("Capabilities must be a dictionary")
if browser_profile:
if "moz:firefoxOptions" in capabilities:
capabilities["moz:firefoxOptions"]["profile"] = browser_profile.encoded
else:
capabilities.update({
'firefox_profile': browser_profile.encoded})
self.capabilities = options.Options().to_capabilities()
self.session_id = self.r_session_id
self.w3c = False
import ReuseChrome
driver = ReuseChrome(command_executor=executor_url, session_id=session_id)
print(driver.current_url)
成功了!