前言
Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。
主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。
测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本(这里主要是针对selenium ide)
一、selenium历程
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是一个分布式实现自动化测试的工具
那么今天我们就要说说selenium3(selenium webdriver)的工作原理,下面简称selenium(以上具体时间可能不太准确,我也是通过网络资料了解到的,抛砖引玉^-^)
二、selenium原理
我们使用Selenium实现自动化测试,主要需要3个东西
1.测试脚本,可以是python,java编写的脚本程序(也可以叫做client端)
2.浏览器驱动, 这个驱动是根据不同的浏览器开发的,不同的浏览器使用不同的webdriver驱动程序且需要对应相应的浏览器版本,比如:geckodriver.exe(chrome)
3.浏览器,目前selenium支持市面上大多数浏览器,如:火狐,谷歌,IE等
三、selenium脚本
先看一个简单的代码
"""
from selenium import webdriver
dr = webdriver.Chrome() # 打开浏览器
执行上述代码,我们会发现程序打开了Chrome浏览器(前提:你已经正确配置了chrome的驱动和对应版本)
那么selenium是如何实现这个过程的呢?ok,我们今天就通过分析源码的方式来理解selenium的工作原理
四、源码分析
查看weddriver源码(按住Ctrl键,鼠标点击Chrome)
C:\Python36\Lib\site-packages\selenium\webdriver\chrome\webdriver.py
1 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_path="chromedriver", port=0,
10 options=None, service_args=None,
11 desired_capabilities=None, service_log_path=None,
12 chrome_options=None, keep_alive=True):
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, stacklevel=2)
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 port=port,
47 service_args=service_args,
48 log_path=service_log_path)
49 self.service.start()
50
51 try:
52 RemoteWebDriver.__init__(
53 self,
54 command_executor=ChromeRemoteConnection(
55 remote_server_addr=self.service.service_url,
56 keep_alive=keep_alive),
57 desired_capabilities=desired_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.py
1 def start(self):
2 """
3 Starts the Service.
4
5 :Exceptions:
6 - WebDriverException : Raised either when it can't start the service
7 or when it can't connect to the service
8 """
9 try:
10 cmd = [self.path]
11 cmd.extend(self.command_line_args())
12 self.process = subprocess.Popen(cmd, env=self.env,
13 close_fds=platform.system() != 'Windows',
14 stdout=self.log_file,
15 stderr=self.log_file,
16 stdin=PIPE)
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\