【Selenium初学记录篇】从零开始

前言

一直想学习自动化测试,但是都没行动,业余时间学习零零碎碎并记录20210402

 

Selenium

  • 目前是软件测试行业最为核心主流的自动化测试架构技术体系
  • Selenium:RobotFramework、airtest、playwright、Appium
  • selenium1.x:这个时候的selenium,使用的是JavaScript注入技术与浏览器打交道。需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。
  • Javascript可以获取并调用DOM的任何元素,自如的进行操作。由此才实现了Selenium的目的:自动化Web操作。这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的Javascript质量高低。
  • selenium2.x:相比于selenium1.x,2.x版本整合了webdriver以及原版selenium。两个项目合二为一,虽然名字还叫selenium,但也可以叫Webdriver。这个版本的selenium是利用浏览器原生的API,封装成一套更加面向对象的Selenium WebDriver API。
  •  
  • SeleniumIDE,早期代表firefox下的插件,支持浏览器的脚本录制与回放,存在于Selenium1和2版本。
  • Selenium+Webdriver,是从Selenium2开始一直延续至今的一套体系。
  • SeleniumIDE4.0版本,支持多浏览器的脚本录制,还是不火。
  • Selenium Grid,可以将线性脚本做到更优越。涉及到分布式概念,可以将原有的自动化测试框架从单体服务器模式转变为M/S(主从节点)形态的分布式架构形式来实现。一般分布式测试框架体系可以结合用例并发的模式来存在。用于结合用户数并发的测试

直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭,安装插件,配置证书之类的)。由于使用的是浏览器原生的API,速度大大提高,而且调用的稳定性交给了浏览器厂商本身,显然是更加科学。然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。

 

WebDriver浏览器驱动

实现代码操作浏览器的插件。实际上,不能算是一个驱动,而是一个基于HTTP网络协议进行数据交互的代理服务。具体对应的浏览器版本于webdriver的对应版本,可以去Selenium官网找。chromdriver可以直接百度。将驱动放/usr/local/bin下

建议关闭谷歌自动更新,便于学习Selenium

cd ~/Library/Google
sudo chown root:wheel GoogleSoftwareUpdate

关闭后重启谷歌浏览器,点击关于,就有个红色感叹号。如下图所示

原理

要通过selenium实现自动化测试,最最主要是需要三种东西:测试需要用的代码、webdriver、浏览器。

① 代码

selenium支持多种语言(java/c#/python/ruby)。测试工程师通过编程语言,调用浏览器对应API实现需要的功能。

② webdriver

webdriver,就像是一个媒介。代码驱动webdriver。上文提过,不同浏览器有不同的webdriver。例如火狐的FirefoxDriver,谷歌的 ChromeDriver。

③ 浏览器

不同的浏览器对应不同的webdriver。

 

从上图,测试代码输入操作给webdriver,webdriver再去控制浏览器,最终达到的效果就是代码实现对浏览器的操作。

【例子】查找元素

以查找元素为例,查看代码与webdriver的交互。以下python为例:

from selenium import webdriver

#创建一个浏览器对象
driver = webdriver.Chrome()

这里driver是webdriver.Chrome()的对象,我们查看webdriver.Chrome()的源码。发现本质是 from .chrome.webdriver import WebDriver as Chrome

从目录名可知这来自chrome的webdriver,再次对这个WebDriver溯源,发现它是继承了一个RemoteWebDriver类。注释的含义是:控制ChromeDriver并允许驱动浏览器。

class WebDriver(RemoteWebDriver):
    """
    Controls the ChromeDriver and allows you to drive the browser.

    You will need to download the ChromeDriver executable from
    http://chromedriver.storage.googleapis.com/index.html
    """

    def __init__(self, executable_path="chromedriver", port=0,
                 options=None, service_args=None,
                 desired_capabilities=None, service_log_path=None,
                 chrome_options=None, keep_alive=True):
        """
        Creates a new instance of the chrome driver.

        Starts the service and then creates new instance of chrome driver.

        :Args:
         - executable_path - path to the executable. If the default is used it assumes the executable is in the $PATH
         - port - port you would like the service to run, if left as 0, a free port will be found.
         - options - this takes an instance of ChromeOptions
         - service_args - List of args to pass to the driver service
         - desired_capabilities - Dictionary object with non-browser specific
           capabilities only, such as "proxy" or "loggingPref".
         - service_log_path - Where to log information from the driver.
         - chrome_options - Deprecated argument for options
         - keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive.
        """
    

再次对继承的RemoteWebDriver类溯源。

发现其是:selenium.webdriver.remote.webdriver.WebDriver。

class WebDriver(object):
    """
    Controls a browser by sending commands to a remote server.
    This server is expected to be running the WebDriver wire protocol
    as defined at
    https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol

    :Attributes:
     - session_id - String ID of the browser session started and controlled by this WebDriver.
     - capabilities - Dictionaty of effective capabilities of this browser session as returned
         by the remote server. See https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities
     - command_executor - remote_connection.RemoteConnection object used to execute commands.
     - error_handler - errorhandler.ErrorHandler object used to handle errors.
    """

    _web_element_cls = WebElement

    def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub',
                 desired_capabilities=None, browser_profile=None, proxy=None,
                 keep_alive=False, file_detector=None, options=None):
        """
        Create a new driver that will issue commands using the wire protocol.

        :Args:
         - command_executor - Either a string representing URL of the remote server or a custom
             remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'.
         - desired_capabilities - A dictionary of capabilities to request when
             starting the browser session. Required parameter.
         - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object.
             Only used if Firefox is requested. Optional.
         - proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will
             be started with given proxy settings, if possible. Optional.
         - keep_alive - Whether to configure remote_connection.RemoteConnection to use
             HTTP keep-alive. Defaults to False.
         - file_detector - Pass custom file detector object during instantiation. If None,
             then default LocalFileDetector() will be used.
         - options - instance of a driver options.Options class
        """

注释的含义是:通过向远程服务器发送命令来控制浏览器。 该服务器应该运行WebDriver有线协议。

一个名为command_executor的对象执行了execute方法。 名为command_executor的对象是RemoteConnection类的对象。

并且这个对象是在新建selenium.webdriver.remote.webdriver.WebDriver类对象的时候就完成赋值的self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive)。

结合selenium.webdriver.remote.webdriver.WebDriver类的类注释来看:WebDriver类的功能是通过给一个remote server发送指令来控制浏览器。而这个remote server是一个运行WebDriver wire protocol的server。而RemoteConnection类就是负责与Remote WebDriver server的连接的类。 可以注意到有这么一个新建WebDriver类的对象时候的参数command_executor。

默认值等于'http://127.0.0.1:4444/wd/hub'。这个值表示的是访问server的URL。因此这个值作为了RemoteConnection类的构造方法的参数。因为要连接remote server,URL是必须的。 

 

指令的URL部分包含了几个组成部分:

  • HTTP请求方法。WebDriver wire protocol中定义的指令是符合RESTful规范的,通过不同请求方法对应不同的指令操作。
  • sessionId. sessionId表示了remote server和浏览器的一个会话,指令通过这个会话变成对于浏览器的一个操作。
  • element 这一部分用来表示具体的指令。

selenium.webdriver.remote.command.Command类里的常量指令又在各个具体的类似find_elements的实例方法中作为execute方法的参数来使用。

这样就实现了selenium.webdriver.remote.webdriver.WebDriver类中实现各种操作的实例方法与WebDriver wire protocol中定义的指令的一一对应。

selenium.webdriver.remote.webelement.WebElement中各种在WebElement上的操作也是用类似的原理实现的。实例方法execute的另一个参数params则是用来保存指令的参数的,这个参数将转化为JSON格式,作为HTTP请求的body发送到remote server。

remote server在执行完对浏览器的操作后得到的数据将作为HTTP Response的body返回给测试代码,测试代码经过解析处理后得到想要的数据。

据说搞懂webdriver的底层原理,才敢说自己懂自动化!

小编在学习的时候,随手做个记录,初学记录,欢迎留言指正~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小慌慌

感谢博友的鼓励,快乐分享~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值