Java+playwright+testNG实现UI自动化测试

今天来讲讲使用Java结合最新的playwright来做UI自动化测试

目前网上大部分都是关于使用Python做自动化的教程,Java的比较少一些,但是我认为使用Java做自动化还是有优点的,性能就好一点,当然大家根据实际需求来。

一、 普通UI测试

  1. 创建 Maven 项目
    在你选择的 IDE(如 IntelliJ IDEA 或 Eclipse)中创建一个新的 Maven 项目。

  2. **添加依赖到 pom.xml**:(我使用的jdk1.8) 打开 pom.xml 文件并添加以下依赖:

    <dependencies>
        <!-- Playwright -->
        <dependency>
            <groupId>com.microsoft.playwright</groupId>
            <artifactId>playwright</artifactId>
            <version>1.41.0</version>
            <scope>test</scope>
        </dependency>
    
        <!-- TestNG -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.4.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

示例测试用例

接下来,编写一个简单的测试用例,使用 Playwright 打开 Google 页面,并验证页面标题。

  1. 创建测试类
    在你的 Maven 项目中,创建一个新的测试类 BaiduTest.java

    import com.microsoft.playwright.*;
    import org.testng.Assert;
    import org.testng.annotations.*;
    
    public class BaiduTest {
        Playwright playwright;
        Browser browser;
        Page page;
    
        @BeforeClass
        public void setUp() {
            playwright = Playwright.create();
            BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
            options.headless = false; // 设置为有头浏览器
            browser = playwright.chromium().launch(options);
            page = browser.newPage();
        }
    
        @Test
        public void testBaiduHomePage() {
            page.navigate("https://www.baidu.com");
            String title = page.title();
            Assert.assertEquals(title, "百度一下,你就知道");
        }
    
        @AfterClass
        public void tearDown() {
            browser.close();
            playwright.close();
        }
    }

使用 TestNG 管理测试用例

  • 使用 @Test 注解:这标记了一个方法作为测试方法。

  • 使用 @BeforeClass 和 @AfterClass 注解:分别用于在测试类中所有测试方法之前和之后执行代码。

  • 断言:使用 Assert 类来进行断言,验证测试结果是否符合预期。

生成测试报告

  • 在 pom.xml 中配置 TestNG 生成测试报告的能力。

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M5</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
            </plugin>
        </plugins>
    </build>
  • 创建 testng.xml 文件来管理测试套件:

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
    <suite name="Sample Suite">
        <test name="Baidu Tests">
            <classes>
                <class name="BaiduTest"/>
            </classes>
        </test>
    </suite>

生成的报告会呈现在target/surefire-reports 目录下生成 XML 格式的测试报告

集成Allure

如果要生成更详细的HTML测试报告,可以集成allure

要集成 Allure,您需要添加相关依赖和插件到您的 POM 文件中:

<dependency>
    <groupId>io.qameta.allure</groupId>
    <artifactId>allure-testng</artifactId>
    <version>2.13.8</version>
    <scope>test</scope>
</dependency>

并配置 Allure Maven 插件:

<plugin>
     <groupId>io.qameta.allure</groupId>
     <artifactId>allure-maven</artifactId>
     <version>2.10.0</version>
     <configuration>
         <reportVersion>2.13.8</reportVersion>
         <reportingOutputDirectory>${project.build.directory}/allure-results</reportingOutputDirectory>
     </configuration>
     <executions>
         <execution>
             <phase>post-integration-test</phase>
             <goals>
                 <goal>report</goal>
             </goals>
         </execution>
     </executions>
 </plugin>

然后我们需要在src/test/resources目录下添加allure.properties

allure.results.directory=target/allure-results

添加这个文件主要让生成的Allure结果放到target目录里面,不然就直接放在根目录,当然你不介意的话

运行和生成报告

可以直接运行测试文件,也可以通过mvn test执行测试,然后就能在target目录下看到Allure_results的测试结果数据,全部为json格式文件,接下来使用allure generate <results dir> -o <report dir> 在report dir 目录下生成Allure测试报告,打开index.html文件就能查看测试结果

我直接使用allure generate .target/allure-results 这样就会根据里面的结果生成报告了,同样在Jenkins上面配置Allure的时候要注意results和report的区别,配置正确

二、数据驱动测试

1. 组织测试数据

为了处理多个参数和多组数据,testNG的数据提供者(@DataProvider)的二维数组会是你的核心工具。数据数组的每个元素都可以包含多种数据,包括不同的定位方式、输入值和其他参数。

import org.testng.annotations.DataProvider;

public class TestDataProvider {
    @DataProvider(name = "complexData")
    public Object[][] createComplexData() {
        return new Object[][] {
            { "Case 1", "https://example.com/login", "username1", "password1", "login-button-id-1" },
            { "Case 2", "https://example.com/login", "username2", "password2", "login-button-id-2" },
            { "Case 3", "https://example.com/signup", "newuser1", "newpass1", "signup-button-id" }
        };
    }
}

在这个示例中,我们有一个数据提供者 complexData,包含了多个参数,包括测试用例名称、网址、用户名、密码和按钮 ID。

2. 链接数据提供者到测试方法

现在,我们需要一个测试类,它使用上面定义的数据提供者来获取不同的数据集,并应用于测试方法。

import com.microsoft.playwright.*;
import org.testng.Assert;
import org.testng.annotations.*;

public class ComplexTest {
    Playwright playwright;
    Browser browser;
    Page page;

    @BeforeClass
    public void setUp() {
        playwright = Playwright.create();
        BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
        options.headless = false; // 设置为 true 运行无头浏览器
        browser = playwright.chromium().launch(options);
        page = browser.newPage();
    }

    @Test(dataProvider = "complexData", dataProviderClass = TestDataProvider.class)
    public void testComplexScenarios(String testCaseName, String url, String username, String password, String buttonId) {
        page.navigate(url);

        // 输入用户名和密码
        page.fill("input[name='username']", username);
        page.fill("input[name='password']", password);

        // 点击按钮
        page.click("#" + buttonId);

        // 检查页面是否成功登录/注册
        boolean isLoginSuccess = page.locator("#success-message").isVisible();
        Assert.assertTrue(isLoginSuccess, testCaseName + " - 登录/注册失败");
    }

    @AfterClass
    public void tearDown() {
        browser.close();
        playwright.close();
    }
}

在这个示例中,测试方法 testComplexScenarios 接收多个参数。这使得我们可以根据不同的数据集运行相同的测试逻辑。

3. 在报告中显示测试用例名称和具体步骤

为了在报告中显示测试用例名称和步骤结果,可以通过以下方式实现:

  • 使用 TestNG Reporter:TestNG 提供了报告功能,测试用例可以通过 Reporter.log() 输出特定信息,这样在最终报告中会显示这些信息。

  • 使用 TestNG 监听器:监听器可以帮助你更好地跟踪测试结果,并自定义报告输出。

示例代码展示了如何记录测试步骤以及在报告中显示测试用例名称:

import com.microsoft.playwright.*;
import org.testng.Assert;
import org.testng.Reporter;
import org.testng.annotations.*;

public class DetailedReportTest {
    Playwright playwright;
    Browser browser;
    Page page;

    @BeforeClass
    public void setUp() {
        playwright = Playwright.create();
        BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
        options.headless = false; // 设置为 true 运行无头浏览器
        browser = playwright.chromium().launch(options);
        page = browser.newPage();
    }

    @Test(dataProvider = "complexData", dataProviderClass = TestDataProvider.class)
    public void testWithReport(String testCaseName, String url, String username, String password, String buttonId) {
        Reporter.log("开始执行用例:" + testCaseName, true);

        page.navigate(url);
        Reporter.log("导航至:" + url, true);

        // 输入用户名和密码
        page.fill("input[name='username']", username);
        Reporter.log("填入用户名:" + username, true);

        page.fill("input[name='password']", password);
        Reporter.log("填入密码", true);

        // 点击按钮
        page.click("#" + buttonId);
        Reporter.log("点击按钮:" + buttonId, true);

        // 检查页面是否成功
        boolean isSuccess = page.locator("#success-message").isVisible();
        Assert.assertTrue(isSuccess, testCaseName + " - 操作失败");

        Reporter.log("用例:" + testCaseName + " 执行成功", true);
    }

    @AfterClass
    public void tearDown() {
        browser.close();
        playwright.close();
    }
}

这个例子通过 Reporter.log() 来记录测试用例的步骤和结果,在生成的 TestNG 报告中,你可以看到这些日志信息以及测试用例名称。

当然如果你想要在Allure里面展示详细步骤,比如某个按钮,或者某个节点是否成功,你可以添加Allure.step(<string>)

import com.microsoft.playwright.*;
import com.microsoft.playwright.options.AriaRole;
import org.testng.Assert;
import org.testng.annotations.*;
import io.qameta.allure.*;

public class LoginTest {
    Playwright playwright;
    Browser browser;
    Page page;

    @BeforeClass
    public void setUp() {
        playwright = Playwright.create();
        BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
        options.headless = false; // 设置为运行有头浏览器
        browser = playwright.chromium().launch(options);
        page = browser.newPage();
    }
    @Feature("登录功能模块")
    @Test(dataProvider = "loginData",dataProviderClass = TestDataProvider.class)
    public void testLogin(String testCaseName,String username, String password, boolean isExpectedAlert ,String expectedMessage, String expectedUrl) {
        boolean[] alertPresent = {false};
        String [] alertMessage = {""};
//        page.onDialog(dialog -> {
//            alertPresent[0] = true;
//            alertMessage[0] =dialog.message();
//        });

        page.navigate("https://yourexample.com/mangement/#/login");
        Allure.step("进入登录页成功");
        page.locator("input[type=\"text\"]").fill(username);
        Allure.step(testCaseName+"输入用户名成功");
        page.fill("#inputPwd", password);
        Allure.step(testCaseName+"输入密码成功!");
        page.getByText("登录", new Page.GetByTextOptions().setExact(true)).click();
        Allure.step(testCaseName+"点击登录按钮成功!");
        String newUrl = page.url();
        if(!testCaseName.equals("Case 1")) {
            Locator toast = page.getByRole(AriaRole.ALERT);
            toast.waitFor(new Locator.WaitForOptions().setTimeout(1000));//最多等待五秒
            if (toast.isVisible()) {
                alertPresent[0] = true;
                alertMessage[0] = toast.textContent();
            }
        }else {
            page.waitForTimeout(2000);
            newUrl = page.url();
            Allure.step(testCaseName+"登录成功!");
        }

        Assert.assertEquals(alertPresent[0],isExpectedAlert, testCaseName + "failed");
        Assert.assertEquals(alertMessage[0],expectedMessage,testCaseName + "failed");
        Assert.assertEquals(newUrl,expectedUrl,testCaseName + "failed");

    }
    @AfterClass
    public void tearDown() {
        browser.close();
        playwright.close();
    }
}

如果熟悉使用Python进行UI测试用过Allure的应该都清楚

这里简单回顾一下Allure常用的接口,装饰器(更多的大家可以去官网查看)

  1. @Feature

  • 意义:用于标注主要的功能模块。

  • 用途:帮助组织和分类测试用例,使其按照功能模块进行归类。通过查看报告中的Feature,可以快速地了解哪些功能模块被测试了。

@Story

  • 意义:用于标注功能模块下的分支功能或具体场景。

  • 用途:进一步细分功能模块,描述更具体的功能点或业务场景。通过Story,可以更详细地了解每个功能模块下的具体测试内容。

@Title

  • 意义:用于为测试用例或测试步骤提供标题。

  • 用途:使得每个测试用例或步骤在报告中都有一个明确的、描述性的标题,方便用户快速识别和理解。

三、测试数据与代码分离进行数据驱动

当然,让我们继续讨论如何使用 CSV 文件来进行数据驱动的测试。

添加 Maven 依赖

首先,在你的 Maven pom.xml 文件中添加 Apache Commons CSV 或任何其他 CSV 解析库的依赖。这里我们使用 Apache Commons CSV。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.8</version>
</dependency>

读取 CSV 文件

创建一个 @DataProvider 方法来读取 CSV 文件,并返回测试用例所需的数据。以下是一个例子,演示如何解析 CSV 文件并构造对象数组。

import org.apache.commons.csv.*;
import org.testng.annotations.DataProvider;

import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CSVDataProviders {

    @DataProvider(name = "csvTestData")
    public static Object[][] readCsvData() throws IOException {
        List<Object[]> testCases = new ArrayList<>();
        try (CSVParser parser = new CSVParser(new FileReader("path/to/testdata.csv"), CSVFormat.DEFAULT.withHeader())) {
            for (CSVRecord record : parser) {
                String testCaseName = record.get("TestCaseName");
                String inputData = record.get("InputData");
                String locatorId = record.get("LocatorId");
                String expectedOutcome = record.get("ExpectedOutcome");
                testCases.add(new Object[]{testCaseName, inputData, locatorId, expectedOutcome});
            }
        }
        return testCases.toArray(new Object[0][]);
    }
}

在这个例子中,我们假设 CSV 文件有列标题 TestCaseName, InputData, LocatorId, 和 ExpectedOutcomeCSVParser 用于读取 CSV 文件,然后每条记录被转换成一个对象数组并添加到列表中。

使用数据提供者

接下来,在你的测试类中使用这个 @DataProvider

import com.microsoft.playwright.*;
import org.testng.Assert;
import org.testng.annotations.*;

public class DataDrivenTests {
    Playwright playwright;
    Browser browser;
    Page page;

    @BeforeClass
    public void setUp() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
        page = browser.newPage();
    }

    @Test(dataProvider = "csvTestData", dataProviderClass = CSVDataProviders.class)
    public void testWithCsvData(String testCaseName, String inputData, String locatorId, String expectedOutcome) {
        page.navigate(inputData); // Assuming inputData is a URL for simplicity
        page.click("#" + locatorId);
        Assert.assertTrue(page.isVisible(expectedOutcome), "Test failed for: " + testCaseName);
    }

    @AfterClass
    public void tearDown() {
        browser.close();
        playwright.close();
    }
}

在这个测试方法中,通过 @DataProvider 注解指定数据来源为 csvTestData,它会自动接收 CSV 文件中的每行数据作为参数。

好了本次分享就到此结束了,欢迎大家一起讨论学习

附官网参考地址:

1、playwright的Java版本相关接口:https://playwright.dev/java/docs/api/class-playwrighthttps://playwright.dev/java/docs/api/class-playwright

2、Allure与testNG相关的接口:

https://allurereport.org/docs/testng/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/583092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全设计的技术有哪些?

目录 1. 防火墙 2. 入侵检测系统&#xff08;IDS&#xff09;和入侵防御系统&#xff08;IPS&#xff09; 3. 身份和访问管理&#xff08;IAM&#xff09; 4. 数据加密 5. 网络分割和虚拟化 6. 安全信息和事件管理&#xff08;SIEM&#xff09; 7. 端点保护 8. 配置管理…

链表带环问题的方法证明

目录 一、带环问题的解决 1、固定思路 2、思路后的数学证明 3、不相遇的情况分析 二、环入口问题 ​编辑 1、固定思路 2、数学证明 三、求环的长度 一、带环问题的解决 1、固定思路 链表带环问题比较传统的思路是使用快慢指针&#xff0c;当快和慢指针相遇的时候那么…

工具篇--Window--常用工具命令汇总(持续更新)

文章目录 前言一、常用工具&#xff1a;1.1 window host 修改&#xff1a;1.2 window 端口占用&#xff1a;1.3 打开/关闭防火墙&#xff1a;1.4 JavaScript 对象或值转换为 JSON 字符串: 二、命令行&#xff1a;2.1 获取本机ip&#xff1a; 三、网页在线工具&#xff1a;3.1 本…

吴恩达深度学习笔记:深度学习的 实践层面 (Practical aspects of Deep Learning)1.9-1.10

目录 第一门课&#xff1a;第二门课 改善深层神经网络&#xff1a;超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第一周&#xff1a;深度学习的 实践层面 (Practical aspects of Deep Learning)…

LabVIEW自动剪板机控制系统

LabVIEW自动剪板机控制系统 随着工业自动化的快速发展&#xff0c;钣金加工行业面临着生产效率和加工精度的双重挑战。传统的手动或脚踏式剪板机已无法满足现代生产的高效率和高精度要求&#xff0c;因此&#xff0c;自动剪板机控制系统的研究与开发成为了行业发展的必然趋势。…

如何快速开发个性化回收小程序

回收小程序的开发无疑是提升回收业务效率的重要途径。它不仅可以清晰地列出各类回收物品&#xff0c;还能在微信、抖音、支付宝等多个平台同时上线&#xff0c;让回收服务触手可及。那么&#xff0c;如何以最快、最简单、最经济的方式上线这样一个小程序呢&#xff1f; 在这里&…

Linux实训-用户和组的管理

实训1&#xff1a;用户的管理 创建一个新用户user1&#xff0c;设置其主目录为/home/user1。查看/etc/passwd文件的最后一行&#xff0c;看看是如何记录的。查看文件/etc/shadow文件的最后一行&#xff0c;看看如何记录的。给用户user1设置密码。再次查看文件/etc/shadow文件的…

分享5个图源二维码及使用方法

数据是GIS的血液&#xff01; 我们在《4个在ArcGIS中可加载的图源分享》一文中&#xff0c;为大家分享了4个可以直接在ArcMap中打开查看的图源。 现在&#xff0c;我们再分享5个可以在水经微图&#xff08;以下简称“微图”&#xff09;桌面版&#xff08;PC端&#xff09;、…

Kafka Exactly Once 语义实现原理:幂等性与事务消息

01 前言 在现代分布式系统中&#xff0c;确保数据处理的准确性和一致性是至关重要的。Apache Kafka&#xff0c;作为一个广泛使用的流处理平台&#xff0c;提供了强大的消息队列和流处理功能。随着业务需求的增长&#xff0c;Kafka 的事务消息功能应运而生&#xff0c;它允许应…

MacPro(M1,M2芯片)Java开发和常用工具开源软件合集

目录 Java开发软件1 IDE1.1 idea1.2 Vs Code 2 开发工具2.1 数据库数据库模型管理数据库连接客户端 2.2 SSH/Telnet/Serial/Shell/Sftp客户端2.3 MarkDown编辑器2.3 代码片段管理粘贴 3小工具3.1 截图贴图3.2 Mac下修改hosts文件的图形化界面软件 Java开发软件 1 IDE 1.1 ide…

第三方软件测试机构-科技成果评价测试

科技成果评价测试是对科研成果的工作质量、学术水平、实际应用和成熟程度等方面进行的客观、具体、恰当的评价过程。这一评价过程有助于了解科技成果的质量和水平&#xff0c;以及其在学术和应用方面的价值和潜力。 科技成果评价测试主要包括以下几个方面&#xff1a; 工作质量…

设计不外流,保护创意的同时锁住图纸安全!

在设计行业中&#xff0c;图纸和创意文稿的安全至关重要&#xff0c;因为它们体现了企业的创新能力和核心竞争力。华企盾DSC数据防泄密系统提供了一系列功能&#xff0c;可以有效地保护这些珍贵的设计和文档不被外泄。以下是如何利用华企盾DSC系统保障设计图纸安全的关键措施&a…

tableau如何传参数到MySQL数据库

1、打开tableau连接本地MySQL-》新建自定义sql-》创建参数 2、新建一个简单的工作表-》把维度拖拽到行显示结果-》右键显示参数 3、参数传递到数据库sql写法 select * from yonghu where yonghu.姓名 like concat(%,<参数.姓名>,%)select * FROMabadata4WHERE abadata4…

mysql-sql-练习题-1

文章目录 环境注释建表 5张建库学生表课程表教师表分数表总表 语法书写顺序in学过/没学过完全相同 环境 Windows cmd&#xff08;普通用户/管理员&#xff09; mysql -uroot -pmysql版本&#xff0c;模式&#xff08;可自定义&#xff09; select version(),global.sql_mode…

不完全微分PD控制器(CODESYS源代码+算法详细介绍)

完全微分计算公式为Kp*Td/Ts(e(k)-e(k-1))。有关位置式PID和增量式PID更多相关内容,大家可以参考下面的文章链接: 1、CODESYS位置式PID CODESYS位置式PID(完整ST源代码)_codesys pid功能块-CSDN博客文章浏览阅读1.1k次,点赞2次,收藏2次。CODESYS增量式PID完整源代码请参看…

中国标准地图如何与卫星影像叠加

我们在《一幅SHP格式的中国标准地图》一文中&#xff0c;为你分享过一幅SHP格式的中国标准地图&#xff0c;但该数据为等积投影。 由于我们常用的卫星影像为WGS84经纬度投影或墨卡托投影&#xff0c;那么将该数据如何与卫星影像进行叠加制作专题图呢&#xff1f; 我们现在就来…

day17-day20_项目实战项目部署

万信金融 项目部署 目标&#xff1a; 理解DevOps概念 能够使用Docker Compose部署项目 理解持续集成的作用 会使用Jenkins进行持续集成 1 DevOps介绍 1.1 什么是DevOps DevOps是Development和Operations两个词的缩写&#xff0c;引用百度百科的定义&#xff1a; DevOps…

Windows Server配置网卡绑定:NIC组合

正文共&#xff1a;1024 字 12 图&#xff0c;预估阅读时间&#xff1a;1 分钟 在网络设备上&#xff0c;为了提高可靠性&#xff0c;一般会配置链路聚合&#xff08;Link Aggregation&#xff09;&#xff08;网络之路28&#xff1a;二层链路聚合&#xff09;&#xff0c;同样…

GNU Radio之OFDM Channel Estimation底层C++实现

文章目录 前言一、 OFDM Channel Estimation 模块简介二、C 具体实现1、初始化和配置参数2、forecast 函数3、计算载波偏移量4、提取信道响应5、核心的数据处理任务 前言 OFDM Channel Estimation 模块的功能是根据前导码&#xff08;同步字&#xff09;估计 OFDM 的信道和粗略…

FileLink内外网文件摆渡系统产品介绍

在现代企业中&#xff0c;往往存在着多个网络、系统之间的数据孤岛问题&#xff0c;数据难以互相访问和共享。 一、常用的内外网文件摆渡方式 传统的数据交换方式往往需要人工介入&#xff0c;效率低下且容易出错。如&#xff1a;U盘、FTP、VPN等&#xff0c;极易引发各种各样…
最新文章