ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Testng(三):加载外部数据

2022-01-05 09:02:37  阅读:205  来源: 互联网

标签:dataProvider String 外部 public DataDriver Testng class dp 加载


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监听器

  • 约定方法名包含“Dp”、“_dp”或其他你喜欢的后缀时,自动给@Test注解添加dataProvider属性
  • 指定group名,假设group = dp的测试方法均自动补充属性
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 后续优化

  • 目前只有excel解析工具类,且只支持2007版,可以补充2007以下版本支持
  • Excel数据类型判断,浮点数、日期等类型需要加强
  • 并行执行时,DataDriver.data可能冲突,需要将引用迁移到Case类下

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有