其他分享
首页 > 其他分享> > Testng(三):加载外部数据

Testng(三):加载外部数据

作者:互联网

1 概述

对于一个函数或者一个流程,给定一个输入,应当返回一个结果

输入指参数或条件的组合,也就构成不同的测试场景

结果即程序对输入的处理,将其与预期结果比对,便可知当前测试场景功能的正确性

当这些数据以外部文件的形式存储时,就可以很方便地修改追加,而不用重新调整代码

2 @DataProvider

在Testng中,@DataProvider负责向测试方法提供数据,返回Object[][]对象

于是可以考虑,在@DataProvider方法中,实现读取外部文件,并将文件的内容以Object[][]形式返回

方案:

  1. 每个方法对应各自的dataProvider,读取各自的数据文件;易于实现,但代码过于冗余,并且数据文件太零散,读频繁
  2. 所有方法对应一个dataProvider,dataProvider根据调用的方法名选择对应的测试数据;实现复杂,且需要考虑并行,但代码精简
public class DataDriver {
    public static Map<String, Object[][]> data = null;

    @DataProvider(name = "dp")
    public static Object[][] getData(Method method) {
        if (data == null || data.get(method.getName()) == null) {
            return new Object[][] {};
        }
        return data.get(method.getName());
    }
}

这里选择第2种方式,但是并没有读外部文件,只提供按方法名选取数据

考虑到测试用例过多,如果一次性将所有用例数据加载到内存,会过于臃肿,所以决定只加载当前case的数据

3 TestCase

@BeforeClass阶段初始化数据,@AfterClass阶段回收

读取数据时,封装了工具类;根据不同的数据载体,可以编写多套工具类

测试方法均指向同一个dataProvider,不要忘记加上dataProviderClass属性

public class IpCase {
    @BeforeClass
    public void setup() {
        String caseFullName = this.getClass().getName();
        String caseName = caseFullName.substring(caseFullName.lastIndexOf('.') + 1);
        DataDriver.data = ExcelUtil.readExcel(caseName);
    }

    @AfterClass
    public void teardown() {
        DataDriver.data.clear();
    }

    @Test(dataProvider = "dp", dataProviderClass = DataDriver.class)
    public void isIpv41(String ip, boolean expected) {
        boolean actual = ip != null;
        Assert.assertEquals(actual, expected);
    }

    @Test(dataProvider = "dp", dataProviderClass = DataDriver.class)
    public void isIpv6(String ip, boolean expected) {
        boolean actual = ip != null;
        Assert.assertEquals(actual, expected);
    }
}

4 处理Excel文件

数据存储,可以使用Excel,TXT,数据库也行,挑选一个易于维护、易于阅读的载体即可

这里我们暂定为excel,使用poi包进行解析

excel的名称要求与TestCase一致(IpCase.xlsx),且sheet名称对应各个测试方法(isIpv4, isIpv6),这样便可以根据方法名获取相应的测试数据

isIpv4对应数据如下,首行为标题,解析时注意跳过

IPExpected
1.1.1.1TRUE
2.2.2.256FALSE

isIpv6对应数据如下

IPExpected
::1TRUE
FF01::1101TRUE
public class ExcelUtil {
    private static final String SUFFIX_2007 = ".xlsx";

    public static Map<String, Object[][]> readExcel(String caseName) {
        Map<String, Object[][]> result = new HashMap<>();
        InputStream is = null;

        try {
            is = ExcelUtil.class.getClassLoader().getResourceAsStream(String.format("TestCase/%s%s", caseName, SUFFIX_2007));
            XSSFWorkbook workbook = new XSSFWorkbook(is);

            for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
                Sheet sheet = workbook.getSheetAt(sheetNum);

                int rows = sheet.getLastRowNum();
                if (rows <= 0) continue;
                int cols = sheet.getRow(1).getLastCellNum();
                Object[][] data = new Object[rows][cols];

                for (int rowNum = 1; rowNum <= rows; rowNum++) {
                    Row row = sheet.getRow(rowNum);
                    for (int celNum = 0; celNum < cols; celNum++) {
                        Cell cell = row.getCell(celNum);

                        Object cellValue = null;
                        CellType cellType = cell.getCellTypeEnum();
                        if (cellType == CellType.BOOLEAN) {
                            cellValue = cell.getBooleanCellValue();
                        } else if (cellType == CellType.STRING) {
                            cellValue = cell.getStringCellValue();
                        } else if (cellType == CellType.NUMERIC) {
                            cellValue = cell.getNumericCellValue();
                        } else {
                            cellValue = "";
                        }

                        data[rowNum - 1][celNum] = cellValue;
                    }
                }
                result.put(sheet.getSheetName(), data);
            }
        } catch (IOException e) {
            System.out.println("File not found: " + caseName);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}

5 @Test注解转换

当测试方法需要加载数据时,都不得不指定属性dataProvider = "dp", dataProviderClass = DataDriver.class

为了省事,可以使用IAnnotationTransformer监听器

public class TestAnnotationTransformer implements IAnnotationTransformer {
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        String[] groups = annotation.getGroups();
        for(String group: groups) {
            if (group.equals("dp")) {
                annotation.setDataProvider("dp");
                annotation.setDataProviderClass(DataDriver.class);
                break;
            }
        }
    }
}

6 后续优化

标签:dataProvider,String,外部,public,DataDriver,Testng,class,dp,加载
来源: https://blog.csdn.net/weixin_44129801/article/details/122315867