原创:testng 参数化(4)- 使用注解获取csv文件
简介
前篇提到,使用@DataProvider读取csv中的数据文件,来逐行执行测试用例。已经很好的实现了数据和逻辑的完全隔离,
并且代码结构也是相当清晰明了。再进一步,使用java注解方式来引入csv文件,则会使得文件结构更加简洁
使用注解来引入csv文件,从而逐行执行测试用例
java注解简单介绍
java注解一种标记式高耦合的配置方式。注解可以配置在方法上,类上,字段属性上,几乎需要配置的地方都可以进行注解。
注解的本质
java.lang.annotation.Annotation 接口中是这样来描述
The common interface extended by all annotation types, 意思是所有注解都继承了Annotation接口
举一个例子,Override注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
实际上就是:
public interface Override extends Annotation{
}
所以,注解的本质就是一个继承了 Annotation 接口的接口
可以把注解理解为一种特殊的注释,这种注释可以用代码来解析。
元注解
修饰注解的注解为元注解,用在注解的定义上
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
JAVA 中有以下几个『元注解』:
- @Target:
- @Retention:
- @Documented
- @Inherited:
@Target 用于指明注解的作用目标
作用目标是一个枚举类型,有以下一些值:
- ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
- ElementType.FIELD:允许作用在属性字段上
- ElementType.METHOD:允许作用在方法上
- ElementType.PARAMETER:允许作用在方法参数上
- ElementType.CONSTRUCTOR:允许作用在构造器上
- ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
- ElementType.ANNOTATION_TYPE:允许作用在注解上
- ElementType.PACKAGE:允许作用在包上
@Retention:用于指明注解的生命周期
- RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
- RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
- RetentionPolicy.RUNTIME:永久保存,可以反射获取
自定义注解
自定义注解中包含文件名称
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamFile {
public String fileName() default "";
}
读取注解中的数据
第一步,获取到注解中fileName文件名称
构造一个监听器,每次执行DataProvider之前,读取测试方法中的注解上的文件名称
@Listeners
public class DataProviderListenerImp implements IDataProviderListener {
@Override
public void beforeDataProviderExecution(IDataProviderMethod dataProviderMethod, ITestNGMethod testNGMethod, ITestContext context){
Method[] methods = testNGMethod.getRealClass().getDeclaredMethods();
if(methods!=null){
for(Method method:methods){
if(method.getName().equals(testNGMethod.getMethodName())){
ParamFile paramFile = method.getAnnotation(ParamFile.class);
ParamDataProvider.fileName = paramFile.fileName();
}
}
}
System.out.println("beforeDataProviderExecution finished");
}
@Override
public void afterDataProviderExecution(IDataProviderMethod dataProviderMethod, ITestNGMethod testNGMethod, ITestContext context){
ParamDataProvider.fileName = "";
}
}
第二步,获取到文件名称后,读取文件中的测试数据
import common.util.csvutils.CSVUtils;
import org.testng.annotations.DataProvider;
import java.util.Map;
public class ParamDataProvider {
public static String fileName = "";
@DataProvider(name = "annoCsvData")
public Object[][] readCsvData(){
//读入csv文件数据并转化为Object[][]
Map<Integer, Map<String,Object>> map = CSVUtils.readFile(fileName);
Object[][] objects = new Object[map.size()][1];
for(int i=0; i<map.size(); i++){
Object[] temp = new Object[1];
temp[0] = map.get(i+1);
objects[i][0]=temp;
}
return objects;
}
}
使用@DataProvider中的监听器
本例子中,使用了testNG中的监听器,关于监听器,参考 监听器 一章
运行结果
beforeDataProviderExecution finished
{age=1, city=BJ, code=0, data=good cat, describe=冒烟测试, id=1, msg=success, name=tom}
success
{age=100, city=TOKYO, code=1, data=, describe=异常测试, id=2, msg=doesn't exist, name=jerry}
doesn't exist
beforeDataProviderExecution finished
{age=1, city=BJ, code=0, data=good cat, describe=冒烟测试, id=1, msg=success, name=tom}
tom
{age=100, city=TOKYO, code=1, data=, describe=异常测试, id=2, msg=doesn't exist, name=jerry}
jerry
===============================================
liang6Demo
Total tests run: 4, Failures: 0, Skips: 0
===============================================
版权所有,本文为原创文章,转载请注明出处
https://www.cnblogs.com/liang6/p/14395828.html
总结
使用注解后的测试用例,看起来如下:
class Liang6DemoAnnoCsv {
@Test(dataProvider = "annoCsvData", dataProviderClass= ParamDataProvider.class)
@ParamFile(fileName = "liang6demo.csv")
public void annoCsvData(Object[] obj){
Map<String, Object> mapLine = (Map<String, Object>)obj[0];
System.out.println(obj[0]);
System.out.println(mapLine.get("msg"));
}
@Test(dataProvider = "annoCsvData", dataProviderClass= ParamDataProvider.class)
@ParamFile(fileName = "liang6demo.csv")
public void annoCsvData2(Object[] obj){
Map<String, Object> mapLine = (Map<String, Object>)obj[0];
System.out.println(obj[0]);
System.out.println(mapLine.get("name"));
}
}
只需要在@ParamFile中配置csv文件名称即可,代码看起来,整洁度和结构性更加清晰简明
浙公网安备 33010602011771号