Ohhnews

分类导航

$ cd ..
DZone Java原文

Java API自动化测试:使用TestNG Iterator优化大规模数据驱动测试

#api测试#java#testng#自动化测试#数据驱动

上一篇文章中,我们探讨了如何使用 Object 数组和 TestNG 的 @DataProvider 注解来实现数据驱动测试。虽然这种方法对于中小型数据集非常有效,但在处理海量数据时并不理想。为了解决这一局限性,TestNG 还支持使用 Iterator(迭代器),它为管理大型和动态数据集提供了更高效的方式。本文重点介绍如何使用 TestNG 的 IteratorDataProvider 注解来执行数据驱动的 API 自动化测试。

使用 @DataProvider 和 Iterator 进行数据驱动测试

设置和配置与之前的教程中讨论的内容保持一致,无需额外的依赖项或项目配置。我们将继续使用 RESTful e-commerce 演示应用中的同一个 POST /addOrder API。以下是该 API 请求体的架构:

$ cat
[
  {
    "user_id": "string",
    "product_id": "string",
    "product_name": "string",
    "product_amount": 0,
    "qty": 0,
    "tax_amt": 0,
    "total_amt": 0
  }
]

创建 POJO 类

让我们为 Order 对象创建一个 POJO 类,该类将在数据提供程序方法中使用。

$ java
@Getter
@Setter
@AllArgsConstructor
@ToString(exclude = "expectedStatus")
public class Order {
    @JsonProperty("user_id")
    private String userId;
    @JsonProperty("product_id")
    private String productId;
    @JsonProperty("product_name")
    private String productName;
    @JsonProperty("product_amount")
    private int productAmount;
    private int qty;
    @JsonProperty("tax_amt")
    private int taxAmt;
    @JsonProperty("total_amt")
    private int totalAmt;
    private int expectedStatus;
}

代码解析

  • @Getter@Setter 注解会在编译时自动为所有字段生成 getter 和 setter 方法。
  • @AllArgsConstructor 注解会创建一个接受所有字段作为参数的构造函数,从而更容易使用 Order 对象定义测试数据。
  • @ToString 注解会自动生成 toString() 方法,并排除 expectedStatus 字段。这确保了在测试执行后能正确打印 Order 对象中的值。
  • @JsonProperty 注解用于指示 Jackson 如何将 JSON 字段名称映射到对应的 Java 变量。
  • 该 POJO 中定义的变量代表了 Order 对象的字段。
  • 额外添加的 expectedStatus 字段用于在测试期间验证状态码,通过灵活的输入和预期的状态码比对,有助于验证有效和无效的测试用例。

创建数据提供程序方法

让我们定义一个使用 Iterator 返回测试数据的数据提供程序方法:

$ java
@DataProvider(name = "orderData")
public Iterator<Order> getOrderData() {
    List<Order> orderList = new ArrayList<>();
    orderList.add(new Order("1", "79", "IPhone 17 Pro", 6999, 1, 699, 7698, 201));
    orderList.add(new Order("2", "81", "Samsung Galaxy S25", 7999, 1, 799, 8798, 201));
    orderList.add(new Order("2", "87", "iPad SE", 4550, 1, 455, 5005, 201));
    orderList.add(new Order("4", "13", "Macbook Pro", 9999, 1, 999, 10098, 201));
    orderList.add(new Order("5", "19", "Macbook Air", 8999, 1, 899, 9898, 201));
    return orderList.iterator();
}

代码解析

此代码通过将多个 order 对象存储在 ArrayList 中来支持数据驱动测试,每个对象代表一个独立的测试用例。

  • getOrderData() 方法上的 @DataProvider 注解告诉 TestNG 该方法用于提供测试数据。名称 "orderData" 用于将此数据提供程序链接到测试方法。
  • getOrderData() 方法返回一个 Iterator<Order>,TestNG 使用它一次获取一个 order 对象,每个对象对应一个独立的测试用例。
  • 测试数据存储在 ArrayList 中,这允许在执行过程中灵活存储、轻松修改并高效迭代多个测试用例。

编写 API 自动化测试

使用 REST Assured 编写 API 自动化测试,并将 dataProvider 参数传递给 @Test 注解,以指示 TestNG 从中获取所需的数据集。

$ java
@Test(dataProvider = "orderData")
public void testCreateOrder(Order order) {
    List<Order> orderList = List.of(order);
    given()
        .contentType(ContentType.JSON)
    .when()
        .log().all()
        .body(orderList)
        .post("http://localhost:3004/addOrder")
    .then()
        .log().all()
        .statusCode(order.getExpectedStatus())
        .and()
        .assertThat()
        .body("message", equalTo("Orders added successfully!"));
}

代码解析

testCreateOrder() 方法使用 orderData DataProvider 实现了数据驱动测试,允许同一测试使用不同的 order 对象多次运行。由于 API 端点在请求体中需要一个订单列表,因此在发送 POST 请求之前,每个 order 都通过 List.of(order) 被包装在 List 中。测试随后通过检查预期的状态码并断言返回了成功消息 "Orders added successfully" 来验证响应。

如需深入了解如何使用强大的断言技术验证状态码和响应体,请查看我之前关于如何在 Java API 测试中使用 REST Assured 进行响应验证的文章。

测试执行

当测试运行时,TestNG 会自动多次执行 testCreateOrder() 方法,每次使用 orderData DataProvider 中的不同数据集。这使得检查 API 是否正确处理各种输入变得非常容易。

总结

在 TestNG DataProvider 中使用 Iterator 可以高效处理大型或动态数据集,因为它一次只提供一个测试用例,而无需将整个数据集加载到内存中。与使用 Object 数组 相比,这使得测试更具内存友好性和可扩展性。此外,它还为动态生成数据或从文件、数据库等外部源读取数据提供了灵活性。

祝测试愉快!