Junit/TestNg 增强版数据驱动 DataProvider

米阳MeYoung · 2021年09月26日 · 1741 次阅读

背景

很多测试框架都带有数据驱动的方式,如TestNG@DataProvider ,在合理使用下可以大大减少代码量,同时也便于后期维护。而熟悉TestNG的同学应该都知道,使用TestNG@DataProvider 时需要先写一个数据源,再 @Test(dataProvider=“xx”) 中引用数据源。
而慢慢看到有不少用例用的数据源,QA 是写在 Excel 等文件里面,这时就觉得直接用原生的略微麻烦了,为啥不能把数据源直接与注解的方式写在测试用例上呢?如下:

@OTPDataProvider(dataFile = "src/test/resources/excel/demo1.xlsx",sheetName = "sheet1")
@Test
public void excelData(JSONObject jsonObject) {
    log.info(jsonObject.toJSONString());
}

TestNG 监听器 -- IAnnotationTransformer2

为了实现上面的效果,查阅 TestNG 官方文档,发现有个 IAnnotationTransformer2 接口, IAnnotationTransformer2 接口继承了 IAnnotationTransformer,而IAnnotationTransformer 接口提供了 public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) 方法,从方法说明上看这个接口可以在@Test用例被调用前操作相应的注解。
基于这个监听器的能力,那就自然会想到,如果在 @Test 用例执行时,动态的生成@DataProvider ,并 @Test上动态添加 dataProvider属性不就可以。

核心代码实现

实现 transform()

核心代码其实就 2 行:
// 动态设定 dataProvider = “xxxx”
annotation.setDataProvider(OTPDataProvider.NAME);
// 动态设定 @DataProvider 的 class
annotation.setDataProviderClass(ExcelDataProvider.class);

    /**
     * 从 IAnnotationTransformer 接口继承 操作 @Test
     *
     * @param annotation
     * @param testClass
     * @param testConstructor
     * @param testMethod
     */
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        boolean annotationDataProvider = testMethod.isAnnotationPresent(OTPDataProvider.class);
        if (annotationDataProvider) {
            annotation.setDataProvider(OTPDataProvider.NAME);
            DataProviderUtil.chooseData(annotation, testMethod);
        }

//        重跑
        IRetryAnalyzer retry = annotation.getRetryAnalyzer();
        if (retry == null) {
            annotation.setRetryAnalyzer(TestNGRetry.class);
        }
    }

    public void chooseData(ITestAnnotation annotation, Method method) {
        OTPDataProvider otpDataProvider = method.getAnnotation(OTPDataProvider.class);
        String file = otpDataProvider.dataFile().toLowerCase();
        if (file.endsWith(JSON_TYPE)) {
            annotation.setDataProviderClass(JsonDataProvicer.class);
        } else if (!"".equals(otpDataProvider.sqlQuery())) {
            annotation.setDataProviderClass(SqlDataProvider.class);
        } else if (file.endsWith(TEXT_TYPE)) {
            annotation.setDataProviderClass(TxtDataProvider.class);
        } else if (file.endsWith(SUPER_EXCEL_TYPE) || file.endsWith(EXCEL_TYPE)) {
//            excel
            annotation.setDataProviderClass(ExcelDataProvider.class);
        }else {
            log.error("OTPDataProvider 属性值有误 请认真检查!");
        }
    }

@DataProvider(name = OTPDataProvider.NAME)
public Iterator<Object[]> dataJson(Class testClass, ITestNGMethod method, ITestContext c) {
    OTPDataProvider otpDataProvider = DataProviderUtil.getDataProvderAn(testClass, method);
    String dataFile = otpDataProvider.dataFile();
    String sheetName = otpDataProvider.sheetName();
    return ExcelDataProvider.getData(dataFile, sheetName);
}

效果展示


怎么解析 Json Excel SQL TXT 等,以及添加一个新注解我就不发了,通用的技术,这边重点只想说明可以通过监听器去实现数据驱动的一种扩展。
原文地址:https://www.yuque.com/miyang.meyoung/other/gkomw5

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册