新网 网站建立信息管理系统网站开发教程

张小明 2026/3/12 14:31:55
新网 网站建立,信息管理系统网站开发教程,文山微网站建设,做彩票网站是违法的吗#x1f345; 点击文末小卡片#xff0c;免费获取软件测试全套资料#xff0c;资料在手#xff0c;涨薪更快 随着近些年IT行业的发展#xff0c;软件测试人才的需求越来越大#xff0c;也有很多小伙伴在考虑入坑#xff0c;而软件测试中#xff0c;收入相对较高的就是自…点击文末小卡片免费获取软件测试全套资料资料在手涨薪更快随着近些年IT行业的发展软件测试人才的需求越来越大也有很多小伙伴在考虑入坑而软件测试中收入相对较高的就是自动化了所以这次作者邀请了浩泰思特李老师为大家简单介绍下自动化测试的必备工具Selenium。Selenium是一款基于Web应用程序的开源测试工具直接运行在浏览器中支持Firefox、IE、Chrome等浏览器。同时支持Java、Python等主流语言。框架底层使用Java模拟真实用户对浏览器进行操作。测试脚本执行时浏览器自动按照脚本代码做出点击输入打开验证等操作从终端用户的角度测试应用程序。并且Selenium测试直接在浏览器中运行就像真实用户所做的一样。一、selenium简介Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中就像真正的用户在操作一样。支持的浏览器包括IE7, 8, 9, 10, 11Mozilla FirefoxSafariGoogle ChromeOpera等。主要功能包括测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本(这里主要是针对selenium ide)二、selenium历程04年诞生了Selenium CoreSelenium 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是一个分布式实现自动化测试的工具那么今天我们就要说说selenium3(selenium webdriver)的工作原理下面简称selenium(以上具体时间可能不太准确我也是通过网络资料了解到的抛砖引玉^-^)三、selenium原理我们使用Selenium实现自动化测试主要需要3个东西1.测试脚本可以是pythonjava编写的脚本程序也可以叫做client端2.浏览器驱动, 这个驱动是根据不同的浏览器开发的不同的浏览器使用不同的webdriver驱动程序且需要对应相应的浏览器版本比如geckodriver.exe(chrome)3.浏览器目前selenium支持市面上大多数浏览器如火狐谷歌IE等四、selenium脚本先看一个简单的代码 ------------------------------------ Time : 2019/6/29 8:16 Auth : linux超 File : seleniumWebdriver.py IDE : PyCharm Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! QQ : 28174043qq.com GROUP: 878565760 ------------------------------------ from selenium import webdriver dr webdriver.Chrome() # 打开浏览器执行上述代码我们会发现程序打开了Chrome浏览器(前提你已经正确配置了chrome的驱动和对应版本)那么selenium是如何实现这个过程的呢ok我们今天就通过分析源码的方式来理解selenium的工作原理五、源码分析查看weddriver源码(按住Ctrl键鼠标点击Chrome)C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py1 class WebDriver(RemoteWebDriver): 2 3 Controls the ChromeDriver and allows you to drive the browser. 4 5 You will need to download the ChromeDriver executable from 6 http://chromedriver.storage.googleapis.com/index.html 7 8 9 def __init__(self, executable_pathchromedriver, port0, 10 optionsNone, service_argsNone, 11 desired_capabilitiesNone, service_log_pathNone, 12 chrome_optionsNone, keep_aliveTrue): 13 14 Creates a new instance of the chrome driver. 15 16 Starts the service and then creates new instance of chrome driver. 17 18 :Args: 19 - executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH 20 - port - port you would like the service to run, if left as 0, a free port will be found. 21 - options - this takes an instance of ChromeOptions 22 - service_args - List of args to pass to the driver service 23 - desired_capabilities - Dictionary object with non-browser specific 24 capabilities only, such as proxy or loggingPref. 25 - service_log_path - Where to log information from the driver. 26 - chrome_options - Deprecated argument for options 27 - keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive. 28 29 if chrome_options: 30 warnings.warn(use options instead of chrome_options, 31 DeprecationWarning, stacklevel2) 32 options chrome_options 33 34 if options is None: 35 # desired_capabilities stays as passed in 36 if desired_capabilities is None: 37 desired_capabilities self.create_options().to_capabilities() 38 else: 39 if desired_capabilities is None: 40 desired_capabilities options.to_capabilities() 41 else: 42 desired_capabilities.update(options.to_capabilities()) 43 44 self.service Service( 45 executable_path, 46 portport, 47 service_argsservice_args, 48 log_pathservice_log_path) 49 self.service.start() 50 51 try: 52 RemoteWebDriver.__init__( 53 self, 54 command_executorChromeRemoteConnection( 55 remote_server_addrself.service.service_url, 56 keep_alivekeep_alive), 57 desired_capabilitiesdesired_capabilities) 58 except Exception: 59 self.quit() 60 raise 61 self._is_remote False通过源码中的44-49行发现初始化了一个service对象然后调用了start()方法那么我们继续看下一49行的start()方法到底实现了什么功能C:\Python36\Lib\site-packages\selenium\webdriver\common\service.py1 def start(self): 2 3 Starts the Service. 4 5 :Exceptions: 6 - WebDriverException : Raised either when it cant start the service 7 or when it cant connect to the service 8 9 try: 10 cmd [self.path] 11 cmd.extend(self.command_line_args()) 12 self.process subprocess.Popen(cmd, envself.env, 13 close_fdsplatform.system() ! Windows, 14 stdoutself.log_file, 15 stderrself.log_file, 16 stdinPIPE) 17 except TypeError: 18 raise 19 except OSError as err: 20 if err.errno errno.ENOENT: 21 raise WebDriverException( 22 %s executable needs to be in PATH. %s % ( 23 os.path.basename(self.path), self.start_error_message) 24 ) 25 elif err.errno errno.EACCES: 26 raise WebDriverException( 27 %s executable may have wrong permissions. %s % ( 28 os.path.basename(self.path), self.start_error_message) 29 ) 30 else: 31 raise 32 except Exception as e: 33 raise WebDriverException( 34 The executable %s needs to be available in the path. %s\n%s % 35 (os.path.basename(self.path), self.start_error_message, str(e))) 36 count 0 37 while True: 38 self.assert_process_still_running() 39 if self.is_connectable(): 40 break 41 count 1 42 time.sleep(1) 43 if count 30: 44 raise WebDriverException(Can not connect to the Service %s % self.path)我们发现9-16行其实就是执行了一个cmd命令命令的作用就是启动了chromedriver.exeChrome浏览器的驱动程序这里我们需要注意一点: 下载的浏览器驱动一定要配置到环境变量中或者放到python的根目录下便于程序在执行驱动的时候查找这个过程和我们手动启动浏览器驱动是一样的效果类似下面的结果启动驱动程序后绑定端口号9515且只允许本地访问这个服务其实我们可以查看一下我们本地电脑任务管理器确实开启了一个服务进程程序第一步工作我们已经知道了执行测试脚本webdriver.Chrome()会自动执行chromedriver.exe驱动程序然后开启一个进程六、如何打开浏览器我们继续看源码 C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py 的51-57行代码调用了父类RemoteWebDriver 的初始化方法我们看这个方法做了什么事C:\Python36\Lib\site-packages\selenium\webdriver\remote\webdriver.py1 class WebDriver(object): 2 3 Controls a browser by sending commands to a remote server. 4 This server is expected to be running the WebDriver wire protocol 5 as defined at 6 https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol 7 8 :Attributes: 9 - session_id - String ID of the browser session started and controlled by this WebDriver. 10 - capabilities - Dictionaty of effective capabilities of this browser session as returned 11 by the remote server. See https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities 12 - command_executor - remote_connection.RemoteConnection object used to execute commands. 13 - error_handler - errorhandler.ErrorHandler object used to handle errors. 14 15 16 _web_element_cls WebElement 17 18 def __init__(self, command_executorhttp://127.0.0.1:4444/wd/hub, 19 desired_capabilitiesNone, browser_profileNone, proxyNone, 20 keep_aliveFalse, file_detectorNone, optionsNone): 21 22 Create a new driver that will issue commands using the wire protocol. 23 24 :Args: 25 - command_executor - Either a string representing URL of the remote server or a custom 26 remote_connection.RemoteConnection object. Defaults to http://127.0.0.1:4444/wd/hub. 27 - desired_capabilities - A dictionary of capabilities to request when 28 starting the browser session. Required parameter. 29 - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. 30 Only used if Firefox is requested. Optional. 31 - proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will 32 be started with given proxy settings, if possible. Optional. 33 - keep_alive - Whether to configure remote_connection.RemoteConnection to use 34 HTTP keep-alive. Defaults to False. 35 - file_detector - Pass custom file detector object during instantiation. If None, 36 then default LocalFileDetector() will be used. 37 - options - instance of a driver options.Options class 38 39 capabilities {} 40 if options is not None: 41 capabilities options.to_capabilities() 42 if desired_capabilities is not None: 43 if not isinstance(desired_capabilities, dict): 44 raise WebDriverException(Desired Capabilities must be a dictionary) 45 else: 46 capabilities.update(desired_capabilities) 47 if proxy is not None: 48 warnings.warn(Please use FirefoxOptions to set proxy, 49 DeprecationWarning, stacklevel2) 50 proxy.add_to_capabilities(capabilities) 51 self.command_executor command_executor 52 if type(self.command_executor) is bytes or isinstance(self.command_executor, str): 53 self.command_executor RemoteConnection(command_executor, keep_alivekeep_alive) 54 self._is_remote True 55 self.session_id None 56 self.capabilities {} 57 self.error_handler ErrorHandler() 58 self.start_client() 59 if browser_profile is not None: 60 warnings.warn(Please use FirefoxOptions to set browser profile, 61 DeprecationWarning, stacklevel2) 62 self.start_session(capabilities, browser_profile) 63 self._switch_to SwitchTo(self) 64 self._mobile Mobile(self) 65 self.file_detector file_detector or LocalFileDetector()这里有一行最重要的代码62行self.start_session(capabilities, browser_profile) 这个方法继续看一下这个方法的源码做了什么工作1 def start_session(self, capabilities, browser_profileNone): 2 3 Creates a new session with the desired capabilities. 4 5 :Args: 6 - browser_name - The name of the browser to request. 7 - version - Which browser version to request. 8 - platform - Which platform to request the browser on. 9 - javascript_enabled - Whether the new session should support JavaScript. 10 - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object. Only used if Firefox is requested. 11 12 if not isinstance(capabilities, dict): 13 raise InvalidArgumentException(Capabilities must be a dictionary) 14 if browser_profile: 15 if moz:firefoxOptions in capabilities: 16 capabilities[moz:firefoxOptions][profile] browser_profile.encoded 17 else: 18 capabilities.update({firefox_profile: browser_profile.encoded}) 19 w3c_caps _make_w3c_caps(capabilities) 20 parameters {capabilities: w3c_caps, 21 desiredCapabilities: capabilities} 22 response self.execute(Command.NEW_SESSION, parameters) 23 if sessionId not in response: 24 response response[value] 25 self.session_id response[sessionId] 26 self.capabilities response.get(value) 27 28 # if capabilities is none we are probably speaking to 29 # a W3C endpoint 30 if self.capabilities is None: 31 self.capabilities response.get(capabilities) 32 33 # Double check to see if we have a W3C Compliant browser 34 self.w3c response.get(status) is None 35 self.command_executor.w3c self.w3c分析这部分源码可以发现22行是向地址localhost:9515/session发送了一个post请求参数是json格式的然后返回特定的响应信息给程序(这里主要就是新建了一个sessionid)最终打开了浏览器ok打开浏览器的操作完成了七、如何执行对应操作查看C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py源码(第一个源码中的51-57行)51 try: 52 RemoteWebDriver.__init__( 53 self, 54 command_executorChromeRemoteConnection( 55 remote_server_addrself.service.service_url, 56 keep_alivekeep_alive), 57 desired_capabilitiesdesired_capabilities)点击ChromeRemoteConnection查看一下源码1 from selenium.webdriver.remote.remote_connection import RemoteConnection 2 3 4 class ChromeRemoteConnection(RemoteConnection): 5 6 def __init__(self, remote_server_addr, keep_aliveTrue): 7 RemoteConnection.__init__(self, remote_server_addr, keep_alive) 8 self._commands[launchApp] (POST, /session/$sessionId/chromium/launch_app) 9 self._commands[setNetworkConditions] (POST, /session/$sessionId/chromium/network_conditions) 10 self._commands[getNetworkConditions] (GET, /session/$sessionId/chromium/network_conditions) 11 self._commands[executeCdpCommand] (POST, /session/$sessionId/goog/cdp/execute)第7行访问的是localhost:9515/session地址第8-11行定义了一些和我们使用的浏览器(chrome)特有的接口地址我们再看一下父类RemoteConnection里面源码C:\Python36\Lib\site-packages\selenium\webdriver\remote\remote_connection.py:RemoteConnection1 self._commands { 2 Command.STATUS: (GET, /status), 3 Command.NEW_SESSION: (POST, /session), 4 Command.GET_ALL_SESSIONS: (GET, /sessions), 5 Command.QUIT: (DELETE, /session/$sessionId), 6 Command.GET_CURRENT_WINDOW_HANDLE: 7 (GET, /session/$sessionId/window_handle), 8 Command.W3C_GET_CURRENT_WINDOW_HANDLE: 9 (GET, /session/$sessionId/window), 10 Command.GET_WINDOW_HANDLES: 11 (GET, /session/$sessionId/window_handles), 12 Command.W3C_GET_WINDOW_HANDLES: 13 (GET, /session/$sessionId/window/handles), 14 Command.GET: (POST, /session/$sessionId/url), 15 Command.GO_FORWARD: (POST, /session/$sessionId/forward), 16 Command.GO_BACK: (POST, /session/$sessionId/back), 17 Command.REFRESH: (POST, /session/$sessionId/refresh), 18 Command.EXECUTE_SCRIPT: (POST, /session/$sessionId/execute), 19 Command.W3C_EXECUTE_SCRIPT: 20 (POST, /session/$sessionId/execute/sync), 21 Command.W3C_EXECUTE_SCRIPT_ASYNC: 22 (POST, /session/$sessionId/execute/async), 23 Command.GET_CURRENT_URL: (GET, /session/$sessionId/url), 24 Command.GET_TITLE: (GET, /session/$sessionId/title), 25 Command.GET_PAGE_SOURCE: (GET, /session/$sessionId/source), 26 Command.SCREENSHOT: (GET, /session/$sessionId/screenshot), 27 Command.ELEMENT_SCREENSHOT: (GET, /session/$sessionId/element/$id/screenshot), 28 Command.FIND_ELEMENT: (POST, /session/$sessionId/element), 29 Command.FIND_ELEMENTS: (POST, /session/$sessionId/elements), 30 Command.W3C_GET_ACTIVE_ELEMENT: (GET, /session/$sessionId/element/active), 31 Command.GET_ACTIVE_ELEMENT: 32 (POST, /session/$sessionId/element/active), 33 Command.FIND_CHILD_ELEMENT: 34 (POST, /session/$sessionId/element/$id/element), 35 Command.FIND_CHILD_ELEMENTS: 36 (POST, /session/$sessionId/element/$id/elements), 37 Command.CLICK_ELEMENT: (POST, /session/$sessionId/element/$id/click), 38 Command.CLEAR_ELEMENT: (POST, /session/$sessionId/element/$id/clear), 39 Command.SUBMIT_ELEMENT: (POST, /session/$sessionId/element/$id/submit), 40 Command.GET_ELEMENT_TEXT: (GET, /session/$sessionId/element/$id/text), 41 Command.SEND_KEYS_TO_ELEMENT: 42 (POST, /session/$sessionId/element/$id/value), 43 Command.SEND_KEYS_TO_ACTIVE_ELEMENT: 44 (POST, /session/$sessionId/keys), 45 Command.UPLOAD_FILE: (POST, /session/$sessionId/file), 46 Command.GET_ELEMENT_VALUE: 47 (GET, /session/$sessionId/element/$id/value), 48 Command.GET_ELEMENT_TAG_NAME: 49 (GET, /session/$sessionId/element/$id/name), 50 Command.IS_ELEMENT_SELECTED: 51 (GET, /session/$sessionId/element/$id/selected), 52 Command.SET_ELEMENT_SELECTED: 53 (POST, /session/$sessionId/element/$id/selected), 54 Command.IS_ELEMENT_ENABLED: 55 (GET, /session/$sessionId/element/$id/enabled), 56 Command.IS_ELEMENT_DISPLAYED: 57 (GET, /session/$sessionId/element/$id/displayed), 58 Command.GET_ELEMENT_LOCATION: 59 (GET, /session/$sessionId/element/$id/location), 60 Command.GET_ELEMENT_LOCATION_ONCE_SCROLLED_INTO_VIEW: 61 (GET, /session/$sessionId/element/$id/location_in_view), 62 Command.GET_ELEMENT_SIZE: 63 (GET, /session/$sessionId/element/$id/size), 64 Command.GET_ELEMENT_RECT: 65 (GET, /session/$sessionId/element/$id/rect), 66 Command.GET_ELEMENT_ATTRIBUTE: 67 (GET, /session/$sessionId/element/$id/attribute/$name), 68 Command.GET_ELEMENT_PROPERTY: 69 (GET, /session/$sessionId/element/$id/property/$name), 70 Command.GET_ALL_COOKIES: (GET, /session/$sessionId/cookie), 71 Command.ADD_COOKIE: (POST, /session/$sessionId/cookie), 72 Command.GET_COOKIE: (GET, /session/$sessionId/cookie/$name), 73 Command.DELETE_ALL_COOKIES: 74 (DELETE, /session/$sessionId/cookie), 75 Command.DELETE_COOKIE: 76 (DELETE, /session/$sessionId/cookie/$name), 77 Command.SWITCH_TO_FRAME: (POST, /session/$sessionId/frame), 78 Command.SWITCH_TO_PARENT_FRAME: (POST, /session/$sessionId/frame/parent), 79 Command.SWITCH_TO_WINDOW: (POST, /session/$sessionId/window), 80 Command.CLOSE: (DELETE, /session/$sessionId/window), 81 Command.GET_ELEMENT_VALUE_OF_CSS_PROPERTY: 82 (GET, /session/$sessionId/element/$id/css/$propertyName), 83 Command.IMPLICIT_WAIT: 84 (POST, /session/$sessionId/timeouts/implicit_wait), 85 Command.EXECUTE_ASYNC_SCRIPT: (POST, /session/$sessionId/execute_async), 86 Command.SET_SCRIPT_TIMEOUT: 87 (POST, /session/$sessionId/timeouts/async_script), 88 Command.SET_TIMEOUTS: 89 (POST, /session/$sessionId/timeouts), 90 Command.DISMISS_ALERT: 91 (POST, /session/$sessionId/dismiss_alert), 92 Command.W3C_DISMISS_ALERT: 93 (POST, /session/$sessionId/alert/dismiss), 94 Command.ACCEPT_ALERT: 95 (POST, /session/$sessionId/accept_alert), 96 Command.W3C_ACCEPT_ALERT: 97 (POST, /session/$sessionId/alert/accept), 98 Command.SET_ALERT_VALUE: 99 (POST, /session/$sessionId/alert_text), 100 Command.W3C_SET_ALERT_VALUE: 101 (POST, /session/$sessionId/alert/text), 102 Command.GET_ALERT_TEXT: 103 (GET, /session/$sessionId/alert_text), 104 Command.W3C_GET_ALERT_TEXT: 105 (GET, /session/$sessionId/alert/text), 106 Command.SET_ALERT_CREDENTIALS: 107 (POST, /session/$sessionId/alert/credentials), 108 Command.CLICK: 109 (POST, /session/$sessionId/click), 110 Command.W3C_ACTIONS: 111 (POST, /session/$sessionId/actions), 112 Command.W3C_CLEAR_ACTIONS: 113 (DELETE, /session/$sessionId/actions), 114 Command.DOUBLE_CLICK: 115 (POST, /session/$sessionId/doubleclick), 116 Command.MOUSE_DOWN: 117 (POST, /session/$sessionId/buttondown), 118 Command.MOUSE_UP: 119 (POST, /session/$sessionId/buttonup), 120 Command.MOVE_TO: 121 (POST, /session/$sessionId/moveto), 122 Command.GET_WINDOW_SIZE: 123 (GET, /session/$sessionId/window/$windowHandle/size), 124 Command.SET_WINDOW_SIZE: 125 (POST, /session/$sessionId/window/$windowHandle/size), 126 Command.GET_WINDOW_POSITION: 127 (GET, /session/$sessionId/window/$windowHandle/position), 128 Command.SET_WINDOW_POSITION: 129 (POST, /session/$sessionId/window/$windowHandle/position), 130 Command.SET_WINDOW_RECT: 131 (POST, /session/$sessionId/window/rect), 132 Command.GET_WINDOW_RECT: 133 (GET, /session/$sessionId/window/rect), 134 Command.MAXIMIZE_WINDOW: 135 (POST, /session/$sessionId/window/$windowHandle/maximize), 136 Command.W3C_MAXIMIZE_WINDOW: 137 (POST, /session/$sessionId/window/maximize), 138 Command.SET_SCREEN_ORIENTATION: 139 (POST, /session/$sessionId/orientation), 140 Command.GET_SCREEN_ORIENTATION: 141 (GET, /session/$sessionId/orientation), 142 Command.SINGLE_TAP: 143 (POST, /session/$sessionId/touch/click), 144 Command.TOUCH_DOWN: 145 (POST, /session/$sessionId/touch/down), 146 Command.TOUCH_UP: 147 (POST, /session/$sessionId/touch/up), 148 Command.TOUCH_MOVE: 149 (POST, /session/$sessionId/touch/move), 150 Command.TOUCH_SCROLL: 151 (POST, /session/$sessionId/touch/scroll), 152 Command.DOUBLE_TAP: 153 (POST, /session/$sessionId/touch/doubleclick), 154 Command.LONG_PRESS: 155 (POST, /session/$sessionId/touch/longclick), 156 Command.FLICK: 157 (POST, /session/$sessionId/touch/flick), 158 Command.EXECUTE_SQL: 159 (POST, /session/$sessionId/execute_sql), 160 Command.GET_LOCATION: 161 (GET, /session/$sessionId/location), 162 Command.SET_LOCATION: 163 (POST, /session/$sessionId/location), 164 Command.GET_APP_CACHE: 165 (GET, /session/$sessionId/application_cache), 166 Command.GET_APP_CACHE_STATUS: 167 (GET, /session/$sessionId/application_cache/status), 168 Command.CLEAR_APP_CACHE: 169 (DELETE, /session/$sessionId/application_cache/clear), 170 Command.GET_NETWORK_CONNECTION: 171 (GET, /session/$sessionId/network_connection), 172 Command.SET_NETWORK_CONNECTION: 173 (POST, /session/$sessionId/network_connection), 174 Command.GET_LOCAL_STORAGE_ITEM: 175 (GET, /session/$sessionId/local_storage/key/$key), 176 Command.REMOVE_LOCAL_STORAGE_ITEM: 177 (DELETE, /session/$sessionId/local_storage/key/$key), 178 Command.GET_LOCAL_STORAGE_KEYS: 179 (GET, /session/$sessionId/local_storage), 180 Command.SET_LOCAL_STORAGE_ITEM: 181 (POST, /session/$sessionId/local_storage), 182 Command.CLEAR_LOCAL_STORAGE: 183 (DELETE, /session/$sessionId/local_storage), 184 Command.GET_LOCAL_STORAGE_SIZE: 185 (GET, /session/$sessionId/local_storage/size), 186 Command.GET_SESSION_STORAGE_ITEM: 187 (GET, /session/$sessionId/session_storage/key/$key), 188 Command.REMOVE_SESSION_STORAGE_ITEM: 189 (DELETE, /session/$sessionId/session_storage/key/$key), 190 Command.GET_SESSION_STORAGE_KEYS: 191 (GET, /session/$sessionId/session_storage), 192 Command.SET_SESSION_STORAGE_ITEM: 193 (POST, /session/$sessionId/session_storage), 194 Command.CLEAR_SESSION_STORAGE: 195 (DELETE, /session/$sessionId/session_storage), 196 Command.GET_SESSION_STORAGE_SIZE: 197 (GET, /session/$sessionId/session_storage/size), 198 Command.GET_LOG: 199 (POST, /session/$sessionId/log), 200 Command.GET_AVAILABLE_LOG_TYPES: 201 (GET, /session/$sessionId/log/types), 202 Command.CURRENT_CONTEXT_HANDLE: 203 (GET, /session/$sessionId/context), 204 Command.CONTEXT_HANDLES: 205 (GET, /session/$sessionId/contexts), 206 Command.SWITCH_TO_CONTEXT: 207 (POST, /session/$sessionId/context), 208 Command.FULLSCREEN_WINDOW: 209 (POST, /session/$sessionId/window/fullscreen), 210 Command.MINIMIZE_WINDOW: 211 (POST, /session/$sessionId/window/minimize) 212 }这个类里面定义了所有的selenium操作需要的接口地址(这些接口地址全部封装在浏览器驱动程序中)那么所有的浏览器操作就是通过访问这些接口来实现的其中 Command.GET: (POST, /session/$sessionId/url) 这个地址就是实现访问一个网址的url 我们先记录一下后面有用ok所有的操作对应接口地址我们知道了那么又怎样执行这些接口来达到在浏览器上实现各种操作呢继续看紧接着接口地址定义下面的源码1 def execute(self, command, params): 2 3 Send a command to the remote server. 4 5 Any path subtitutions required for the URL mapped to the command should be 6 included in the command parameters. 7 8 :Args: 9 - command - A string specifying the command to execute. 10 - params - A dictionary of named parameters to send with the command as 11 its JSON payload. 12 13 command_info self._commands[command] 14 assert command_info is not None, Unrecognised command %s % command 15 path string.Template(command_info[1]).substitute(params) 16 if hasattr(self, w3c) and self.w3c and isinstance(params, dict) and sessionId in params: 17 del params[sessionId] 18 data utils.dump_json(params) 19 url %s%s % (self._url, path) 20 return self._request(command_info[0], url, bodydata) 21 22 def _request(self, method, url, bodyNone): 23 24 Send an HTTP request to the remote server. 25 26 :Args: 27 - method - A string for the HTTP method to send the request with. 28 - url - A string for the URL to send the request to. 29 - body - A string for request body. Ignored unless method is POST or PUT. 30 31 :Returns: 32 A dictionary with the servers parsed JSON response. 33 34 LOGGER.debug(%s %s %s % (method, url, body)) 35 36 parsed_url parse.urlparse(url) 37 headers self.get_remote_connection_headers(parsed_url, self.keep_alive) 38 resp None 39 if body and method ! POST and method ! PUT: 40 body None 41 42 if self.keep_alive: 43 resp self._conn.request(method, url, bodybody, headersheaders) 44 45 statuscode resp.status 46 else: 47 http urllib3.PoolManager(timeoutself._timeout) 48 resp http.request(method, url, bodybody, headersheaders) 49 50 statuscode resp.status 51 if not hasattr(resp, getheader): 52 if hasattr(resp.headers, getheader): 53 resp.getheader lambda x: resp.headers.getheader(x) 54 elif hasattr(resp.headers, get): 55 resp.getheader lambda x: resp.headers.get(x) 56 57 data resp.data.decode(UTF-8) 58 try: 59 if 300 statuscode 304: 60 return self._request(GET, resp.getheader(location)) 61 if 399 statuscode 500: 62 return {status: statuscode, value: data} 63 content_type [] 64 if resp.getheader(Content-Type) is not None: 65 content_type resp.getheader(Content-Type).split(;) 66 if not any([x.startswith(image/png) for x in content_type]): 67 68 try: 69 data utils.load_json(data.strip()) 70 except ValueError: 71 if 199 statuscode 300: 72 status ErrorCode.SUCCESS 73 else: 74 status ErrorCode.UNKNOWN_ERROR 75 return {status: status, value: data.strip()} 76 77 # Some of the drivers incorrectly return a response 78 # with no value field when they should return null. 79 if value not in data: 80 data[value] None 81 return data 82 else: 83 data {status: 0, value: data} 84 return data 85 finally: 86 LOGGER.debug(Finished Request) 87 resp.close()可以看到主要是通过execute方法调用_request方法通过urilib3标准库向服务器发送对应操作请求地址进而实现了浏览器各种操作有人会问打开浏览器和操作浏览器实现各种动作是怎么关联的呢其实打开浏览器也是发送请求请求会返回一个sessionid后面操作的各种接口地址你也会发现接口地址中存在一个变量$sessionid那么不难猜测打开浏览器和操作浏览器就是用过sessionid关联到一起达到在同一个浏览器中做操作第二步在浏览其上实现各种操作原理也完成了八、模拟selenium现在我们可以通过下面的一段代码查看一下打开浏览器和访问我的博客首页的请求参数是什么样子的 ------------------------------------ Time : 2019/6/29 9:16 Auth : linux超 File : seleniumWebdriver.py IDE : PyCharm Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! QQ : 28174043qq.com GROUP: 878565760 ------------------------------------ from selenium import webdriver import logging logging.basicConfig(levellogging.DEBUG) # 打印源码中的日志 dr webdriver.Chrome() # 打开浏览器 driver.get(https://www.cnblogs.com/linuxchao/) # 访问我的博客首页输出日志信息DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:55695/session {capabilities: {firstMatch: [{}], alwaysMatch: {browserName: chrome, platformName: any, goog:chromeOptions: {extensions: [], args: []}}}, desiredCapabilities: {browserName: chrome, version: , platform: ANY, goog:chromeOptions: {extensions: [], args: []}}} DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): 127.0.0.1 DEBUG:urllib3.connectionpool:http://127.0.0.1:55695 POST /session HTTP/1.1 200 830 DEBUG:selenium.webdriver.remote.remote_connection:Finished Request DEBUG:selenium.webdriver.remote.remote_connection:POST http://127.0.0.1:51006/session/09d52393b7dfcb45b8bb9101885ce206/url {url: https://www.cnblogs.com/linuxchao/, sessionId: 09d52393b7dfcb45b8bb9101885ce206} DEBUG:urllib3.connectionpool:http://127.0.0.1:51006 POST /session/09d52393b7dfcb45b8bb9101885ce206/url HTTP/1.1 200 72 DEBUG:selenium.webdriver.remote.remote_connection:Finished Request Process finished with exit code 0通过执行结果就很明显明白selenium执行的过程了程序告诉RemoteWebDriver打开一个浏览器(发送post请求带上请求参数)然后再向remote server发送执行浏览器动作的请求那么为了更加深入理解selenium实现自动化测试的过程我们可以自己编写程序模拟一下打开浏览器然后控制浏览器访问我的博客地址的操作过程首先我们需要保持浏览器的驱动程序打开状态然后编写如下代码并执行 ------------------------------------ Time : 2019/6/28 8:52 Auth : linux超 File : test.py IDE : PyCharm Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! QQ : 28174043qq.com GROUP: 878565760 ------------------------------------ import requests # 请求地址(打开浏览器) driver_url http://localhost:9515/session # 打开浏览器的请求参数 driver_value {capabilities: {firstMatch: [{}], alwaysMatch: {browserName: chrome, platformName: any, goog:chromeOptions: {extensions: [], args: []}}}, desiredCapabilities: {browserName: chrome, version: , platform: ANY, goog:chromeOptions: {extensions: [], args: []}}} # 发送求清 response_session requests.post(driver_url, json driver_value) print(response_session.json()) # 访问我的博客的请求地址 这个地址是我们上面记录的地址 url http://localhost:9515/session/response_session.json()[sessionId]/url # 访问我的博客的请求参数 value {url: https://www.cnblogs.com/linuxchao/, sessionId: response_session.json()[sessionId]} response_blog requests.post(url url,json value) print(response_blog.json())执行结果{sessionId: 25144efef880dcce53e4e6f60c342e9d, status: 0, value: {acceptInsecureCerts: False, acceptSslCerts: False, applicationCacheEnabled: False, browserConnectionEnabled: False, browserName: chrome, chrome: {chromedriverVersion: 2.39.562718 (9a2698cba08cf5a471a29d30c8b3e12becabb0e9), userDataDir: C:\\Users\\v-xug\\AppData\\Local\\Temp\\scoped_dir9944_25238}, cssSelectorsEnabled: True, databaseEnabled: False, handlesAlerts: True, hasTouchScreen: False, javascriptEnabled: True, locationContextEnabled: True, mobileEmulationEnabled: False, nativeEvents: True, networkConnectionEnabled: False, pageLoadStrategy: normal, platform: Windows NT, rotatable: False, setWindowRect: True, takesHeapSnapshot: True, takesScreenshot: True, unexpectedAlertBehaviour: , version: 75.0.3770.100, webStorageEnabled: True}} {sessionId: 25144efef880dcce53e4e6f60c342e9d, status: 0, value: None} Process finished with exit code 0上面的返回信息中最重要的信息是sessionId: 25144efef880dcce53e4e6f60c342e9d从代码中你也可以看到访问我的博客地址的url是使用这个参数拼接的因为打开浏览器后后面所有的操作都是基于这个sessionid的你还会看到Chrome浏览器被打开且打开了我的博客地址https://www.cnblogs.com/linuxchao/这就是selenium原理的一个过程了九、最后前面的代码你看不懂也没关系我们再来叙述一下selenium工作的过程1.selenium client(python等语言编写的自动化测试脚本)初始化一个service服务通过Webdriver启动浏览器驱动程序chromedriver.exe2.通过RemoteWebDriver向浏览器驱动程序发送HTTP请求浏览器驱动程序解析请求打开浏览器并获得sessionid如果再次对浏览器操作需携带此id3.打开浏览器绑定特定的端口把启动后的浏览器作为webdriver的remote server3.打开浏览器后所有的selenium的操作(访问地址查找元素等)均通过RemoteConnection链接到remote server然后使用execute方法调用_request方法通过urlib3向remote server发送请求4.浏览器通过请求的内容执行对应动作5.浏览器再把执行的动作结果通过浏览器驱动程序返回给测试脚本最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走这些资料对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴我走过了最艰难的路程希望也能帮助到你凡事要趁早特别是技术行业一定要提升技术功底。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

搜索关键词站长工具定做网站建设

WVP-GB28181-Pro视频点播超时难题深度剖析:从故障定位到彻底根治 【免费下载链接】wvp-GB28181-pro 项目地址: https://gitcode.com/GitHub_Trending/wv/wvp-GB28181-pro 还在为WVP-GB28181-Pro平台中视频点播频繁出现"播放超时"而困扰不已吗&…

张小明 2026/3/7 23:34:02 网站建设

太原网站建设方案推广请将网站首页底部的备案号

Samba服务器问题排查指南 1. 身份验证与账户配置 在使用Samba服务器时,若要绕过域控制器的安全机制,在本地对用户名和密码进行身份验证,即便安全参数设置正确,也必须在Linux计算机上为尝试访问该计算机的用户创建对应的账户。若用户在Windows和Linux系统中的用户名不同,…

张小明 2026/3/7 23:33:54 网站建设

推广型网站如何建站济南网站建设内容设计

文章目录 一、前言 1.1 项目介绍 【1】项目开发背景 【2】设计实现的功能 【3】项目硬件模块组成 【4】设计意义 【5】国内外研究现状 **国内研究现状** **国外研究现状** **技术痛点与用户项目的创新性** **总结** 【6】摘要 1.2 设计思路 1.3 系统功能总结 1.4 开发工具的选择…

张小明 2026/3/7 23:33:46 网站建设

汽车网站开发背景wordpress5.0难用

终极指南:如何用PandasAI实现零代码数据分析 【免费下载链接】pandas-ai 该项目扩展了Pandas库的功能,添加了一些面向机器学习和人工智能的数据处理方法,方便AI工程师利用Pandas进行更高效的数据准备和分析。 项目地址: https://gitcode.co…

张小明 2026/3/9 11:43:35 网站建设

建数据库的网站多少钱自适应网站做多大尺寸

5分钟掌握Android MVVM开发:Saber框架完整实战指南 【免费下载链接】Saber 🏄 帮助你快速使用Android的LiveData与ViewModel,已支持SavedState 项目地址: https://gitcode.com/gh_mirrors/saber2/Saber 还在为Android MVVM架构中的繁琐…

张小明 2026/3/9 11:43:27 网站建设