• Selenium WebDriver - 其它



    一、上手

    如果您是Selenium的新手,我们有一些资源可以帮助您立即了解最新情况。

    Selenium通过使用WebDriver支持市场上所有主要浏览器的自动化。
    WebDriver是一种API和协议,它定义了一个语言中立的界面,用于控制Web浏览器的行为。
    每个浏览器都有一个特定的WebDriver实现,称为驱动程序
    驱动程序是负责委托给浏览器的组件,并处理Selenium和浏览器之间的通信。

    这种分离是有意识地让浏览器供应商对其浏览器的实现负责的努力的一部分。
    Selenium尽可能使用这些第三方驱动程序,但也为不现实的情况提供由项目维护的自己的驱动程序。

    Selenium框架通过一个面向用户的界面将所有这些部分联系在一起,使不同的浏览器后端能够透明地使用,从而实现跨浏览器和跨平台自动化。

    Selenium设置与其他商业工具的设置完全不同。
    在开始编写Selenium代码之前,您必须为您选择的语言安装语言绑定库、您要使用的浏览器以及该浏览器的驱动程序。

    按照下面的链接开始使用Selenium WebDriver。

    如果您希望从低代码/录制和播放工具开始,请检查 Selenium IDE

    一旦你把事情做好,如果你想扩大你的测试,看看 Selenium 网格


    二、Driver Sessions

    启动和停止会话用于打开和关闭浏览器。


    创建会话

    创建一个新会话对应于W3C命令的新建会话

    会话是通过初始化一个新的Driver类对象自动创建的。

    每种语言都允许使用来自以下类之一(或等效类)的参数创建会话:

    • 选项来描述您想要的会话类型;默认值用于本地,但这是远程所必需的
    • 某种形式的HTTP客户端配置(实现因语言而异)
    • 听众

    本地驱动

    启动本地驱动程序的主要唯一参数包括有关在本地计算机上启动所需驱动程序服务的信息。

    • 服务对象仅适用于本地驱动程序并提供有关浏览器驱动程序的信息

    三、支持的浏览器

    每个浏览器都具有自定义功能和独特的功能。


    Chrome特定功能

    这些是特定于GoogleChrome浏览器的功能和特性。


    Edge 特定功能

    这些是特定于Microsoft Edge浏览器的功能和特性。


    Firefox特定功能

    这些是特定于Mozilla Firefox浏览器的功能和特性。


    IE特定功能

    这些是特定于Microsoft Internet Explorer浏览器的功能和特性。


    Safari特定功能

    这些是苹果Safari浏览器特有的功能和特性。


    四、等待策略

    也许浏览器自动化最常见的挑战是确保Web应用程序处于按需执行特定Selenium命令的状态。
    这些进程通常以竞争条件告终,有时浏览器首先进入正确的状态(事情按预期工作),有时Selenium代码首先执行(事情按预期工作)。
    这是不稳定测试的主要原因之一。

    所有导航命令等待特定的readyState值 基于页面加载策略(the 在驱动程序将控制权返回给代码之前,要等待的默认值是"complete")。

    readyState关心加载超文本标记语言定义的资产, 但加载的JavaScript资产通常会导致网站发生变化, 并且需要交互的元素可能还没有出现在页面上 当代码准备好执行下一个Selenium命令时。

    类似地,在许多单页应用程序中,元素是动态获取的 添加到页面或根据单击更改可见性。
    一个元素必须同时存在和 显示在页面上 为了让Selenium 与之互动。

    以这个页面为例:https://www.selenium.dev/selenium/web/dynamic.html
    单击“添加框!”按钮时,会创建一个不存在的“div”元素。
    单击“显示新输入”按钮时,会显示一个隐藏的文本字段元素。
    在这两种情况下,转换都需要几秒钟。
    如果Selenium代码要单击其中一个按钮并与生成的元素交互, 它将在该元素准备好并失败之前执行此操作。

    许多人转向的第一个解决方案是添加一个睡眠语句来暂停代码执行一段时间。
    因为代码不能确切知道它需要等待多长时间,所以当它睡眠时间不够长时,这可能会失败。
    或者,如果该值设置得太高,并且在需要的每个地方都添加了一个睡眠语句,会话的持续时间可能会变得令人望而却步。

    Selenium提供了两种更好的同步机制。


    隐式等待

    Selenium有一种自动等待元素的内置方法,称为隐式等待
    隐式等待值可以设置为超时 浏览器选项中的功能,或使用驱动程序方法(如下所示)。

    这是一个全局设置,适用于整个会话的每个元素位置调用。
    默认值为0,这意味着如果没有找到该元素,它将 立即返回错误。
    如果设置了隐式等待,驱动程序将等待 返回错误之前提供值的持续时间。
    请注意,一旦 元素定位,驱动程序将返回元素引用,代码将继续执行, 因此,较大的隐式等待值不一定会增加会话的持续时间。

    警告:不要混合隐式和显式等待。
    这样做可能会导致不可预测的等待时间。
    例如,设置隐式等待10秒和显式等待15秒可能会导致20秒后超时。

    使用隐式等待解决我们的示例如下所示:

    driver.implicitly_wait(2)
    

    在GitHub上查看完整示例


    显式等待

    显式等待是添加到代码中的循环,它轮询应用程序以获取特定条件,以便在退出循环并继续执行代码中的下一个命令之前评估为true。
    如果在指定的超时值之前没有满足条件,则代码将给出超时错误。
    由于有许多方法可以让应用程序不处于所需的状态,因此显式等待是在每个需要它的地方指定要等待的确切条件的绝佳选择。
    另一个不错的功能是,默认情况下,Selenium等待类会自动等待指定元素的存在。

    此示例将等待的条件显示为lambda
    Python还支持 预期条件

    wait = WebDriverWait(driver, timeout=2)
    wait.until(lambda d : revealed.is_displayed())
    

    在GitHub上查看完整示例


    定制化

    等待类可以使用各种参数来实例化,这些参数将改变评估条件的方式。

    这可以包括:

    • 更改评估代码的频率(轮询间隔)
    • 指定应自动处理哪些异常
    • 更改总超时长度
    • 自定义超时消息

    例如,如果元素not interactable错误默认重试,那么我们可以 在执行的代码中添加对方法的操作(我们只需要 确保代码成功时返回true):

    errors = [NoSuchElementException, ElementNotInteractableException]
    wait = WebDriverWait(driver, timeout=2, poll_frequency=.2, ignored_exceptions=errors)
    wait.until(lambda d : revealed.send_keys("Displayed") or True)
    

    在GitHub上查看完整示例


    五、双向功能

    Selenium正在与浏览器供应商合作创建 WebDriver双向协议 作为提供使用双向的稳定、跨浏览器API的一种手段 对浏览器自动化和测试都有用的功能。
    在此之前,寻求此功能的用户必须依赖CDP(ChromeDevTools协议) 所有的挫折和限制。

    严格请求/响应命令的传统WebDriver模型将通过WebSockets将事件从用户代理流式传输到控制软件的能力进行补充,更好地匹配浏览器DOM的事件性质。

    由于将测试绑定到任何浏览器的特定版本都不是一个好主意,Selenium项目建议尽可能使用WebDriver BiDi。

    在规范制定过程中,浏览器供应商正在并行实施 该WebDriver双向协议
    请参阅web平台测试仪表板 看看浏览器供应商的进展情况。
    Selenium正在努力跟上浏览器供应商的步伐,并已开始实施W3C BiDi API。
    目标是确保API符合W3C并在不同的语言绑定之间保持统一。

    但是,在规范和相应的Selenium实现完成之前,CDP提供了许多有用的东西。
    Selenium提供了一些使用CDP的有用帮助类。


    1、Chrome开发工具

    许多浏览器都提供“开发工具”——一组与浏览器集成的工具,开发人员可以使用这些工具来调试网络应用程序并探索其页面的性能。
    谷歌浏览器的开发工具使用了一种称为Chrome开发工具协议(简称“CDP”)的协议。
    顾名思义,这不是为测试而设计的,也不是为了有一个稳定的应用编程接口,所以功能高度依赖于浏览器的版本。

    WebDriver双向协议是下一代的 W3C WebDriver协议,旨在提供所有浏览器实现的稳定API,但尚未完成。
    在此之前,Selenium提供访问 实现它的浏览器(如谷歌Chrome或Microsoft Edge的CDP Firefox),允许您以有趣的方式增强测试。
    您可以做的一些示例 用它做下面给出。


    使用SeleniumChrome开发工具的方法

    有三种不同的方法可以访问SeleniumChrome开发工具。
    如果你在网上寻找其他例子,你可能会看到这些混合和匹配。

    • 用户的第一个选择是CDP端点
      它只适用于最简单的事情(设置状态,获取基本信息),而您 必须知道域、方法和键值对的“魔术字符串”。
      对于基本需求,这可能比其他选项更简单。
      这些方法只是暂时支持的。
    • 与仅使用端点相比,CDP API是一种改进,因为您可以设置 异步做事。
      您可以访问支持的类,而不是字符串和映射, 代码中的方法和参数。
      这些方法也只是暂时支持的。
    • 应该尽可能使用BiDi API选项,因为它 完全抽象出实现细节,并将与CDP或WebDriver-BiDi一起使用 当Selenium 离开CDP时。

    价值有限的示例

    有许多常用的使用CDP的例子,它们的实用价值有限。

    • 地理位置-几乎所有站点都使用IP地址来确定物理位置,因此设置模拟地理位置很少能达到预期的效果。
    • 覆盖设备指标-Chrome提供了一个很棒的API来设置移动仿真 在Options类中,这通常优于尝试使用CDP执行此操作。

    查看这些文档中的示例,了解做其他有用事情的方法:

    • ChromeDevTools协议端点
      Google提供了一个可以直接访问的/cdp/execute端点,每个Selenium绑定都提供了一个方法,允许您将CDP域作为字符串传递,并将所需参数作为简单的Map传递。
    • Chrome开发工具协议API
      每个Selenium绑定都会为各种CDP域和特性动态生成类和方法;这些绑定与Chrome的特定版本相关联。
    • Chrome开发者工具协议
      这些示例目前使用CDP实现,但当使用WebDriver-BiDi重新实现该功能时,相同的代码应该可以工作。

    ChromeDevTools协议端点

    Google提供了一个可以直接访问的/cdp/execute端点,每个Selenium绑定都提供了一个方法,允许您将CDP域作为字符串传递,并将所需参数作为简单的Map传递。

    这些方法最终会被删除。
    建议使用WebDriver-BiDiWebDriver Bidi API 尽可能确保未来兼容性的方法。


    用法

    一般来说,您应该更喜欢使用CDP API而不是这种方法, 但有时语法更简洁或更简单。

    限制包括:

    • 它仅适用于仅限于设置或获取信息的用例;任何实际的异步交互都需要另一个实现
    • 您必须知道域和密钥的完全正确的“魔法字符串”
    • 对Chrome的更新可能会更改所需的参数

    例子

    设置Cookie

    另一种实现可以在CDP API Set Cookie

        cookie = {'name': 'cheese',
                  'value': 'gouda',
                  'domain': 'www.selenium.dev',
                  'secure': True}
    
        driver.execute_cdp_cmd('Network.setCookie', cookie)
    

    在GitHub上查看完整示例


    绩效指标

    另一种实现可以在CDP API性能指标

        driver.execute_cdp_cmd('Performance.enable', {})
    
        metric_list = driver.execute_cdp_cmd('Performance.getMetrics', {})["metrics"]
    

    在GitHub上查看完整示例


    基本认证

    替代实现可以在CDP API基本身份验证BiDi API基本认证

        driver.execute_cdp_cmd("Network.enable", {})
    
        credentials = base64.b64encode("admin:admin".encode()).decode()
        headers = {'headers': {'authorization': 'Basic ' + credentials}}
    
        driver.execute_cdp_cmd('Network.setExtraHTTPHeaders', headers)
    

    在GitHub上查看完整示例


    Chrome开发工具协议API

    每个Selenium绑定都会为各种CDP域和特性动态生成类和方法;这些绑定与Chrome的特定版本相关联。

    虽然Selenium 4提供对Chrome开发工具协议(CDP)的直接访问,但这些 方法最终会被删除。
    建议使用WebDriver Bidi API 尽可能确保未来兼容性的方法。


    用法

    如果您的用例已由WebDriver Bidi或 对于BiDi API,您应该使用这些实现而不是这个。
    通常,您应该更喜欢这种方法,而不是使用CDP端点执行, 尤其是在Ruby中。


    例子

    设置Cookie

    另一种实现可以在CDP端点设置Cookie

    因为Python需要在此示例中使用异步方法,所以在 CDP端点集Cookie可能更容易。

    async with driver.bidi_connection() as connection:
         execution = connection.devtools.network.set_cookie(
             name="cheese",
             value="gouda",
             domain="www.selenium.dev",
             secure=True
         )
    
         await connection.session.execute(execution)
    

    在GitHub上查看完整示例


    绩效指标

    可以在CDP端点性能指标中找到替代实现

    因为Python需要在此示例中使用异步方法,所以在 CDP端点性能指标可能更容易。

    async with driver.bidi_connection() as connection:
         await connection.session.execute(connection.devtools.performance.enable())
    
         metric_list = await connection.session.execute(connection.devtools.performance.get_metrics())
    

    在GitHub上查看完整示例


    基本认证

    可以在以下位置找到替代实现 CDP端点基本认证BiDi API基本认证

    因为Python需要在此示例中使用异步方法,所以在 CDP端点基本身份验证可能更容易。

    async with driver.bidi_connection() as connection:
        await connection.session.execute(connection.devtools.network.enable())
    
        credentials = base64.b64encode("admin:admin".encode()).decode()
        auth = {'authorization': 'Basic ' + credentials}
    
        await connection.session.execute(connection.devtools.network.set_extra_http_headers(Headers(auth)))
    

    在GitHub上查看完整示例


    控制台日志

    因为读取控制台日志需要设置事件侦听器, 这不能通过CDP端点实现来完成 可以在以下位置找到替代实现 BiDi API控制台日志和错误WebDriver BiDi控制台日志

    使用BiDi API控制台日志和错误实现

    添加示例


    JavaScript异常

    类似于控制台日志,但这会侦听实际的javascript异常,而不仅仅是记录的错误 可以在以下位置找到替代实现 BiDi API JavaScript异常WebDriver BiDi JavaScript异常

    使用BiDi API JavaScript异常实现

    添加示例


    下载完成

    在继续之前等待下载完成。
    因为获取下载状态需要设置侦听器,所以这不能通过CDP端点实现来完成。

    添加示例


    Chrome开发者工具协议

    这些示例目前使用CDP实现,但当使用WebDriver-BiDi重新实现该功能时,相同的代码应该可以工作。


    用法

    以下API列表将随着Selenium的增长而增长 项目通过支持现实世界的用例来工作。
    如果有 是您想看到的附加功能,请提出 功能要求

    由于这些示例使用WebDriver-Bidi协议重新实现,它们将 移动到WebDriver Bidi页面。


    例子

    基本认证

    一些应用程序使用浏览器身份验证来保护页面。
    过去在URL中处理它们很常见,但浏览器不再支持此功能。
    使用BiDi,您现在可以在必要时提供凭据

    可以在以下位置找到替代实现 CDP端点基本认证CDP API基本认证

    可以在以下位置找到替代实现 CDP端点基本认证


    引脚脚本

    这在远程服务器上执行时特别有用。
    例如,每当您检查元素的可见性时,或者每当您使用经典的get属性方法时,Selenium正在将js文件的内容发送到脚本执行端点。
    这些文件每个大约50kB,加起来。


    突变观察

    突变观察是当DOM中的特定元素发生DOM突变时通过WebDriver BiDi捕获事件的能力。

    async with driver.bidi_connection() as session:
        log = Log(driver, session)
    

    在GitHub上查看完整示例


    控制台日志和错误

    监听console.log事件并注册回调以处理该事件。

    CDP API控制台日志WebDriver BiDi控制台日志

    async with driver.bidi_connection() as session:
         log = Log(driver, session)
    
         async with log.add_listener(Console.ALL) as messages:
    

    在GitHub上查看完整示例


    JavaScript异常

    监听JS异常并注册回调以处理异常详细信息。

    async with driver.bidi_connection() as session:
        log = Log(driver, session)
    
        async with log.add_js_error_listener() as messages:
    

    在GitHub上查看完整示例


    网络拦截

    请求和响应都可以被记录或转换。


    响应信息

    响应变换

    请求拦截

    2、双向API(符合W3C)

    以下API列表将随着WebDriver双向协议的增长而增长 和浏览器供应商实现相同。
    此外,Selenium将尝试支持内部使用W3C BiDi协议API组合的实际用例。

    如果您想看到其他功能,请提出 功能要求


    六、支持功能

    支持类提供可选的更高级别的功能。

    Selenium的核心库试图成为低级和非固执己见的。
    每种语言中的支持类都为常见的交互提供了固执己见的包装器,可用于简化某些行为。


    1、以预期条件等待

    这些是用来描述需要等待什么的类。

    预期条件与显式等待一起使用。
    不是定义要使用lambda执行的代码块,而是预期的 可以创建条件方法来表示等待的常见事物。
    一些 方法将定位器作为参数,其他方法将元素作为参数。

    这些方法可以包括以下条件:

    • 元素存在
    • 元素陈旧
    • 元素可见
    • 文本可见
    • 标题包含指定值

    预期条件文档

    添加示例


    2、命令侦听器

    这些允许您在每次发送特定Selenium命令时执行自定义操作

    添加示例


    3、使用颜色

    作为测试的一部分,你偶尔会想验证一些东西的颜色;问题是网络上的颜色定义不是恒定的。
    如果有一种简单的方法来比较一种颜色的十六进制表示和一种颜色的RGB表示,或者一种颜色的RGBA表示和一种颜色的HSLA表示,那不是很好吗?

    别担心。
    有一个解决方案:颜色类!

    首先,您需要导入类:

    from selenium.webdriver.support.color import Color
      
    

    您现在可以开始创建颜色对象。
    每个颜色对象都需要从您的颜色的字符串表示中创建。
    支持的颜色表示是:

    HEX_COLOUR = Color.from_string('#2F7ED8')
    RGB_COLOUR = Color.from_string('rgb(255, 255, 255)')
    RGB_COLOUR = Color.from_string('rgb(40%, 20%, 40%)')
    RGBA_COLOUR = Color.from_string('rgba(255, 255, 255, 0.5)')
    RGBA_COLOUR = Color.from_string('rgba(40%, 20%, 40%, 0.5)')
    HSL_COLOUR = Color.from_string('hsl(100, 0%, 50%)')
    HSLA_COLOUR = Color.from_string('hsla(100, 0%, 50%, 0.5)')
    

    Color类还支持所有基本颜色定义 指定于 http://www.w3.org/TR/css3-color/#html4.

    BLACK = Color.from_string('black')
    CHOCOLATE = Color.from_string('chocolate')
    HOTPINK = Color.from_string('hotpink')
    

    有时,如果元素上没有设置颜色,浏览器会返回“透明”的颜色值。
    Color类也支持这一点:

    TRANSPARENT = Color.from_string('transparent')
    

    您现在可以安全地查询元素以获取其颜色/背景颜色,因为您知道任何响应都将被正确解析并转换为有效的Color对象:

    login_button_colour = Color.from_string(driver.find_element(By.ID,'login').value_of_css_property('color'))
    
    login_button_background_colour = Color.from_string(driver.find_element(By.ID,'login').value_of_css_property('background-color'))
    

    然后,您可以直接比较颜色对象:

    assert login_button_background_colour == HOTPINK
      
    

    或者,您可以将颜色转换为以下格式之一并执行静态验证:

    assert login_button_background_colour.hex == '#ff69b4'
    assert login_button_background_colour.rgba == 'rgba(255, 105, 180, 1)'
    assert login_button_background_colour.rgb == 'rgb(255, 105, 180)'
      
    

    颜色不再是问题。


    4、使用选择列表元素

    与其他元素相比,选择列表具有特殊的行为。

    Select对象现在将为您提供一系列命令 允许您与元素的类型。


    单选

    这是标准的下拉对象,其中可以选择一个且只能选择一个选项。

    <select name="selectomatic">
        <option selected="selected" id="non_multi_option" value="one">Oneoption>
        <option value="two">Twooption>
        <option value="four">Fouroption>
        <option value="still learning how to count, apparently">Still learning how to count, apparentlyoption>
    select>
    

    多选

    此选择列表允许一次选择和取消选择多个选项。
    这仅适用于具有multiple属性的元素,然后使用它来初始化一个Select对象。
    请注意,从Selenium 4.5开始,如果禁用元素中所有选项的列表:

    option_list = select.options
    

    在GitHub上查看完整示例


    选定选项

    获取