testng参数化测试主要依赖三种方式:1. 使用@parameters注解结合testng.xml配置参数值,优点是简单直接但不够灵活;2. 使用@dataprovider注解在代码中动态生成参数,支持object[][]或iterator

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

解决方案

TestNG参数化测试主要依赖以下几种方式:
立即学习“Java免费学习笔记(深入)”;

-
@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文件:
这种方式的优点是简单直接,缺点是参数值写死在XML文件中,不够灵活。
-
@DataProvider注解
@DataProvider注解允许你定义一个方法,该方法返回测试用例需要的参数值。这个方法返回的数据可以是Object[][]或Iterator。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方式的优点是参数值可以在代码中动态生成,非常灵活。 -
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:
这种方式结合了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方法,然后让测试类继承该抽象类。
移动端无限滚动加载瀑布流下载里面有2个文件夹。其中这个文件名是:finishing,是我项目还没有请求后台的数据的模拟写法。请求后台数据之后,瀑布流的js有一点点变化,放在文件名是:finished。变化在于需要穿参数到后台,和填充的内容都用后台的数据填充。看自己项目需求来。由于chrome模拟器是不允许读取本地文件json的,所以如果你要进行测试,在hbuilder打开项目就可以看到效果啦,或者是火狐浏览器。
// 抽象类 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参数化测试中使用工厂模式?
工厂模式允许你动态创建测试类的实例,并为每个实例提供不同的参数。这在需要创建多个具有不同配置的测试实例时非常有用。
-
创建测试类: 首先,创建一个测试类,该类包含测试方法和构造函数,构造函数接收参数。
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); } } -
创建工厂类: 创建一个工厂类,该类实现
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; } } -
在testng.xml中配置工厂类: 在testng.xml文件中配置工厂类。
或者,可以直接在代码中使用
@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:
使用工厂模式可以灵活地创建多个测试实例,并为每个实例提供不同的参数。这在需要对同一测试类进行多次测试,但每次测试的配置都不同时非常有用。
如何在参数化测试中使用CSV文件作为数据源?
使用CSV文件作为数据源,可以方便地管理和维护测试数据。
-
添加依赖: 确保项目中包含了处理CSV文件的依赖,例如
opencsv。com.opencsv opencsv 5.7.1 -
创建CSV文件: 创建一个CSV文件,其中包含测试数据。例如,
data.csv:input,expected 1,2 3,4 5,6
-
读取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.ListcsvData = 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; } } -
使用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。
-
添加依赖: 添加
Apache POI的依赖。org.apache.poi poi 5.2.3 org.apache.poi poi-ooxml 5.2.3 -
创建Excel文件: 创建一个Excel文件,例如
data.xlsx,包含测试数据。确保第一行是表头。input expected 1 2 3 4 5 6
-
读取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 -
使用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参数):
如果testng.xml包含message参数:
@Optional注解可以使测试更加灵活,允许在不修改代码的情况下,通过XML配置文件控制测试行为。









