一,Selenium有关理论知识
1,简介
Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中,
就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),
Mozilla Firefox,Safari,Google Chrome,Opera等。
2,主要功能:
测试与浏览器的兼容性
模拟人工操作
3,生命历程
04年,诞生了Selenium Core,Selenium Core是基于浏览器并且采用JavaScript编程语言的测试工具,
运行在浏览器的安全沙箱中,设计理念是将待测试产品、Selenium Core和测试脚本均部署到同一台服务器上
来完成自动化测试的工作。05年,Selenium RC诞生,就是selenium1 ,这个时候,Selenium Core其实是
Selenium RC的核心Selenium RC让待测试产品、Selenium Core和测试脚本三者分散在不同的服务器上。
(测试脚本只关心将HTTP请求发送到指定的URL上,selenium本身不需要关心HTTP请求由于什么程序编程语言
编写而成)Selenium RC包括两部分:一个是Selenium RC Server,一个是提供各种编程语言的客户端驱动来
编写测试脚本07年,Webdriver诞生,WebDriver的设计理念是将端到端测试与底层具体的测试工具分隔离,
并采用设计模式Adapter适配器来达到目标。WebDriver的API组织更多的是面向对象。08/09年,selenium2诞生,selenium2其实是selenium rc和webdriver的合并,合并的根本原因是相互补充各自的缺点09年,selenium3诞生,这个版本剔除了selenium rc , 主要由 selenium webdriver和selenium Grid组成, 我们日常使用的其实就是selenium webdriver,至于selenium grid是一个分布式实现自动化测试的工具
4,成员组成
测试脚本(可是是Pyhon,java,c#编写的脚本程序)
浏览器驱动(不同的浏览器编写配套的驱动webdriver,比如谷歌浏览器为chromedriver.exe)
浏览器(目前selenium支持市面上大多数浏览器,如:火狐,谷歌,IE等)
二,Selenium的使用
1,下载驱动
用我们常用的谷歌浏览器举例首先我们获取本机谷歌浏览器的版本是多少,
因为驱动版本需要和浏览器版本相对应。
本机默认路径为:C:\Program Files\Google\Chrome\Application
dirPath=r'C:\Program Files\Google\Chrome\Application'
version='122.0.6261.112'
for item in os.listdir(dirPath):
if re.search(r'\d{3}.\d.\d{4}.\d{1,3}',item):
version=re.search(r'\d{3}.\d.\d{4}.\d{1,3}',item).group(0)
break
通过版本号判断本机是否已存在该驱动版本,如果没有则下载最新驱动,
并返回驱动路径驱动默认下载位置
C:\Users\admin\.wdm\drivers\chromedriver\win64\116.0.5845.141\chromedriver-win32
username = getpass.getuser()
driver_path = f"""C:\\Users\\{username}\\.wdm\\drivers\\chromedriver\\win64\\{version}\\chromedriver-win32\\chromedriver.exe"""
if not os.path.exists(driver_path):
driver_path = ChromeDriverManager().install()
2,创建驱动对象
self.driver = webdriver.Chrome(service=Service(driver_path))
3,执行自动化脚本
对于每一条selenium脚本,都有一个http请求被创建并发送给浏览器的驱动服务 HttpServer
HttpServer接收到请求后根据请求具体操控对应的浏览器
三,WebDriver的运行原理
1,开启驱动服务进程
webdriver.Chrome(service=Service(driver_path)) 自动执行chromedriver.exe驱动程序,
然后开启一个进程,
这个进程是一个http服务 http://localhost:49254
2,向驱动服务发送post请求,获取sessionid并打开一个本机浏览器
url=http://localhost:49254/session
header={
'Accept':'application/json',
'Content-Type':'application/json;charset=UTF-8',
'User-Agent':'selenium/4.11.2 (python windows)',
'Connection':'keep-alive'
}
body={
"capabilities": {
"firstMatch": [
{
}
],
"alwaysMatch": {
"browserName": "chrome",
"pageLoadStrategy": "normal",
"goog:chromeOptions": {
"excludeSwitches": [
"enable-automation"
],
"prefs": {
"profile.default_content_settings.popups": 1
},
"extensions": [
],
"args": [
"disable-infobars",
"--ignore-certificate-errors",
"--allow-insecure-localhost",
"-ignore -ssl-errors"
]
}
}
}
}
response={
"value": {
"capabilities": {
"acceptInsecureCerts": false,
"browserName": "chrome",
"browserVersion": "124.0.6367.62",
"chrome": {
"chromedriverVersion": "124.0.6367.91 (51df0e5e17a8b0a4f281c1665dbd1b8a0c6b46af-refs/branch-heads/6367@{#984})",
"userDataDir": "C:\\\\Users\\\\admin\\\\AppData\\\\Local\\\\Temp\\\\scoped_dir16596_831287611"
},
"fedcm:accounts": true,
"goog:chromeOptions": {
"debuggerAddress": "localhost:49716"
},
"networkConnectionEnabled": false,
"pageLoadStrategy": "normal",
"platformName": "windows",
"proxy": {
},
"setWindowRect": true,
"strictFileInteractability": false,
"timeouts": {
"implicit": 0,
"pageLoad": 300000,
"script": 30000
},
"unhandledPromptBehavior": "dismiss and notify",
"webauthn:extension:credBlob": true,
"webauthn:extension:largeBlob": true,
"webauthn:extension:minPinLength": true,
"webauthn:extension:prf": true,
"webauthn:virtualAuthenticators": true
},
"sessionId": "fa19533d53578b0139a15e08960435a8"
}
}
3,将自动化脚本转换为请求发送到驱动服务执行
{
'newSession': ('POST', '/session'),
'quit': ('DELETE', '/session/$sessionId'),
'w3cGetCurrentWindowHandle': ('GET', '/session/$sessionId/window'),
'w3cGetWindowHandles': ('GET', '/session/$sessionId/window/handles'),
'get': ('POST', '/session/$sessionId/url'),
'goForward': ('POST', '/session/$sessionId/forward'),
'goBack': ('POST', '/session/$sessionId/back'),
'refresh': ('POST', '/session/$sessionId/refresh'),
'w3cExecuteScript': ('POST', '/session/$sessionId/execute/sync'),
'w3cExecuteScriptAsync': ('POST', '/session/$sessionId/execute/async'),
'getCurrentUrl': ('GET', '/session/$sessionId/url'),
'getTitle': ('GET', '/session/$sessionId/title'),
'getPageSource': ('GET', '/session/$sessionId/source'),
'screenshot': ('GET', '/session/$sessionId/screenshot'),
'elementScreenshot': ('GET', '/session/$sessionId/element/$id/screenshot'),
'findElement': ('POST', '/session/$sessionId/element'),
'findElements': ('POST', '/session/$sessionId/elements'),
'w3cGetActiveElement': ('GET', '/session/$sessionId/element/active'),
'findChildElement': ('POST', '/session/$sessionId/element/$id/element'),
'findChildElements': ('POST', '/session/$sessionId/element/$id/elements'),
'clickElement': ('POST', '/session/$sessionId/element/$id/click'),
'clearElement': ('POST', '/session/$sessionId/element/$id/clear'),
'getElementText': ('GET', '/session/$sessionId/element/$id/text'),
'sendKeysToElement': ('POST', '/session/$sessionId/element/$id/value'),
'uploadFile': ('POST', '/session/$sessionId/se/file'),
'getElementTagName': ('GET', '/session/$sessionId/element/$id/name'),
'isElementSelected': ('GET', '/session/$sessionId/element/$id/selected'),
'isElementEnabled': ('GET', '/session/$sessionId/element/$id/enabled'),
'getElementRect': ('GET', '/session/$sessionId/element/$id/rect'),
'getElementAttribute': ('GET', '/session/$sessionId/element/$id/attribute/$name'),
'getElementProperty': ('GET', '/session/$sessionId/element/$id/property/$name'),
'getElementAriaRole': ('GET', '/session/$sessionId/element/$id/computedrole'),
'getElementAriaLabel': ('GET', '/session/$sessionId/element/$id/computedlabel'),
'getShadowRoot': ('GET', '/session/$sessionId/element/$id/shadow'),
'findElementFromShadowRoot': ('POST', '/session/$sessionId/shadow/$shadowId/element'),
'findElementsFromShadowRoot': ('POST', '/session/$sessionId/shadow/$shadowId/elements'),
'getCookies': ('GET', '/session/$sessionId/cookie'),
'addCookie': ('POST', '/session/$sessionId/cookie'),
'getCookie': ('GET', '/session/$sessionId/cookie/$name'),
'deleteAllCookies': ('DELETE', '/session/$sessionId/cookie'),
'deleteCookie': ('DELETE', '/session/$sessionId/cookie/$name'),
'switchToFrame': ('POST', '/session/$sessionId/frame'),
'switchToParentFrame': ('POST', '/session/$sessionId/frame/parent'),
'switchToWindow': ('POST', '/session/$sessionId/window'),
'newWindow': ('POST', '/session/$sessionId/window/new'),
'close': ('DELETE', '/session/$sessionId/window'),
'getElementValueOfCssProperty': ('GET', '/session/$sessionId/element/$id/css/$propertyName'),
'executeAsyncScript': ('POST', '/session/$sessionId/execute_async'),
'setTimeouts': ('POST', '/session/$sessionId/timeouts'),
'getTimeouts': ('GET', '/session/$sessionId/timeouts'),
'w3cDismissAlert': ('POST', '/session/$sessionId/alert/dismiss'),
'w3cAcceptAlert': ('POST', '/session/$sessionId/alert/accept'),
'w3cSetAlertValue': ('POST', '/session/$sessionId/alert/text'),
'w3cGetAlertText': ('GET', '/session/$sessionId/alert/text'),
'actions': ('POST', '/session/$sessionId/actions'),
'clearActionState': ('DELETE', '/session/$sessionId/actions'),
'setWindowRect': ('POST', '/session/$sessionId/window/rect'),
'getWindowRect': ('GET', '/session/$sessionId/window/rect'),
'w3cMaximizeWindow': ('POST', '/session/$sessionId/window/maximize'),
'setScreenOrientation': ('POST', '/session/$sessionId/orientation'),
'getScreenOrientation': ('GET', '/session/$sessionId/orientation'),
'getNetworkConnection': ('GET', '/session/$sessionId/network_connection'),
'setNetworkConnection': ('POST', '/session/$sessionId/network_connection'),
'getLog': ('POST', '/session/$sessionId/se/log'),
'getAvailableLogTypes': ('GET', '/session/$sessionId/se/log/types'),
'getCurrentContextHandle': ('GET', '/session/$sessionId/context'),
'getContextHandles': ('GET', '/session/$sessionId/contexts'),
'switchToContext': ('POST', '/session/$sessionId/context'),
'fullscreenWindow': ('POST', '/session/$sessionId/window/fullscreen'),
'minimizeWindow': ('POST', '/session/$sessionId/window/minimize'),
'printPage': ('POST', '/session/$sessionId/print'),
'addVirtualAuthenticator': ('POST', '/session/$sessionId/webauthn/authenticator'),
'removeVirtualAuthenticator': ('DELETE', '/session/$sessionId/webauthn/authenticator/$authenticatorId'),
'addCredential': ('POST', '/session/$sessionId/webauthn/authenticator/$authenticatorId/credential'),
'getCredentials': ('GET', '/session/$sessionId/webauthn/authenticator/$authenticatorId/credentials'),
'removeCredential': ('DELETE', '/session/$sessionId/webauthn/authenticator/$authenticatorId/credentials/$credentialId'),
'removeAllCredentials': ('DELETE', '/session/$sessionId/webauthn/authenticator/$authenticatorId/credentials'),
'setUserVerified': ('POST', '/session/$sessionId/webauthn/authenticator/$authenticatorId/uv'),
'launchApp': ('POST', '/session/$sessionId/chromium/launch_app'),
'setPermissions': ('POST', '/session/$sessionId/permissions'),
'setNetworkConditions': ('POST', '/session/$sessionId/chromium/network_conditions'),
'getNetworkConditions': ('GET', '/session/$sessionId/chromium/network_conditions'),
'deleteNetworkConditions': ('DELETE', '/session/$sessionId/chromium/network_conditions'),
'executeCdpCommand': ('POST', '/session/$sessionId/goog/cdp/execute'),
'getSinks': ('GET', '/session/$sessionId/goog/cast/get_sinks'),
'getIssueMessage': ('GET', '/session/$sessionId/goog/cast/get_issue_message'),
'setSinkToUse': ('POST', '/session/$sessionId/goog/cast/set_sink_to_use'),
'startDesktopMirroring': ('POST', '/session/$sessionId/goog/cast/start_desktop_mirroring'),
'startTabMirroring': ('POST', '/session/$sessionId/goog/cast/start_tab_mirroring'),
'stopCasting': ('POST', '/session/$sessionId/goog/cast/stop_casting')
}
四,自动化动作举例
driver.get()
self.driver.get("www.baidu.com")
1,首先通过自动化动作获取接口地址以及接口类型
'get': ('POST', '/session/$sessionId/url')
2,将sessionId与地址拼接成最终服务端地址
http://localhost:51016/session/082240411554fc7a198b9b5b01ec33a0/url
3,向驱动服务端发起请求
从某种意义上来说 我们只要拿到了sessionid以及驱动服务地址,
并且搞清楚每个方法的参数 我们可以通过接口的方式与浏览器交互,
而无需执行selenium方法,虽然这并没什么用。
import requests
body={"url": "https://www.baidu.com"}
headers={'Accept': 'application/json', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'selenium/4.11.2 (python windows)', 'Connection': 'keep-alive'}
url='http://localhost:51016/session/082240411554fc7a198b9b5b01ec33a0/url'
response = requests.post(url=url,json=body, headers=headers)