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

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中的参数化使用指南。用户已经提到了他们之前的提问和回答,我需要参考之前的引用内容并结合用户的问题来生成详细的回答。 首先,用户提到了几个引用,其中引用[1]和引用[2]直接涉及TestNG参数化,特别是参数的作用范围和@DataProvider的使用。引用[3]到引用[5]可能相关,但需要看是否有必要包含在回答中。用户现在的问题是询问TestNG参数化的详细用法,所以我需要重点放在参数化的两种主要方法:通过testng.xml和@DataProvider。 用户之前的问题是关于Java输出对象类型,而现在的转向是TestNG参数化,可能需要我调整回答结构,确保清晰易懂。我需要确定用户可能需要的详细步骤,例如如何声明参数,如何使用@DataProvider,以及可能遇到的注意事项。 接下来,我需要考虑用户可能的实际应用场景,比如他们可能在编写自动化测试用例时,需要不同的参数组合来测试同一功能。因此,示例代码和具体步骤会很有帮助。同时,用户可能对参数优先级、数据驱动测试以及动态参数生成感兴趣,所以需要覆盖这些方面。 需要注意的是,用户提供的引用中有提到参数在suite和test标签中的优先级,以及@DataProvider返回二维数组的结构。这些点必须包含在回答中,以确保准确引用。此外,引用[5]提到的监听器可能和参数化关系不大,但如果涉及到测试方法的调用前后处理,可能需要简要提及,但根据用户问题,可能不需要深入。 最后,生成相关问题时要考虑用户可能进一步探索的方向,例如参数覆盖规则、与JUnit的区别、动态参数生成技巧以及常见错误处理。这些问题可以帮助用户更深入地理解TestNG参数化的各个方面。</think>在TestNG中实现参数化测试主要有两种方式,以下是详细使用指南: ### 一、XML参数化(静态参数) #### 1. 配置参数优先级 在`testng.xml`中参数作用域遵循: $$套件级 < 测试级 < 类级 < 方法级$$ 优先级顺序:方法级 > 类级 > 测试级 > 套件级[^1] ```xml <suite name="Suite"> <parameter name="env" value="prod"/> <!-- 套件级参数 --> <test name="Test"> <parameter name="env" value="dev"/> <!-- 测试级覆盖 --> <classes> <class name="TestCases"/> </classes> </test> </suite> ``` #### 2. 测试类接收参数 ```java public class TestCases { @Test @Parameters({"username", "password"}) public void loginTest(String user, String pwd) { System.out.println("用户:" + user + " 密码:" + pwd); } } ``` ### 二、@DataProvider动态参数化 #### 1. 基础数据驱动 ```java @DataProvider(name = "searchData") public Object[][] provideData() { return new Object[][] { {"Java", 10}, {"Python", 20}, {"TestNG", 30} }; } @Test(dataProvider = "searchData") public void searchTest(String keyword, int count) { // 执行搜索逻辑 } ``` #### 2. 类型自动转换特性 TestNG支持自动类型转换: ```java @DataProvider public Object[][] numberData() { return new Object[][] { {"100"}, {200} }; } @Test(dataProvider = "numberData") public void testNumbers(int num) { // 字符串"100"自动转为int Assert.assertTrue(num > 0); } ``` ### 三、混合参数化模式 #### 1. XML参数与DataProvider结合 ```java @Test(dataProvider = "dbData") @Parameters("timeout") public void dbOperation(int timeout, String query) { // timeout来自XML配置 // query来自DataProvider } ``` ### 四、高级技巧 1. **动态生成参数**:通过Excel/CSV读取测试数据 ```java @DataProvider public Object[][] excelData() throws IOException { List<Object[]> data = new ArrayList<>(); // 使用Apache POI读取Excel数据 return data.toArray(new Object[0][]); } ``` 2. **方法参数传递**:通过`Method`参数获取测试方法信息 ```java @DataProvider public Object[][] methodData(Method method) { if(method.getName().equals("testLogin")) { return new Object[][] { {"admin", "123456"} }; } return new Object[][] { {"guest", "guest"} }; } ``` ### 五、最佳实践 1. 使用`@Optional`设置默认值 ```java @Test @Parameters("retryCount") public void retryTest(@Optional("3") int retry) { // 当未配置参数时默认使用3次重试 } ``` 2. 数据驱动测试报告优化 ```java @Test(dataProvider = "data") public void test(ITestContext context, String param) { context.setAttribute("param", param); // 在报告中显示具体参数 } ``` [^1]: 参数优先级规则参考TestNG官方文档的参数作用域定义 [^2]: 数据驱动实现基于《Selenium与TestNG的自动化测试实战指南》第二章 --相关问题-- 1. 如何在TestNG中实现多线程参数化测试? 2. DataProvider能否返回Iterator类型的数据源? 3. TestNG参数化与JUnit参数化的核心区别是什么? 4. 如何处理参数化测试中出现的空值情况?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值