TestNg参数化测试之读取csv文件

本文介绍如何使用TestNG框架结合CSV文件进行数据驱动测试。通过创建CSV文件存放测试数据,并利用CSVData类解析这些数据,最终在CalculatorCSV测试类中实现自动化的测试案例执行。文章展示了完整的实现步骤及示例代码。

1、新建csv文档,准备好测试数据

在当前工程的resources目录下,新建文件名为add的csv文档

这里写图片描述

打开csv文件,构造n1、n2、r1三个参数数据
这里写图片描述

2、新建一个CSVData类用来获取csv文件中的数据

package com.mcj.testng;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;

public class CSVData implements Iterator<Object[]> {
    BufferedReader in;
    ArrayList<String> csvList=new ArrayList<String>();
    int rowNum=0;     //行数
    int columnNum=0;  //列数
    int curRowNo=0;   //当前行数
    String columnName[];  //列名
    /**
     * 在TestNG中由@DataProvider(dataProvider = "name")修饰的方法
     * 取csv文件数据时时,调用此类构造方法(此方法会得到列名并将当前行移到下以后)执行后,转发到
     * TestNG自己的方法中去,然后由它们调用此类实现的hasNext()、next()方法
     * 得到一行数据,然后返回给由@Test(dataProvider = "name")修饰的方法,如此
     * 反复到数据读完为止
     * @param fileName
     * @throws IOException 
     */
    public CSVData(String fileName) throws IOException{
        File directory=new File(".");
        String path=".src.resources.";
        String absolutePath=directory.getCanonicalPath()+path.replaceAll("\\.", Matcher.quoteReplacement("\\"))+fileName;
        System.out.println(absolutePath);
        File csv=new File(absolutePath);
        in=new BufferedReader(new FileReader(csv));
        while (in.ready()) {            
            csvList.add(in.readLine());
            this.rowNum++;
        }       
        String[] str=csvList.get(0).split(",");
        this.columnNum=str.length; 
        columnName=new String[columnNum];
        //获取列名
        for (int i = 0; i < columnNum; i++) {
            columnName[i]=str[i];
        }
        this.curRowNo++;
    }
    @Override
    public boolean hasNext() {
        // TODO Auto-generated method stub
        if(rowNum==0||curRowNo>=rowNum){
            try {
                in.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return false;
        }else{
            return true;
        }       
    }
    /**
     * 获取一组参数,即一行数据
     */
    @Override
    public Object[] next() {
        // TODO Auto-generated method stub
        Map<String,String> s=new TreeMap<String,String>();
        String csvCell[]=csvList.get(curRowNo).split(",");
        for(int i=0;i<this.columnNum;i++){
            s.put(columnName[i], csvCell[i]);           
        }
        Object[] d=new Object[1];
        d[0]=s;
        this.curRowNo++;
        return d;
    }

    @Override
    public void remove() {
        // TODO Auto-generated method stub
        throw new UnsupportedOperationException("remove unsupported");
    }

}

3、创建TestNg测试类CalculatorCSV

package com.mcj.testng;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class CalculatorCSV {
    Calculator cal=new Calculator();

    @DataProvider(name="num")
    public Iterator<Object[]> Numbers() throws IOException{      
        return (Iterator<Object[]>)new CSVData("add.csv");
    }
    @Test(dataProvider="num")
    public void testAdd(Map<String, String> data){
        float num1=Float.parseFloat(data.get("n1"));
        float num2=Float.parseFloat(data.get("n2"));
        float expectedResult=Float.parseFloat(data.get("r1"));  
        Float actual=cal.add(num1, num2);
        Assert.assertEquals(actual, expectedResult);
    }
}

4、运行结果

PASSED: testAdd({n1=3, n2=2, r1=5})
PASSED: testAdd({n1=-3, n2=8, r1=5})
FAILED: testAdd({n1=5.4, n2=6.6, r1=11.9})
java.lang.AssertionError: expected [11.9] but found [12.0]
at org.testng.Assert.fail(Assert.java:94)

<think> 首先,用户的问题是:“我想查找在 TestNG 中实现动态参数化测试的方法 请问TestNG 实现动态参数化测试的方法”。这翻译成英文是“I want to find a way to implement dynamic parameterized testing in TestNG. Please tell me the method for implementing dynamic parameterized testing in TestNG.” 我需要基于提供的引用来回答。引用来自用户给出的内容,我必须使用它们来构建回答。记住系统级指令:所有行内数学表达式用$...$,独立公式用$$...$$,但这里可能不需要数学,因为主题是TestNG测试框架。回答必须用中文生成相关问题。 关键点: - 引用[1]提到:测试类中至多被放到一个构造函数签,这样TestNG才能用testng.xml中的参数实例化类。 - 引用[2]讨论了TestNG的优点,比如灵活的方法命名、支持动态传参、注解等。 - 引用[3]描述如何使用@DataProvider传递参数,特别是第一个参数是java.lang.reflect.Method来获取当前测试方法名。 - 引用[4]展示如何在@BeforeClass中使用@Parameters来获取动态参数。 - 引用[5]提到Jenkins+Maven+TestNG动态入参的自动化构建。 用户的问题是关于“动态参数化测试”在TestNG中的实现。动态参数化测试通常意味着测试方法可以接收不同的参数值,而这些值可以在运行时动态生成或从外部源获取。 核心方法从引用中提取: 1. **使用@DataProvider注解**:引用[3]详细说明了@DataProvider。它允许你定义一个方法返回一个数组的数组,每个元素是一组参数用于测试方法。测试方法通过@Test(dataProvider = "name")来使用。特别地,可以使用Method参数来根据测试方法动态返回数据。 示例代码: ```java @DataProvider(name = "dp") public Object[][] createData(Method m) { System.out.println(m.getName()); // 打印测试方法名 return new Object[][]{ new Object[]{ "Cedric" }}; } @Test(dataProvider = "dp") public void test1(String s) { } @Test(dataProvider = "dp") public void test2(String s) { } ``` 2. **使用@Parameters注解**:引用[4]提到在@BeforeClass中使用@Parameters从testng.xml获取参数。 示例: ```java @BeforeClass @Parameters({"swimlane"}) public void beforeClass(String swimlane) throws Exception { this.swimlane = swimlane; } ``` 这里的参数来自testng.xml文件。 3. **结合外部文件或动态数据**:引用[5]提到Jenkins+Maven+TestNG动态入参,这可能涉及从外部源如属性文件、数据库或命令行参数获取数据。 TestNG支持动态参数化的主要方式是通过@DataProvider,因为它允许在运行时生成数据。@Parameters通常用于从XML配置文件获取静态参数,但结合代码也可以动态处理。 回答结构: - 因为用户要求“帮助用户逐步解决问题”,我应该结构清晰。 - 步骤: 1. 介绍动态参数化测试的概念。 2. 使用@DataProvider注解实现动态参数化- 解释@DataProvider如何工作。 - 提供示例代码(引用[3])。 - 提到动态数据源的可能性,如从文件或数据库。 3. 使用@Parameters注解(如果相关),但对于动态性,@DataProvider更灵活。 4. 可能提到其他方法或最佳实践。 - 最后,生成相关问题。 回答语言:中文。 引用标识:在相关段落末尾添加[^n],如[^1]、[^2]等。 相关问题:基于内容生成几个相关问题,放在最后。 可能的回答大纲: 1. **简介**:解释TestNG中动态参数化测试的含义和好处。 2. **主要方法**:详细说明使用@DataProvider。 - 代码示例。 3. **其他方法**:简要提及@Parameters或数据驱动测试的其他形式。 4. **实践建议**:如何结合外部工具(如从Jenkins传入参数)。 5. **生成相关问题**。 确保代码块正确格式:使用```java```等。 现在,整合引用: - [^1] 提到构造函数用于初始化值,但直接相关是@Parameters。 - [^2] 提到TestNG支持动态传参和@DataProvider。 - [^3] 核心引用,提供@DataProvider示例。 - [^4] @Parameters示例。 - [^5] 外部集成。 在回答中引用这些。 </think> 以下是针对您查询“在 TestNG 中实现动态参数化测试的方法”的详细解答。我将基于您提供的引用内容(尤其是引用[1]、[2]、[3]、[4]、[5]),逐步解释动态参数化测试的实现方法。TestNG 的动态参数化测试允许您为单个测试方法提供多组输入参数,这些参数可以在运行时动态生成(例如从外部文件、数据库或命令行获取),而非固定写死,从而实现更灵活的数据驱动测试。核心方法是使用 `@DataProvider` 注解,辅以 `@Parameters` 等其他特性。下面我将从概念到具体实现逐步说明。 ### 1. **动态参数化测试的概念与优势** 动态参数化测试是指测试方法能接收动态变化的参数值,这些值在测试运行时才确定。例如,您可以从 CSV 文件、数据库或 Jenkins 构建参数中读取数据,减少硬编码,方便维护和扩展测试用例。TestNG 支持此功能,使其成为 Java 测试框架的首选,因为它支持灵活的参数传递和注解机制[^2]。 ### 2. **主要实现方法:使用 `@DataProvider` 注解** `@DataProvider` 是 TestNG 实现动态参数化测试的核心方式。它允许您定义一个数据提供方法,返回一个二维数组(每组数据对应一组测试参数),然后通过 `@Test(dataProvider = "providerName")` 将数据注入到测试方法中。此方法高度灵活,支持根据测试方法名动态生成数据。 #### 步骤说明: - **定义数据提供方法**:使用 `@DataProvider(name = "yourProviderName")` 注解一个方法。该方法可以返回 `Object[][]`,其中每个内层数组代表一组测试参数。 - **注入测试方法**:在 `@Test` 注解中指定 `dataProvider = "yourProviderName"`,测试方法参数需匹配数据提供方法返回的类型。 - **动态获取数据**:数据提供方法可以接收 `java.lang.reflect.Method` 参数,用于根据当前测试方法名动态调整数据(引用[3]示例)。 #### 示例代码(基于引用[3]): ```java import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.reflect.Method; public class DynamicParameterTest { // 定义数据提供器,支持动态方法名 @DataProvider(name = "dynamicData") public Object[][] createData(Method method) { // 打印当前测试方法名,用于动态逻辑判断 System.out.println("Generating data for method: " + method.getName()); // 动态返回数据:这里简化示例,实际可从文件、数据库或外部源读取 if (method.getName().equals("test1")) { return new Object[][]{ {"Param1_for_test1"} }; } else { return new Object[][]{ {"DefaultParam"} }; } } // 测试方法1,使用动态数据 @Test(dataProvider = "dynamicData") public void test1(String param) { System.out.println("test1 executed with parameter: " + param); } // 测试方法2,复用同一数据提供器 @Test(dataProvider = "dynamicData") public void test2(String param) { System.out.println("test2 executed with parameter: " + param); } } ``` - **运行结果**:当运行 `test1` 时,输出参数为 `"Param1_for_test1"`;运行 `test2` 时,输出 `"DefaultParam"`。这演示了如何基于方法名动态决定参数值。 - **优势**:支持运行时动态生成数据(如从 JSON 文件读取),避免硬编码,提高测试重用性[^3]。 #### 动态数据源扩展: - **外部数据源**:在 `createData` 方法中,可以使用 `FileReader`、`JDBC` 或第三方库(如 Apache Commons CSV读取外部数据。例如,Jenkins 构建时可传入参数文件路径,实现 CI/CD 集成[^5]。 - **数据驱动测试**:结合 TestNG 的 `@Factory` 注解,可以批量生成测试实例,适用于大规模参数化场景。 ### 3. **辅助方法:使用 `@Parameters` 注解** `@Parameters` 适用于从 `testng.xml` 文件获取静态或半动态参数,常用于初始化测试环境。相比 `@DataProvider`,它更简单但不直接支持运行时动态生成数据。通常用于类级别的参数设置(如数据库连接字符串)。 #### 步骤说明: - **在 `testng.xml` 中定义参数**:例如: ```xml <suite name="Suite"> <parameter name="username" value="testUser" /> <test name="Test"> <classes> <class name="com.example.TestClass" /> </classes> </test> </suite> ``` - **在测试类中使用参数**:例如在 `@BeforeClass` 或测试方法中注入参数(引用[4]示例)。 #### 示例代码: ```java import org.testng.annotations.Parameters; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class ParameterTest { private String swimlane; // 从 testng.xml 获取参数 @BeforeClass @Parameters({"swimlane"}) public void setup(String swimlane) { this.swimlane = swimlane; // 初始化类字段 System.out.println("Initialized swimlane: " + swimlane); } @Test public void validateSwimlane() { System.out.println("Testing with swimlane: " + this.swimlane); } } ``` - **优势**:简单易用,适合配置类初始化参数[^4]。 - **局限性**:参数值在 XML 中静态定义,如需动态化,需结合 Jenkins 或 Maven 传递命令行参数(如 `-Dswimlane=value`),再在 `testng.xml` 中使用 `${variable}` 语法引用[^5]。 ### 4. **最佳实践与注意事项** - **组合使用**:在实际项目中,常混合使用 `@DataProvider` 和 `@Parameters`。例如,`@Parameters` 用于环境配置,`@DataProvider` 用于测试数据。 - **动态性与性能**:`@DataProvider` 支持运行时计算,但需注意数据生成效率(如避免大数据集导致内存溢出)。推荐懒加载或流式处理。 - **外部集成**:在 CI/CD 工具(如 Jenkins)中,通过 Maven 传递动态参数。示例 Maven 命令: ```shell mvn test -Dtest=DynamicParameterTest -Ddata.source=dynamic_values.csv ``` 然后在代码中读取 `System.getProperty("data.source")`[^5]。 - **错误处理**:确保数据提供方法正确处理边界情况(如空值或无效输入),避免测试失败。 ### 总结 在 TestNG 中,动态参数化测试主要通过 `@DataProvider` 实现,它允许在运行时动态生成或获取参数值,支持高度灵活的测试场景。`@Parameters` 则适合从配置文件获取初始化参数。结合外部工具(如 Jenkins 或 Maven),可构建自动化动态测试流程[^2][^3][^5]。如果您提供更多具体需求(如数据源类型),我可以进一步优化实现方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值