[跟着官方文档学Selenium][学习笔记][九][WebDriver的双向协议]

举报
John2021 发表于 2022/04/04 16:19:26 2022/04/04
【摘要】 Selenium正在与浏览器供应商合作创建WebDriver双向协议,作为一种提供稳定的跨浏览器API的方法,该API使用双向协议处理各种浏览器的通用自动化以及特定测试的需求。在此之前,寻求此功能的用户必须忍受当前实现的全部问题和局限。严格限制请求响应命令的传统WebDriver模型,将从user agent转变为基于WebSockets的软件控制,通过这样完善流事件的能力,以便更好地匹配浏...

Selenium正在与浏览器供应商合作创建WebDriver双向协议,作为一种提供稳定的跨浏览器API的方法,该API使用双向协议处理各种浏览器的通用自动化以及特定测试的需求。在此之前,寻求此功能的用户必须忍受当前实现的全部问题和局限。
严格限制请求响应命令的传统WebDriver模型,将从user agent转变为基于WebSockets的软件控制,通过这样完善流事件的能力,以便更好地匹配浏览器DOM地事件性质。
因为将测试受限于特定浏览器的特定版本是个坏主意,Selenium项目建议尽可能使用WebDriver BiDi。然而,在规范完成之前,CDP提供了许多有用的东西。为了帮助保持测试的独立性和可移植性,Selenium提供了一些有用的辅助类。目前,这些应用程序使用CDP,但我们将尽快提供WebDriver Bidi的实现。

Chrome开发工具

虽然Selenium 4提供了对Chrome DevTools Protocol(CDP)的直接访问,但是仍非常鼓励您使用WebDriver Bidi APIs代替
许多浏览器都提供开发者工具-一组与浏览器集成的工具,开发人员可以用其调试Web应用程序并探索其页面的性能。谷歌浏览器开发工具(使用一种称为Chrome DevTools Protocol)简称CDP的协议。顾名思义,这不是为测试而设计的,而并没有一个稳定的API,所以它的功能高度依赖于浏览器的版本。
WebDriver Bidi是W3C WebDriver的下一代协议,旨在提供由所有浏览器实现稳定的API,但尚未完成。在此之前,Selenium提供了通过CDP实现的方式 (诸如Google Chrome或Microsoft Edge,以及Firefox),允许您以有趣的方式增强测试。下面给出了实际使用的例子。

模拟地理位置

一些应用程序在不同的位置具有不同的特性和功能。自动化此类应用程序很难,因为很难使用Selenium在浏览器中模拟地理位置。但是在Devtools的帮助下,我们可以轻易模拟他们。下面的代码片段演示了这一点。

import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v97.emulation.Emulation;
import org.openqa.selenium.edge.EdgeDriver;

import java.util.Optional;


public class demo1
{
    public static void main(String[] args)
    {
        EdgeDriver webDriver = new EdgeDriver();
        DevTools devTools=webDriver.getDevTools();
        devTools.createSession();
        devTools.send(Emulation.setGeolocationOverride(Optional.of(53.5043),
                                                        Optional.of(13.4501),
                                                        Optional.of(1)));
        webDriver.get("https://my-location.org/");
    }
}

通过远程WebDriver模拟地理位置

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.v97.emulation.Emulation;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Optional;

public class demo2
{
    public static void main(String[] args) throws MalformedURLException
    {
        EdgeOptions edgeOptions = new EdgeOptions();
        WebDriver webDriver = new RemoteWebDriver(new URL("<grid-url>"),edgeOptions);
        webDriver = new Augmenter().augment(webDriver);

        DevTools devTools = ((HasDevTools) webDriver).getDevTools();
        devTools.createSession();

        devTools.send(Emulation.setGeolocationOverride(Optional.of(52.5043),
                Optional.of(13.4501),
                Optional.of(1)));
        webDriver.get("https://my-location.org/");
    }
}

覆盖设备模式

使用Selenium与CDP的集成,可以覆盖当前设备模式并模拟新模式。Width,height,mobile和deviceScaleFactor是必需的参数。可选参数包括scale,screenWidth,screenHeight,positionX,positionY,dontSetVisible,screenOrientation,viewport和displayFeature。

import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v97.emulation.Emulation;
import org.openqa.selenium.edge.EdgeDriver;

import java.util.Optional;

public class demo3
{
    public static void main(String[] args)
    {
        EdgeDriver edgeDriver = new EdgeDriver();
        DevTools devTools=edgeDriver.getDevTools();
        devTools.createSession();
        // iPhone 11 Pro dimensions
        devTools.send(Emulation.setDeviceMetricsOverride(375,
                812,
                50,
                true,
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty()));
        edgeDriver.get("https://www.selenium.dev");
        edgeDriver.quit();
    }
}

Collect Performance Metrics

在应用导航的期间收集性能数据

import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v97.performance.Performance;
import org.openqa.selenium.devtools.v97.performance.model.Metric;
import org.openqa.selenium.edge.EdgeDriver;

import java.util.List;
import java.util.Optional;

public class performanceMetricsExample
{
    public static void main(String[] args)
    {
        EdgeDriver webDriver = new EdgeDriver();
        DevTools devTools=webDriver.getDevTools();
        devTools.createSession();
        devTools.send(Performance.enable(Optional.empty()));
        List<Metric> metricList = devTools.send(Performance.getMetrics());

        webDriver.get("https://www.baidu.com");
        webDriver.quit();

        for (Metric m : metricList)
        {
            System.out.println(m.getName()+" = "+m.getValue());
        }
    }
}

双向接口

以下这些API列表随着Selenium项目通过支持真实用例而增长。

Register Basic Auth

某些应用程序使用浏览器身份验证来保护页面。使用Selenium,可以在出现基本身份验证凭据时自动输入它们。

import org.openqa.selenium.HasAuthentication;
import org.openqa.selenium.UsernameAndPassword;
import org.openqa.selenium.edge.EdgeDriver;

import java.net.URI;
import java.util.function.Predicate;

public class registerBasicAuth
{
    public static void main(String[] args)
    {
        EdgeDriver edgeDriver = new EdgeDriver();
        Predicate<URI> uriPredicate = uri -> uri.getHost().contains("your-domain.com");
        ((HasAuthentication) edgeDriver).register(uriPredicate, UsernameAndPassword.of("username", "password"));
        edgeDriver.get("https://your-domain.com/login");
    }
}

Listen to console.log events

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

import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v97.log.Log;
import org.openqa.selenium.edge.EdgeDriver;

public class listenToConsole
{
    public static void main(String[] args)
    {
        EdgeDriver driver = new EdgeDriver();
        DevTools devTools = driver.getDevTools();
        devTools.createSession();
        devTools.send(Log.enable());
        devTools.addListener(Log.entryAdded(),
                logEntry -> {
                    System.out.println("log: "+logEntry.getText());
                    System.out.println("level: "+logEntry.getLevel());
                });
        driver.get("http://the-internet.herokuapp.com/broken_images");
        driver.quit();
    }
}

Listen to JS Exceptions

监听JS Exceptions并注册回调以处理Exception

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptException;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.edge.EdgeDriver;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class listenToJS
{
    public static void main(String[] args)
    {
        EdgeDriver driver = new EdgeDriver();
        DevTools devTools = driver.getDevTools();
        devTools.createSession();

        List<JavascriptException> jsExceptionsList = new ArrayList<>();
        Consumer<JavascriptException> addEntry = jsExceptionsList::add;
        devTools.getDomains().events().addJavascriptExceptionListener(addEntry);

        driver.get("<your site url>");

        WebElement link2click = driver.findElement(By.linkText("<your link text>"));
        ((JavascriptExecutor) driver).executeScript("arguments[0].setAttribute(arguments[1], arguments[2]);",
                link2click, "onclick", "throw new Error('Hello, world!')");
        link2click.click();

        for (JavascriptException jsException : jsExceptionsList) {
            System.out.println("JS exception message: " + jsException.getMessage());
            System.out.println("JS exception system information: " + jsException.getSystemInformation());
            jsException.printStackTrace();
        }
    }
}

Network Interception

如果要捕获进入浏览器的网络事件并希望对其进行操作,则可以使用以下示例进行操作。

import com.google.common.net.MediaType;
import junit.framework.TestCase;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Assertions;
import org.openqa.selenium.devtools.NetworkInterceptor;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.remote.http.Route;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.devtools.HasDevTools;
import org.openqa.selenium.devtools.NetworkInterceptor;
import org.openqa.selenium.remote.http.Contents;
import org.openqa.selenium.remote.http.Filter;
import org.openqa.selenium.remote.http.HttpResponse;
import org.openqa.selenium.remote.http.Route;

import static org.openqa.selenium.remote.http.Contents.utf8String;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.is;

public class networkInterception
{
    public static void main(String[] args)
    {
        WebDriver driver = new EdgeDriver();
        NetworkInterceptor interceptor = new NetworkInterceptor(
                driver,
                Route.matching(req -> true)
                        .to(() -> req -> new HttpResponse()
                                .setStatus(200)
                                .addHeader("Content-Type", MediaType.HTML_UTF_8.toString())
                                .setContent(utf8String("Creamy, delicious cheese!"))));

        driver.get("https://example-sausages-site.com");

        String source = driver.getPageSource();

        assertThat(source, CoreMatchers.containsString("delicious cheese!"));

    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。