接JUNIT5测试框架实践一(JUNIT5测试框架实践一)
内容概述
如下为重点代码实现:
一、参数化(不同参数个数实现方法)
1、参数类型为 Int 型
1)参数方法
static Stream<Arguments> calculatortest01(){
return Stream.of(
Arguments.arguments(Arrays.asList(1,2,3),6),
Arguments.arguments(Arrays.asList(12,22,34),50),
Arguments.arguments(Arrays.asList(2,3),5)
);
}
2)测试方法
@ParameterizedTest(name = ARGUMENTS_WITH_NAMES_PLACEHOLDER)
@MethodSource()
public void calculatortest01(List<Integer> a, int c){
result = calculator.sum(a.stream().mapToInt(Integer::intValue).toArray());
//result1 = calculator.sum(a.stream().toArray(Integer::new));
//junit5
// assertEquals(20,result);
assertThat("计算结果01错误",result,is(equalTo(c)));
}
2、参数类型为 String 型
1)参数方法
static Stream<Arguments> str1Test(){
return Stream.of(
Arguments.arguments(Arrays.asList("hello","JUnit5"),"hello JUnit5"),
Arguments.arguments(Arrays.asList("中国","欢迎","您"),"中国 欢迎 您"),
Arguments.arguments(Arrays.asList("这里","是","北京","天安门"),"这里 是 北京 天安门")
);
}
2)测试方法
void str1Test(List<String> stringList,String strRe){
//list --> String[]
str1Result = calculator.concatStr(stringList.stream().toArray(String[]::new));
assertEquals(strRe,str1Result,"message");
}
二、合并不同类型的断言方法(通过flag内容区分执行哪个测试方法)
1、参数方法
static Stream<Arguments> conbinTest(){
return Stream.of(
//第一个方法的参数
Arguments.arguments(true, Arrays.asList(1,1),2),
Arguments.arguments(true, Arrays.asList(1,1,4),6),
Arguments.arguments(true, Arrays.asList(1,1,4,9,6),21),
//第二个方法的参数
Arguments.arguments(false, Arrays.asList(1,100),0),
Arguments.arguments(false, Arrays.asList(1,100,5),0),
Arguments.arguments(false, Arrays.asList(21,3,100,33),0)
);
2、测试方法
@ParameterizedTest
@MethodSource()
void conbinTest(boolean flag, List<Integer> numlist,int re){
if(flag){
result = calculator.sum(numlist.stream().mapToInt(Integer::intValue).toArray());
logger.info("计算结果:{}",result);
assertThat("加法成功",result,is(equalTo(re)));
}else {
Exception exception = assertThrowsExactly(NumberFormatException.class,
() -> calculator.sum(numlist.stream().mapToInt(Integer::intValue).toArray())
);
String string = exception.getMessage().toString();
assertThat("断言失败",string,is(containsString("integer is 100")));
}
三、自定义注解
1、新增注解接口 P0test
//创建p0标签 组合@Test 及 @Tag 标签
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Test
@Tag("p0")
public @interface P0test {
}
2、应用注解
//引用P0test标签,相当于应用了@Test + @Tag("p0") 标签
// @Test
@P0test
@DisplayName("100连减01")
public void subtest1_1(){
result = calculator.subtract(20,30,30);
assertThat("100连续减去",result,is(lessThanOrEqualTo(20)));
}
3、新建suit类测试正确性
@Suite
@SelectClasses({
com.ceshiren.num.SubTest1.class,
com.ceshiren.num.SubTest2.class
})
@IncludeTags("p0") //引用Tag标签
public class Suit2Test {
}
四、引用参数对象,使用注解@AggregateWith(适用于多参数测试)
1、实体类(添加get\set方法、添加全参和无参构造函数)
public class SumData {
private boolean flag;
private List<Integer> numlist;
private int re;
2、实体类SumData的aggregateArguments结构化
public class ListAggregator implements ArgumentsAggregator {
@Override
public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException {
//list --实体类对象SumData
//access[boolean flag, List<Integer> numlist,int re]
boolean flag = accessor.getBoolean(0);
List<Integer> numlist = (List<Integer>) accessor.get(1);
int re = accessor.getInteger(2);
SumData sumData = new SumData(flag,numlist,re);
return sumData;
}
}
3、参数方法
static Stream<Arguments> conbin1Test(){
return Stream.of(
Arguments.arguments(true, Arrays.asList(1,1),2),
Arguments.arguments(true, Arrays.asList(1,1,4),6),
Arguments.arguments(true, Arrays.asList(1,1,4,9,6),21),
Arguments.arguments(false, Arrays.asList(1,100),0),
Arguments.arguments(false, Arrays.asList(1,100,5),0),
Arguments.arguments(false, Arrays.asList(21,3,100,33),0)
);
4、测试方法
@ParameterizedTest
@MethodSource("conbin1Test")
void conbin2Test (@AggregateWith(ListAggregator.class) SumData sumdata){
if (sumdata.isFlag()) {
result = calculator.sum(sumdata.getNumlist().stream().mapToInt(Integer::intValue).toArray());
logger.info("计算结果:{}", result);
assertThat("加法成功", result, is(equalTo(sumdata.getRe())));
} else {
Exception exception = assertThrowsExactly(NumberFormatException.class,
() -> calculator.sum(sumdata.getNumlist().stream().mapToInt(Integer::intValue).toArray())
);
String string = exception.getMessage().toString();
assertThat("断言失败", string, is(containsString("integer is 100")));
}
}
四、多断言(聚合所有断言-assertAll(heading, executables))
例
public void subtest1_1(){
ArrayList<Executable> list = new ArrayList<>();
result = calculator.subtract(20,30,30);
//问题:一个断言失败,就不再运行后续的代码---解决方法:assertAll运行断言列表
list.add(() ->assertThat("100连续减去",result,is(lessThanOrEqualTo(10))));
System.out.println("第二次业务逻辑运算");
int sum = calculator.sum(1,2,3);
list.add(() ->assertThat("100连续减去",result,is(lessThanOrEqualTo(10))));
System.out.println("如下执行断言列表");
assertAll(list);
}
五、yaml 文件解析
1、添加yaml文件
datas:
- a: 1
b: 1
result: 2
message: 有效2个整数【1,1】
- a: 98
b: 98
result: 196
message: 有效边界值相加【98,98】
- a: -98
b: 98
result: 0
message: 有效边界值相加【-98,98】
- a: 98
b: -98
result: 0
message: 有效边界值相加【98,-98】
- a: -98
b: -98
result: -196
message: 有效边界值相加【-98,-98】
- a: 100
b: 0
result: 0
message: 无效边界值相加【100,0】
- a: -100
b: -1
result: 0
message: 无效边界值相加【-100,-1】
- a: 2
b: 100
result: 0
message: 无效边界值相加【2,100】
- a: 1
b: -100
result: 0
message: 无效边界值相加【1,-100】
2、编写实体类
1)DataInfo.java(内层数据对象)
public class DataInfo {
//实体类的成员变量名就是map里面的key
private int a;
private int b;
private int result;
private String message;
//添加get、set方法及构造函数
}
2)Datas.java ( yaml 倒数第二层信息)
public class DataInfo {
//实体类的成员变量名就是map里面的key
private int a;
private int b;
private int result;
private String message;
//添加get、set方法及构造函数
}
3、新建 YamlParameterSource 类,从 yaml 中读取数据
public class YamlParameterSource {
static Stream<DataInfo> parameterYaml(){
//yaml文件解析为stream流提供给测试方法
Datas datas = getYaml();
List<DataInfo> dataInfos = datas.getDatas();
return dataInfos.stream();
}
//读取yaml文件返回Datas实体类
private static Datas getYaml(){
Datas dataList = null;
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
TypeReference<Datas> type = new TypeReference<Datas>() {};
//按预定义格式读取yaml文件中的内容
try {
dataList = mapper.readValue(new File("src/test/resources/data.yaml"),type);
} catch (IOException e) {
e.printStackTrace();
}
return dataList;
}
}
4、测试方法
public Calculator calculator = new Calculator("YamlFactory测试");
@ParameterizedTest
//前提:public修饰数据源方法
//数据源在其他类中,需要引用格式为:包名.类名#数据源的方法名
@MethodSource("com.ceshiren.source.YamlParameterSource#parameterYaml")
void parameterYaml(DataInfo dataInfo){
if(dataInfo.getMessage().startsWith("有效")){
int sum = calculator.sum(dataInfo.getA(), dataInfo.getB());
assertAll(
() -> assertEquals(dataInfo.getResult(),sum,dataInfo.getMessage())
);
} else if(dataInfo.getMessage().startsWith("无效")){
// System.out.println("进入无效判定");
Exception exception = assertThrowsExactly(NumberFormatException.class,
() -> calculator.sum(dataInfo.getA(),dataInfo.getB())
);
String string = exception.getMessage().toString();
assertThat(dataInfo.getMessage(), string, is(containsString("integer is 100")));
}
}
六、动态生成测试用例
1、yaml文件
resultList:
- caseName : 'case_1_1'
result : true
- caseName : 'case_1_2'
result : false
- caseName : 'case_2_1'
result : true
- caseName : 'case_2_2'
result : false
- caseName: 'case_1_1'
result: true
- caseName: 'case_1_2'
result: false
- caseName: 'case_2_1'
result: true
- caseName: 'case_2_2'
result: false
- caseName: 'case_1_1'
result: true
- caseName: 'case_1_2'
result: false
- caseName: 'case_2_1'
result: true
- caseName: 'case_2_2'
result: false
2、动态测试创建
1)创建ShellResult类(yaml 文件中最后一层数据)
public class ShellResult {
private String caseName;
private Boolean result;
添加set和get、tostring
2)创建ResultList类(yaml 文件中倒数第二层数据)
public class ResultList {
private List<ShellResult> resultList;
添加get、set方法
3)工厂法动态生成测试用例并运行
//读取yaml文件数据
private ResultList getResutlelist(){
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
TypeReference<ResultList> typeReference = new TypeReference<ResultList>() {};
try {
resutlelist = mapper.readValue(new File("src/test/resources/shell_test_result.yaml"),typeReference);
} catch (IOException e) {
e.printStackTrace();
}
return resutlelist;
}
// 动态测试
@TestFactory
Collection<DynamicTest> shellDynamicTest(){
Collection<DynamicTest> dynamicTests = new ArrayList<>();
ResultList resultList = getResutlelist();
resultList.getResultList().forEach(
ShellResult -> {
DynamicTest dynamicTest = DynamicTest.dynamicTest(ShellResult.getCaseName(),() -> {
assertTrue(ShellResult.getResult());
});
dynamicTests.add(dynamicTest);
}
);
return dynamicTests;
}