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;@BeforeClasspublic void setUp() {playwright = Playwright.create();BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();options.headless = false; // 设置为有头浏览器browser = playwright.chromium().launch(options);page = browser.newPage();}@Testpublic void testBaiduHomePage() {page.navigate("https://www.baidu.com");String title = page.title();Assert.assertEquals(title, "百度一下,你就知道");}@AfterClasspublic 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;@BeforeClasspublic 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 + " - 登录/注册失败");}@AfterClasspublic 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;@BeforeClasspublic 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);}@AfterClasspublic 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;@BeforeClasspublic 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");}@AfterClasspublic 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;@BeforeClasspublic 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 simplicitypage.click("#" + locatorId);Assert.assertTrue(page.isVisible(expectedOutcome), "Test failed for: " + testCaseName);}@AfterClasspublic 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.mzph.cn/pingmian/4849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python】去除水印的几种方式

1、python调用FFMEPG的delogo函数去除水印 要使用Python调用FFmpeg的delogo filter去除视频水印&#xff0c;你需要使用subprocess模块运行FFmpeg命令。以下是一个简单的Python脚本示例&#xff1a; import subprocessdef remove_watermark(input_video, output_video, logo_…

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…

如果把软路由的网段更换成169.254.0.0/16会咋样?

前言 这几天有小伙伴在折腾软路由系统&#xff0c;然后问题就来了。 他咨询的是&#xff1a;为啥电脑连接软路由之后&#xff0c;无法访问软路由的管理页&#xff1f; 嗯。。。确实不是什么大事。但不注意看&#xff0c;还以为软路由没有正常获取到ip。 熟悉网络的小伙伴们都…

教程推荐:手机应用自动化

手机应用程序的自动化通常涉及使用专门设计的自动化框架和工具。对于Android和iOS平台&#xff0c;以下是一些常用的自动化工具&#xff1a; Android: Espresso: Espresso是谷歌官方支持的自动化测试框架。它适用于写UI测试来模拟用户对Android应用的交云。Espresso工作在应用…

Python中的map()和filter()函数:深入解析与使用场景

Python中的map()和filter()函数&#xff1a;深入解析与使用场景 在Python编程中&#xff0c;map()和filter()是两个非常实用的内置函数&#xff0c;它们可以帮助我们更高效地处理数据。这两个函数都是高阶函数&#xff0c;可以接受一个函数作为参数&#xff0c;并应用于序列&a…

实例解释:溢出和进位是咋回事?不能胡来吧!

有学生给我一段程序&#xff0c;就在运行中标志位的“怪异”表现提出问题。   程序不难懂&#xff1a; assume cs:codesg codesg segment start:mov al,0fchadd al,05h ;结果不溢出mov al,0f5hadd al,87h ;结果溢出mov ax,4c00hint 21h codesg ends end start难懂的是&a…

设计模式- 访问者模式(Visitor Pattern)结构|原理|优缺点|场景|示例

设计模式&#xff08;分类&#xff09; 设计模式&#xff08;六大原则&#xff09; 创建型&#xff08;5种&#xff09; 工厂方法 抽象工厂模式 单例模式 建造者模式 原型模式 结构型&#xff08;7种&#xff09; 适配器…

leetcode-有效括号序列-94

题目要求 思路 1.使用栈的先进后出的思路&#xff0c;存储前括号&#xff0c;如果st中有对应的后括号与之匹配就说明没问题 2.有两个特殊情况就是字符串第一个就是后括号&#xff0c;这个情况本身就是不匹配的&#xff0c;还有一种是前面的n个字符串本身是匹配的&#xff0c;这…

Python中format的常见用法

一、填充 1、按默认顺序填充 name "Alice" age 25 print("My name is {} and I am {} years old.".format(name, age))输出&#xff1a;My name is Alice and I am 25 years old. 2、指定位置 name "Bob" age 30 print("My name is…

与Apollo共创生态:我们携手远航

目录 小程一言会议记录 回望7年发展展望未来小程有感 小程一言 4月22日&#xff0c;百度Apollo在北京车展前夕举办了以“破晓•拥抱智变时刻”为主题的智能汽车产品发布会。我在观看后也是很是触动 作为在校大学生的我&#xff0c;从大一开始知道Apollo开始&#xff0c;Apollo…

2024.04.09 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、校招&实习 | 佑驾创新Minieye 春招补录实习&#xff08;内推&#xff09; 校招&实习 | 佑驾创新Minieye 春招补录实习&#xff08;内推&#xff09; 2、校招 | 上海复旦微电子…

STM32中I2C通信的完整C语言代码范例

在嵌入式系统开发中&#xff0c;STM32芯片是一种广泛应用的微控制器&#xff0c;具有强大的性能和丰富的外设功能。其中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种常用的串行通信协议&#xff0c;用于在微控制器之间或者微控制器与外设之间进行数…

高并发实现高效内存管理

高并发下传统方式的弊端 void *malloc(size_t size);在内存的动态存储区中分配一块长度为size字节的连续区域返回该区域的首地址. void *calloc(size_t nmemb, size_t size);与malloc相似&#xff0c;参数size为申请地址的单位元素长度&#xff0c;nmemb为元素个数&#xff0…

开发中git的常用操作

Git 是一款分布式版本控制系统&#xff0c;广泛应用于软件开发中&#xff0c;用于管理项目的版本和修改历史。在开发过程中&#xff0c;有许多常用的 Git 操作可以帮助团队协作、版本管理和代码管理。下面将详细讲解常用的 Git 操作&#xff0c;并通过举例说明它们的用法和作用…

软考高级 | 系统架构设计师笔记(一)

一. 系统规划 1.1 项目的提出与选择 该步骤生成” 产品/项目建议书”. 1.2 可行性研究与效益分析 包括经济可行性/技术可行性/法律可行性/执行可行性/方案选择 5 个部分. 该步骤生 成”可行性研究报告”. 1.3 方案的制订和改进 包括确定软件架构/确定关键性要素?/确定计算…

spring-boot控制bean的创建顺序

1、order注解&#xff08;不一定有效&#xff09; org.springframework.core.annotation.Order 2、dependsOn注解&#xff08;有效&#xff09; org.springframework.context.annotation.DependsOn 3、提前将bean注册为BeanDefinition 1、实现BeanDefinitionRegistryPostP…

商城数据库88张表结构(八)

DDL 29.商品规格表 CREATE TABLE wang_goods_specs (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,shopId int(11) NOT NULL DEFAULT 0 COMMENT 店铺ID,goodsid int(11) NOT NULL DEFAULT 0 COMMENT 商品ID,productNo varchar(20) NOT NULL COMMENT 商品货号,specids v…

Python 自定义日志输出

Python 有着内置的日志输出模块&#xff1a;logging 使用也很方便&#xff0c;但我们今天不说这个&#xff0c;我们用文件读写模块&#xff0c;实现自己的日志输出模块&#xff1b;这样在项目中&#xff0c;可以存在更高的自由度及更高的扩展性&#xff1b; 先来看看日志输出…

TDengine高可用架构之TDengine+Keepalived

之前在《TDengine高可用探讨》提到过&#xff0c;TDengine通过多副本和多节点能够保证数据库集群的高可用。单对于应用端来说&#xff0c;如果使用原生连接方式&#xff08;taosc&#xff09;还好&#xff0c;当一个节点下线&#xff0c;应用不会受到影响&#xff1b;但如果使用…

探索AI作画算法的原理:从深度学习到创造性艺术

引言 介绍AI在不同领域的应用&#xff0c;以及AI作画算法对于创造性艺术的影响。概述将在本文中讨论的主要内容。 第一部分&#xff1a;深度学习与计算机视觉 深度学习的基本原理&#xff1a;神经网络的结构和训练过程。计算机视觉的重要性&#xff1a;图像识别、生成和处理…