讲师中心 微信公众号
AI工具推荐 视频效率加速

Java中如何用TestNG进行参数化测试

夏墨姑娘_3317

夏墨姑娘_3317

发布时间:2025-06-24 09:35:01

|

1058人浏览过

|

来源于php中文网

原创

testng参数化测试主要依赖三种方式:1. 使用@parameters注解结合testng.xml配置参数值,优点是简单直接但不够灵活;2. 使用@dataprovider注解在代码中动态生成参数,支持object[][]或iterator返回类型,灵活性高;3. 结合xml配置与@dataprovider,通过xml指定参数影响数据生成逻辑。此外,testng还支持工厂模式创建带不同参数的测试实例、使用csv或excel作为数据源,并可通过@optional设置默认参数值。异常处理方面,可使用try-catch、expectedexceptions属性或itestresult接口进行断言和结果处理。dataprovider可在同一类、不同类或通过继承抽象类复用,提升代码维护性。数据驱动测试是参数化测试的一种形式,区别在于测试数据来源外部化。

Java中如何用TestNG进行参数化测试

Java中,用TestNG进行参数化测试,简单来说,就是让你的测试用例可以接收不同的输入值,然后重复执行,这样可以覆盖更多的测试场景,提高测试效率。TestNG提供了多种方式来实现参数化,包括使用@Parameters注解、@DataProvider注解以及通过XML配置文件。

Java中如何用TestNG进行参数化测试

解决方案

Java中如何用TestNG进行参数化测试

TestNG参数化测试主要依赖以下几种方式:

立即学习“Java免费学习笔记(深入)”;

Java中如何用TestNG进行参数化测试
  1. @Parameters注解

    这是最简单的一种方式,直接在测试方法上使用@Parameters注解指定参数名称,然后在testng.xml文件中配置参数值。

    import org.testng.annotations.Parameters;
    import org.testng.annotations.Test;
    import static org.testng.Assert.assertEquals;
    
    public class ParameterTest {
    
        @Test
        @Parameters({"input", "expected"})
        public void testAdd(int input, int expected) {
            int result = input + 1;
            assertEquals(result, expected);
        }
    }

    对应的testng.xml文件:

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
    <suite name="Parameter Suite">
        <test name="Add Test">
            <parameter name="input" value="5"/>
            <parameter name="expected" value="6"/>
            <classes>
                <class name="ParameterTest"/>
            </classes>
        </test>
    </suite>

    这种方式的优点是简单直接,缺点是参数值写死在XML文件中,不够灵活。

  2. @DataProvider注解

    @DataProvider注解允许你定义一个方法,该方法返回测试用例需要的参数值。这个方法返回的数据可以是Object[][]或Iterator<object></object>。

    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Test;
    import static org.testng.Assert.assertEquals;
    
    public class DataProviderTest {
    
        @DataProvider(name = "additionProvider")
        public Object[][] provideData() {
            return new Object[][]{
                    {1, 2},
                    {3, 4},
                    {5, 6}
            };
        }
    
        @Test(dataProvider = "additionProvider")
        public void testAdd(int input, int expected) {
            int result = input + 1;
            assertEquals(result, expected);
        }
    }

    @DataProvider方式的优点是参数值可以在代码中动态生成,非常灵活。

  3. XML配置结合@DataProvider

    可以结合XML配置文件和@DataProvider,在XML中指定使用哪个@DataProvider方法,这样可以在不修改代码的情况下切换不同的数据源。

    import org.testng.annotations.DataProvider;
    import org.testng.annotations.Test;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.Optional;
    import org.testng.annotations.Parameters;
    import static org.testng.Assert.assertEquals;
    
    public class XmlDataProviderTest {
    
        private int offset;
    
        @BeforeClass
        @Parameters({"offset"})
        public void setup(@Optional("1") int offset) {
            this.offset = offset;
        }
    
        @DataProvider(name = "additionProvider")
        public Object[][] provideData() {
            return new Object[][]{
                    {1, 1 + offset},
                    {3, 3 + offset},
                    {5, 5 + offset}
            };
        }
    
        @Test(dataProvider = "additionProvider")
        public void testAdd(int input, int expected) {
            int result = input + offset;
            assertEquals(result, expected);
        }
    }

    testng.xml:

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
    <suite name="XmlDataProvider Suite">
        <test name="Add Test">
            <parameter name="offset" value="2"/>
            <classes>
                <class name="XmlDataProviderTest"/>
            </classes>
        </test>
    </suite>

    这种方式结合了XML配置和@DataProvider的优点,既可以灵活地配置参数,又可以在代码中动态生成参数。

如何在TestNG中处理参数化测试中的异常情况?

在参数化测试中,不同的参数组合可能会导致不同的异常。处理这些异常,需要考虑以下几点:

  • try-catch块: 在测试方法中使用try-catch块捕获异常,并进行相应的处理,例如记录日志、进行断言等。

    @Test(dataProvider = "exceptionProvider")
    public void testException(int input) {
        try {
            if (input < 0) {
                throw new IllegalArgumentException("Input cannot be negative");
            }
            System.out.println("Input: " + input);
        } catch (IllegalArgumentException e) {
            System.out.println("Exception caught: " + e.getMessage());
            // 可以进行断言,例如 Assert.fail("Exception should not be thrown");
        }
    }
    
    @DataProvider(name = "exceptionProvider")
    public Object[][] provideExceptionData() {
        return new Object[][]{
                {-1},
                {1}
        };
    }
  • expectedExceptions: 使用@Test注解的expectedExceptions属性指定期望抛出的异常类型。如果测试方法抛出了指定的异常,则测试通过;否则,测试失败。

    @Test(dataProvider = "exceptionProvider", expectedExceptions = IllegalArgumentException.class)
    public void testExpectedException(int input) {
        if (input < 0) {
            throw new IllegalArgumentException("Input cannot be negative");
        }
        System.out.println("Input: " + input); // 如果input < 0,这行代码不会执行
    }
  • ITestResult: 可以使用ITestResult接口获取测试结果,并根据结果进行相应的处理。

    import org.testng.ITestResult;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.Test;
    import org.testng.annotations.DataProvider;
    import static org.testng.Assert.fail;
    
    public class ExceptionHandlingTest {
    
        @Test(dataProvider = "data")
        public void testMethod(int value) {
            if (value < 0) {
                throw new IllegalArgumentException("Value cannot be negative");
            }
            System.out.println("Value: " + value);
        }
    
        @DataProvider(name = "data")
        public Object[][] dataProvider() {
            return new Object[][] {
                    { 10 },
                    { -5 }
            };
        }
    
        @AfterMethod
        public void afterMethod(ITestResult result) {
            if (result.getStatus() == ITestResult.FAILURE) {
                System.out.println("Test failed: " + result.getName());
                System.out.println("Exception: " + result.getThrowable());
            }
        }
    }

    这个例子展示了如何在@AfterMethod中检查测试结果,并输出失败信息。

TestNG参数化测试中,如何复用DataProvider?

复用DataProvider可以减少代码重复,提高代码的可维护性。有以下几种方式可以复用DataProvider:

  • 在同一个类中复用: 如果DataProvider和测试方法在同一个类中,可以直接使用dataProvider属性指定DataProvider的名称。

    public class DataProviderReuseTest {
    
        @DataProvider(name = "commonProvider")
        public Object[][] provideData() {
            return new Object[][]{
                    {1, "one"},
                    {2, "two"}
            };
        }
    
        @Test(dataProvider = "commonProvider")
        public void testMethod1(int num, String str) {
            System.out.println("Method 1: " + num + ", " + str);
        }
    
        @Test(dataProvider = "commonProvider")
        public void testMethod2(int num, String str) {
            System.out.println("Method 2: " + num + ", " + str);
        }
    }
  • 在不同的类中复用: 如果DataProvider在不同的类中,可以使用dataProviderClass属性指定DataProvider所在的类。

    // DataProvider类
    public class MyDataProvider {
        @DataProvider(name = "externalProvider")
        public static Object[][] provideData() {
            return new Object[][]{
                    {"a", 1},
                    {"b", 2}
            };
        }
    }
    
    // 测试类
    import org.testng.annotations.Test;
    import org.testng.annotations.DataProvider;
    
    public class TestDataProviderReuse {
    
        @Test(dataProvider = "externalProvider", dataProviderClass = MyDataProvider.class)
        public void testMethod(String str, int num) {
            System.out.println("String: " + str + ", Number: " + num);
        }
    }

    注意:如果DataProvider在不同的类中,必须是static方法。

  • 使用抽象类和继承: 可以创建一个抽象类,其中包含DataProvider方法,然后让测试类继承该抽象类。

    Apache Superset Dashboard and SQL Exploration Skill
    Apache Superset Dashboard and SQL Exploration Skill

    Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。

    下载
    // 抽象类
    import org.testng.annotations.DataProvider;
    
    public abstract class AbstractDataProvider {
    
        @DataProvider(name = "abstractProvider")
        public Object[][] provideData() {
            return new Object[][]{
                    {true, 1},
                    {false, 0}
            };
        }
    }
    
    // 测试类
    import org.testng.annotations.Test;
    
    public class TestAbstractDataProvider extends AbstractDataProvider {
    
        @Test(dataProvider = "abstractProvider")
        public void testMethod(boolean bool, int num) {
            System.out.println("Boolean: " + bool + ", Number: " + num);
        }
    }

如何在TestNG参数化测试中使用工厂模式?

工厂模式允许你动态创建测试类的实例,并为每个实例提供不同的参数。这在需要创建多个具有不同配置的测试实例时非常有用。

  1. 创建测试类: 首先,创建一个测试类,该类包含测试方法和构造函数,构造函数接收参数。

    import org.testng.annotations.Test;
    import static org.testng.Assert.assertEquals;
    
    public class FactoryTest {
    
        private int input;
        private int expected;
    
        public FactoryTest(int input, int expected) {
            this.input = input;
            this.expected = expected;
        }
    
        @Test
        public void testAdd() {
            int result = input + 1;
            assertEquals(result, expected);
        }
    }
  2. 创建工厂类: 创建一个工厂类,该类实现org.testng.ITest接口,并包含一个方法,该方法返回测试类的实例数组。

    import org.testng.ITest;
    import org.testng.annotations.Factory;
    
    public class FactoryCreator implements ITest {
    
        private String testName;
    
        @Factory
        public Object[] createInstances() {
            Object[] result = new Object[3];
            result[0] = new FactoryTest(1, 2);
            result[1] = new FactoryTest(2, 3);
            result[2] = new FactoryTest(3, 4);
            return result;
        }
    
        @Override
        public String getTestName() {
            return testName;
        }
    
        public void setTestName(String testName) {
            this.testName = testName;
        }
    }
  3. 在testng.xml中配置工厂类: 在testng.xml文件中配置工厂类。

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
    <suite name="Factory Suite">
        <test name="Factory Test">
            <classes>
                <class name="FactoryCreator"/>
            </classes>
        </test>
    </suite>

    或者,可以直接在代码中使用@Factory注解:

    import org.testng.annotations.Factory;
    
    public class TestFactory {
    
        @Factory
        public Object[] createInstances() {
            return new Object[] {
                    new FactoryTest(10, 11),
                    new FactoryTest(20, 21)
            };
        }
    }

    testng.xml:

    <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
    <suite name="Factory Suite">
        <test name="Factory Test">
            <classes>
                <class name="TestFactory"/>
            </classes>
        </test>
    </suite>

使用工厂模式可以灵活地创建多个测试实例,并为每个实例提供不同的参数。这在需要对同一测试类进行多次测试,但每次测试的配置都不同时非常有用。

如何在参数化测试中使用CSV文件作为数据源?

使用CSV文件作为数据源,可以方便地管理和维护测试数据。

  1. 添加依赖: 确保项目中包含了处理CSV文件的依赖,例如opencsv。

    <dependency>
        <groupId>com.opencsv</groupId>
        <artifactId>opencsv</artifactId>
        <version>5.7.1</version>
    </dependency>
  2. 创建CSV文件: 创建一个CSV文件,其中包含测试数据。例如,data.csv:

    input,expected
    1,2
    3,4
    5,6
  3. 读取CSV数据: 创建一个DataProvider方法,该方法读取CSV文件中的数据,并将其转换为Object[][]。

    import org.testng.annotations.DataProvider;
    import java.io.FileReader;
    import java.io.IOException;
    import com.opencsv.CSVReader;
    import com.opencsv.exceptions.CsvException;
    
    public class CsvDataProvider {
    
        @DataProvider(name = "csvData")
        public static Object[][] provideData() throws IOException, CsvException {
            String csvFile = "src/test/resources/data.csv"; // 确保路径正确
            CSVReader reader = new CSVReader(new FileReader(csvFile));
            java.util.List<String[]> csvData = reader.readAll();
    
            // 移除header
            csvData.remove(0);
    
            Object[][] data = new Object[csvData.size()][2];
            for (int i = 0; i < csvData.size(); i++) {
                data[i][0] = Integer.parseInt(csvData.get(i)[0]);
                data[i][1] = Integer.parseInt(csvData.get(i)[1]);
            }
            return data;
        }
    }
  4. 使用DataProvider: 在测试方法中使用@Test注解的dataProvider属性指定DataProvider的名称和类。

    import org.testng.annotations.Test;
    import static org.testng.Assert.assertEquals;
    
    public class CsvTest {
    
        @Test(dataProvider = "csvData", dataProviderClass = CsvDataProvider.class)
        public void testAdd(int input, int expected) {
            int result = input + 1;
            assertEquals(result, expected);
        }
    }

这种方式可以将测试数据与测试代码分离,方便管理和维护。

如何在TestNG参数化测试中使用Excel文件作为数据源?

使用Excel文件作为数据源与CSV文件类似,但需要使用处理Excel文件的库,如Apache POI。

  1. 添加依赖: 添加Apache POI的依赖。

    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
  2. 创建Excel文件: 创建一个Excel文件,例如data.xlsx,包含测试数据。确保第一行是表头。

    input   expected
    1   2
    3   4
    5   6
  3. 读取Excel数据: 创建一个DataProvider方法,读取Excel文件中的数据。

    import org.testng.annotations.DataProvider;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.apache.poi.xssf.usermodel.XSSFSheet;
    import org.apache.poi.ss.usermodel.Row;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class ExcelDataProvider {
    
        @DataProvider(name = "excelData")
        public static Object[][] provideData() throws IOException {
            String excelFilePath = "src/test/resources/data.xlsx"; // 确保路径正确
            FileInputStream inputStream = new FileInputStream(excelFilePath);
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            XSSFSheet sheet = workbook.getSheetAt(0);
    
            List<Object[]> dataList = new ArrayList<>();
            int rowCount = sheet.getLastRowNum();
    
            for (int i = 1; i <= rowCount; i++) { // 从第二行开始读取数据,跳过表头
                Row row = sheet.getRow(i);
                int input = (int) row.getCell(0).getNumericCellValue();
                int expected = (int) row.getCell(1).getNumericCellValue();
                dataList.add(new Object[]{input, expected});
            }
    
            workbook.close();
            inputStream.close();
    
            Object[][] data = new Object[dataList.size()][2];
            for (int i = 0; i < dataList.size(); i++) {
                data[i] = dataList.get(i);
            }
    
            return data;
        }
    }
  4. 使用DataProvider: 在测试方法中使用@Test注解的dataProvider属性。

    import org.testng.annotations.Test;
    import static org.testng.Assert.assertEquals;
    
    public class ExcelTest {
    
        @Test(dataProvider = "excelData", dataProviderClass = ExcelDataProvider.class)
        public void testAdd(int input, int expected) {
            int result = input + 1;
            assertEquals(result, expected);
        }
    }

使用Excel文件作为数据源,可以方便地使用Excel工具进行数据管理和编辑。

参数化测试与数据驱动测试的区别是什么?

虽然这两个概念经常一起使用,但它们略有不同。参数化测试是一种更广泛的概念,指的是使用不同的参数值运行相同的测试用例。数据驱动测试是参数化测试的一种具体实现,其中测试数据来自外部数据源(如CSV、Excel、数据库等)。

  • 参数化测试: 指的是使用不同的参数值运行相同的测试用例,以验证不同的输入对系统的影响。参数可以来自硬编码、XML文件、DataProvider等。
  • 数据驱动测试: 是一种特殊的参数化测试,其中测试数据来自外部数据源。这意味着测试用例的行为是由外部数据驱动的。

简单来说,所有数据驱动测试都是参数化测试,但并非所有参数化测试都是数据驱动测试。

如何使用TestNG的@Optional注解?

@Optional注解允许你在@Parameters注解中指定一个参数是可选的。如果testng.xml文件中没有提供该参数的值,TestNG会使用@Optional注解指定的默认值。

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
import org.testng.annotations.Optional;
import static org.testng.Assert.assertEquals;

public class OptionalParameterTest {

    @Test
    @Parameters({"message"})
    public void testMessage(@Optional("Default Message") String message) {
        System.out.println("Message: " + message);
        assertEquals(message, "Default Message"); // 如果XML中没有提供message参数,则使用默认值
    }
}

testng.xml(不包含message参数):

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Optional Parameter Suite">
    <test name="Optional Test">
        <classes>
            <class name="OptionalParameterTest"/>
        </classes>
    </test>
</suite>

如果testng.xml包含message参数:

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Optional Parameter Suite">
    <test name="Optional Test">
        <parameter name="message" value="Custom Message"/>
        <classes>
            <class name="OptionalParameterTest"/>
        </classes>
    </test>
</suite>

@Optional注解可以使测试更加灵活,允许在不修改代码的情况下,通过XML配置文件控制测试行为。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

相关专题

更多
pdf怎么转换成xml格式
pdf怎么转换成xml格式

将 pdf 转换为 xml 的方法:1. 使用在线转换器;2. 使用桌面软件(如 adobe acrobat、itext);3. 使用命令行工具(如 pdftoxml)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

4704

2024.04.01

xml怎么变成word
xml怎么变成word

步骤:1. 导入 xml 文件;2. 选择 xml 结构;3. 映射 xml 元素到 word 元素;4. 生成 word 文档。提示:确保 xml 文件结构良好,并预览 word 文档以验证转换是否成功。想了解更多xml的相关内容,可以阅读本专题下面的文章。

6097

2024.08.01

xml是什么格式的文件
xml是什么格式的文件

xml是一种纯文本格式的文件。xml指的是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。想了解更多相关的内容,可阅读本专题下面的相关文章。

2502

2024.11.28

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3168

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5029

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3829

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

466

2026.01.19

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2825

2023.06.29

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

60

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Apache Maven 官方安装指南
Apache Maven 官方安装指南

共0课时 | 0人学习

Apache Maven 官方用户中心
Apache Maven 官方用户中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn