it编程 > 开发工具 > IDE

Selenium —— 用这个框架自动化任何你想做的事情!

47人参与 2024-08-06 IDE

chrome devtools 简介

chrome devtools 是一组直接内置在基于 chromium 的浏览器(如 chrome、opera 和 microsoft edge)中的工具,用于帮助开发人员调试和研究网站。

借助 chrome devtools,开发人员可以更深入地访问网站,并能够:

selenium 4 chrome devtools api

selenium 是支持 web 浏览器自动化的一系列工具和库的综合项目。selenium 4 添加了对 chrome devtools api 的原生支持。借助这些新的 api,我们的测试现在可以:

这只是冰山一角!

selenium 4 引入了新的 chromiumdriver 类,其中包括两个方法用于访问 chrome devtools:getdevtools() 和 executecdpcommand()。

getdevtools() 方法返回新的 devtools 对象,允许您使用 send() 方法发送针对 cdp 的内置 selenium 命令。这些命令是包装方法,使调用 cdp 函数更加清晰和简便。

executecdpcommand() 方法也允许您执行 cdp 方法,但更加原始。它不使用包装的 api,而是允许您直接传入 chrome devtools 命令和该命令的参数。如果某个 cdp 命令没有 selenium 包装 api,或者您希望以与 selenium api 不同的方式进行调用,则可以使用 executecdpcommand()。

像 chromedriver 和 edgedriver 这样的基于 chromium 的驱动程序现在继承自 chromiumdriver,因此您也可以从这些驱动程序中访问 selenium cdp api。

让我们探索如何利用这些新的 selenium 4 api 来解决各种使用案例。

模拟设备模式

我们今天构建的大多数应用都是响应式的,以满足来自各种平台、设备(如手机、平板、可穿戴设备、桌面)和屏幕方向的终端用户的需求。

作为测试人员,我们可能希望将我们的应用程序放置在不同的尺寸中,以触发应用程序的响应性。

我们如何使用 selenium 的新 cdp 功能来实现这一点呢?

用于修改设备度量的 cdp 命令是 emulation.setdevicemetricsoverride,并且此命令需要输入宽度、高度、移动设备标志和设备缩放因子。这四个键在此场景中是必需的,但还有一些可选的键。

在我们的 selenium 测试中,我们可以使用 devtools::send() 方法并使用内置的 setdevicemetricsoverride() 命令,但是这个 selenium api 接受 12 个参数 - 除了 4 个必需的参数外,还有 8 个可选的参数。对于我们不需要发送的这 8 个可选参数中的任何一个,我们可以传递 optional.empty()。

然而,为了简化这个过程,只传递所需的参数,我将使用下面代码中的原始 executecdpcommand() 方法。

package com.devtools;

import org.openqa.selenium.chrome.chromedriver;
import org.openqa.selenium.devtools.devtools;
import java.util.hashmap;
import java.util.map;

public class setdevicemode {

    final static string project_path = system.getproperty("user.dir");

    public static void main(string[] args){
        system.setproperty("webdriver.chrome.driver", project_path + "/src/main/resources/chromedriver");
        chromedriver driver;
        driver = new chromedriver();

        devtools devtools = driver.getdevtools();
        devtools.createsession();
        map devicemetrics = new hashmap()
        {{
            put("width", 600);
            put("height", 1000);
            put("mobile", true);
            put("devicescalefactor", 50);
        }};
        driver.executecdpcommand("emulation.setdevicemetricsoverride", devicemetrics);
        driver.get("https://www.google.com");
    }
}

在第19行,我创建了一个包含此命令所需键的映射。

然后在第26行,我调用 executecdpcommand() 方法,并传递两个参数:命令名称为 "emulation.setdevicemetricsoverride",以及包含参数的设备度量映射。

在第27行,我打开了渲染了我提供的规格的 "google" 首页,如下图所示。

借助像 applitools eyes 这样的解决方案,我们不仅可以使用这些新的 selenium 命令在不同的视口上快速进行测试,还可以在规模上保持任何不一致性。eyes 足够智能,不会对由于不同的浏览器和视口导致的 ui 中微小且难以察觉的变化报告错误的结果。

模拟地理位置

在许多情况下,我们需要测试特定的基于位置的功能,例如优惠、基于位置的价格等。为此,我们可以使用devtools api来模拟位置。

  @test
    public void mocklocation(){
        devtools.send(emulation.setgeolocationoverride(
                optional.of(48.8584),
                optional.of(2.2945),
                optional.of(100)));
        driver.get("https://mycurrentlocation.net/");
        try {
            thread.sleep(30000);
        } catch (interruptedexception e) {
            e.printstacktrace();
        }
    }

模拟网络速度

许多用户通过连接到 wi-fi 或蜂窝网络的手持设备访问 web 应用程序。遇到信号弱的网络信号,因此互联网连接速度较慢是很常见的。

在互联网连接速度较慢(2g)或间歇性断网的情况下,测试应用程序在这种条件下的行为可能很重要。

伪造网络连接的 cdp 命令是 network.emulatenetworkconditions。关于此命令的必需和可选参数的信息可以在文档中找到。

通过访问 chrome devtools,就可以模拟这些场景。让我们看看如何做到这一点。

package com.devtools;

import org.openqa.selenium.chrome.chromedriver;
import org.openqa.selenium.devtools.devtools;
import org.openqa.selenium.devtools.network.network;
import org.openqa.selenium.devtools.network.model.connectiontype;

import java.util.hashmap;
import java.util.map;
import java.util.optional;

public class setnetwork {

    final static string project_path = system.getproperty("user.dir");

    public static void main(string[] args){
        system.setproperty("webdriver.chrome.driver", project_path + "/src/main/resources/chromedriver");
        chromedriver driver;
        driver = new chromedriver();
        
        devtools devtools = driver.getdevtools();
        devtools.createsession();
        devtools.send(network.enable(optional.empty(), optional.empty(), optional.empty()));
        devtools.send(network.emulatenetworkconditions(
                false,
                20,
                20,
                50,
                optional.of(connectiontype.cellular2g)
        ));
        driver.get("https://www.google.com");
    }
}

在第21行,我们通过调用 getdevtools() 方法获取 devtools 对象。然后,我们调用 send() 方法来启用 network,并再次调用 send() 方法来传递内置命令 network.emulatenetworkconditions() 和我们希望与此命令一起发送的参数。

最后,我们使用模拟的网络条件打开 google 首页。

捕获http请求

使用 devtools,我们可以捕获应用程序发起的 http 请求,并访问方法、数据、头信息等等。

让我们看看如何使用示例代码捕获 http 请求、uri 和请求方法。

package com.devtools;

import org.openqa.selenium.chrome.chromedriver;
import org.openqa.selenium.devtools.devtools;
import org.openqa.selenium.devtools.network.network;

import java.util.optional;

public class capturenetworktraffic {

    private static chromedriver driver;
    private static devtools chromedevtools;

    final static string project_path = system.getproperty("user.dir");

    public static void main(string[] args){
        system.setproperty("webdriver.chrome.driver", project_path + "/src/main/resources/chromedriver");
        driver = new chromedriver();
        chromedevtools = driver.getdevtools();
        chromedevtools.createsession();

        chromedevtools.send(network.enable(optional.empty(), optional.empty(), optional.empty()));
        chromedevtools.addlistener(network.requestwillbesent(),
                entry -> {
                    system.out.println("request uri : " + entry.getrequest().geturl()+"\n"
                    + " with method : "+entry.getrequest().getmethod() + "\n");
                    entry.getrequest().getmethod();
                });
        driver.get("https://www.google.com");
        chromedevtools.send(network.disable());
    }
}

开始捕获网络流量的 cdp 命令是 network.enable。关于此命令的必需和可选参数的信息可以在文档中找到。

在我们的代码中,第22行使用 devtools::send() 方法发送 network.enable cdp 命令以启用网络流量捕获。

第23行添加了一个监听器,用于监听应用程序发送的所有请求。对于应用程序捕获的每个请求,我们使用 getrequest().geturl() 提取 url,并使用 getrequest().getmethod() 提取 http 方法。

第29行,我们打开了 google 的首页,并在控制台上打印了此页面发出的所有请求的 uri 和 http 方法。

一旦我们完成了请求的捕获,我们可以发送 network.disable 的 cdp 命令以停止捕获网络流量,如第30行所示。

拦截http响应

为了拦截响应,我们将使用network.responsereceived事件。当http响应可用时触发此事件,我们可以监听url、响应头、响应代码等。要获取响应正文,请使用network.getresponsebody方法。

 @test
    public void validateresponse() {
        final requestid[] requestids = new requestid[1];
        devtools.send(network.enable(optional.of(100000000), optional.empty(), optional.empty()));
        devtools.addlistener(network.responsereceived(), responsereceived -> {
            if (responsereceived.getresponse().geturl().contains("api.zoomcar.com")) {
                system.out.println("url: " + responsereceived.getresponse().geturl());
                system.out.println("status: " + responsereceived.getresponse().getstatus());
                system.out.println("type: " + responsereceived.gettype().tojson());
                responsereceived.getresponse().getheaders().tojson().foreach((k, v) -> system.out.println((k + ":" + v)));
                requestids[0] = responsereceived.getrequestid();
                system.out.println("response body: \n" + devtools.send(network.getresponsebody(requestids[0])).getbody() + "\n");
            }
        });
        driver.get("https://www.zoomcar.com/bangalore");
        driver.findelement(by.classname("search")).click();
    }

访问控制台日志

我们都依赖日志来进行调试和分析故障。在测试和处理具有特定数据或特定条件的应用程序时,日志可以帮助我们调试和捕获错误消息,提供更多在 chrome devtools 的控制台选项卡中发布的见解。

我们可以通过调用 cdp 日志命令来通过我们的 selenium 脚本捕获控制台日志,如下所示。

package com.devtools;

import org.openqa.selenium.chrome.chromedriver;
import org.openqa.selenium.devtools.devtools;
import org.openqa.selenium.devtools.log.log;

public class captureconsolelogs {
    
    private static chromedriver driver;
    private static devtools chromedevtools;
    final static string project_path = system.getproperty("user.dir");

    public static void main(string[] args){
        system.setproperty("webdriver.chrome.driver", project_path + "/src/main/resources/chromedriver");
        driver = new chromedriver();
        chromedevtools = driver.getdevtools();
        chromedevtools.createsession();

        chromedevtools.send(log.enable());
        chromedevtools.addlistener(log.entryadded(),
                logentry -> {
                    system.out.println("log: "+logentry.gettext());
                    system.out.println("level: "+logentry.getlevel());
                });
        driver.get("https://testersplayground.herokuapp.com/console-5d63b2b2-3822-4a01-8197-acd8aa7e1343.php");
    }
}

在我们的代码中,第19行使用 devtools::send() 来启用控制台日志捕获。

然后,我们添加一个监听器来捕获应用程序记录的所有控制台日志。对于应用程序捕获的每个日志,我们使用 gettext() 方法提取日志文本,并使用 getlevel() 方法提取日志级别。

最后,打开应用程序并捕获应用程序发布的控制台错误日志。

捕获性能指标

在当今快节奏的世界中,我们以如此快的速度迭代构建软件,我们也应该迭代性地检测性能瓶颈。性能较差的网站和加载较慢的页面会让客户感到不满。

我们能够在每次构建时验证这些指标吗?是的,我们可以!

捕获性能指标的 cdp 命令是 performance.enable。关于这个命令的信息可以在文档中找到。

让我们看看如何在 selenium 4 和 chrome devtools api 中完成这个过程。

package com.devtools;

import org.openqa.selenium.chrome.chromedriver;
import org.openqa.selenium.devtools.devtools;
import org.openqa.selenium.devtools.performance.performance;
import org.openqa.selenium.devtools.performance.model.metric;
import java.util.arrays;
import java.util.list;
import java.util.stream.collectors;

public class getmetrics {

    final static string project_path = system.getproperty("user.dir");

    public static void main(string[] args){
        system.setproperty("webdriver.chrome.driver", project_path + "/src/main/resources/chromedriver");
        chromedriver driver = new chromedriver();
        devtools devtools = driver.getdevtools();
        devtools.createsession();
        devtools.send(performance.enable());

        driver.get("https://www.google.org");

        list<metric> metrics = devtools.send(performance.getmetrics());
        list<string> metricnames = metrics.stream()
                .map(o -> o.getname())
                .collect(collectors.tolist());

        devtools.send(performance.disable());

        list<string> metricstocheck = arrays.aslist(
                "timestamp", "documents", "frames", "jseventlisteners",
                "layoutobjects", "mediakeysessions", "nodes",
                "resources", "domcontentloaded", "navigationstart");

        metricstocheck.foreach( metric -> system.out.println(metric +
                " is : " + metrics.get(metricnames.indexof(metric)).getvalue()));
    }
}

首先,我们通过调用 devtools 的 createsession() 方法创建一个会话,如第19行所示。

接下来,我们通过将 performance.enable() 命令发送给 send() 来启用 devtools 来捕获性能指标,如第20行所示。

一旦启用了性能捕获,我们可以打开应用程序,然后将 performance.getmetrics() 命令发送给 send()。这将返回一个 metric 对象的列表,我们可以通过流式处理来获取捕获的所有指标的名称,如第25行所示。

然后,我们通过将 performance.disable() 命令发送给 send() 来禁用性能捕获,如第29行所示。

为了查看我们感兴趣的指标,我们定义了一个名为 metricstocheck 的列表,然后通过循环遍历该列表来打印指标的值。

基本身份验证

在 selenium 中,无法与浏览器弹出窗口进行交互,因为它只能与 dom 元素进行交互。这对于身份验证对话框等弹出窗口构成了挑战。

我们可以通过使用 cdp api 直接与 devtools 处理身份验证来绕过此问题。设置请求的附加标头的 cdp 命令是 network.setextrahttpheaders。

以下是在 selenium 4 中调用此命令的方法。

package com.devtools;

import org.apache.commons.codec.binary.base64;
import org.openqa.selenium.by;
import org.openqa.selenium.chrome.chromedriver;
import org.openqa.selenium.devtools.devtools;
import org.openqa.selenium.devtools.network.network;
import org.openqa.selenium.devtools.network.model.headers;
import java.util.hashmap;
import java.util.map;
import java.util.optional;

public class setauthheader {

  private static final string username = "guest";
  private static final string password = "guest";
  final static string project_path = system.getproperty("user.dir");

  public static void main(string[] args){
    system.setproperty("webdriver.chrome.driver", project_path + "/src/main/resources/chromedriver");
    chromedriver driver = new chromedriver();

    //create devtools session and enable network
    devtools chromedevtools = driver.getdevtools();
    chromedevtools.createsession();
    chromedevtools.send(network.enable(optional.empty(), optional.empty(), optional.empty()));

    //open website
    driver.get("https://jigsaw.w3.org/http/");

    //send authorization header
    map<string, object> headers = new hashmap<>();
    string basicauth ="basic " + new string(new base64().encode(string.format("%s:%s", username, password).getbytes()));
    headers.put("authorization", basicauth);
    chromedevtools.send(network.setextrahttpheaders(new headers(headers)));

    //click authentication test - this normally invokes a browser popup if unauthenticated
    driver.findelement(by.linktext("basic authentication test")).click();

    string loginsuccessmsg = driver.findelement(by.tagname("html")).gettext();
    if(loginsuccessmsg.contains("your browser made it!")){
      system.out.println("login successful");
    }else{
      system.out.println("login failed");
    }

    driver.quit();
  }
}

我们首先使用 devtools 对象创建一个会话,并启用 network。这在第25-26行中展示。

接下来,我们打开我们的网站,然后创建用于发送的身份验证标头。

在第35行,我们将 setextrahttpheaders 命令发送到 send(),同时发送标头的数据。这部分将对我们进行身份验证并允许我们绕过浏览器弹出窗口。

为了测试这个功能,我们点击了基本身份验证测试链接。如果您手动尝试这个操作,您会看到浏览器弹出窗口要求您进行登录。但由于我们发送了身份验证标头,所以我们的脚本中不会出现这个弹出窗口。

相反,我们会收到消息“您的浏览器登录成功!”。

总结

通过添加 cdp api,selenium 已经变得更加强大。现在,我们可以增强我们的测试,捕获 http 网络流量,收集性能指标,处理身份验证,并模拟地理位置、时区和设备模式。以及在 chrome devtools 中可能出现的任何其他功能!

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

如何利用selenium使用代理IP?

08-06

注册中心 Eureka; Ribbo - 负载均衡; 负载均衡策略 ;注册中心的配置集群, 创建 namespace,配置命名空间,nacos添加配置文件,从nacos拉取配置等相关的操作

08-06

分享12个免费AI一键生成PPT的网站【2024年最新】

08-05

【图像处理高级编程】-真彩色转256 色源程序

08-05

【kg推荐->精读】RippleNet: Propagating User Preferences on the Knowledge Graph for Recommender Systems

08-05

【计算机视觉 | 目标检测】术语理解6:ViT 变种( ViT-H、ViT-L & ViT-B)、bbox(边界框)、边界框的绘制(含源代码)

08-05

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论