Skip to content

计算器

计算器

相关知识点

  1. yaml文件读取
  2. 参数化执行
  3. 多断言
  4. allure报告

需求分析

业务功能梳理

计算器

  1. 对计算机加法、平均值功能进行测试
  2. 指定测试用例执行顺序
  3. 并发执行测试用例
  4. yaml参数化实现
  5. 使用hamcrest进行多断言
  6. 结合allure实现测试报告

实现思路

uml diagram

用例设计

单元测试设计思路

可以通过错误推断法边界值与等价类进行测试用例设计

测试用例

标题 步骤 预期结果 实际结果
加法冒烟测试 输入1,3 4
加法等价类边界值测试 输入99,0 99
加法等价类边界值测试 输入99,99 198
加法等价类边界值测试 输入-99, 0 -99
加法等价类边界值测试 输入-99,-99 -198
平均值冒烟测试 输入1,3 2
平均值等价类边界值测试 输入99,0 49.5
平均值等价类边界值测试 输入99,99 0
平均值等价类边界值测试 输入-99, 0 -49.5
平均值等价类边界值测试 输入-99,-99 0

参数化实现

通过yaml写入数据

写入测试数据

public static void init(){
    // 添加测试数据准备,通过硬编码实现,实际使用从数据库中读取
    List<AddEntity> addEntities = new ArrayList<>();
    addEntities.add(new AddEntity(new int[]{99, -99}, 0));
    addEntities.add(new AddEntity(new int[]{99, 99}, 198));
    addEntities.add(new AddEntity(new int[]{-99, -99}, -198));
    addEntities.add(new AddEntity(new int[]{99, 99, 99, 99, 99}, 495));
        // 测试数据写入yaml文件
        TestDataUtil.dumpYamlData(EntityFileMapping.ADD_ENTITY, addEntities);
}

/** file: TestDataUtil
 *  写入实体类列表到对应yaml文件中
 * @param entityFileMap 实体类与文件对应关系
 * @param testDataList
 * @param <T>
 * @throws IOException
 */
public static <T> void dumpYamlData(EntityFileMapping entityFileMap, List<T> testDataList) throws IOException {
    if (testDataList.size() ==0) {
        throw new IllegalArgumentException("数组长度不应为零");
    }
    // 判断类型是否一致
    if (!testDataList.get(0).getClass().equals(entityFileMap.getEntityClass()))  {
        throw new ClassCastException("列表类型与文件类型不匹配");
    }
    File file = new File(TEST_DATA_FILE_PATH + entityFileMap.getFilePath()); // 指定YAML文件路径
    objectMapper.writeValue(file, testDataList);

}

通过实体类实例化yaml对象

使用泛型对yaml数据进行实例化

    /**
     * 用于yaml文件解析测试数据
     *
     * @param entityFileMap 实体类与文件对应关系
     * @param <T>
     * @return 返回实体类列表
     * @throws IOException
     */
    public static <T> List<T> loadYamlData(EntityFileMapping entityFileMap) throws IOException {
        File file = new File(TEST_DATA_FILE_PATH + entityFileMap.getFilePath()); // 指定YAML文件路径
        //获取一个`TypeFactory`实例,用于`JavaType`对象
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        // 指定泛型类型为type
        JavaType javaType = typeFactory.constructParametricType(List.class, entityFileMap.getEntityClass());
        return objectMapper.readValue(file, javaType);
    }

执行方法进行参数化测试

编写工厂类读取yaml数据(@MethodSource不能指定实参)

public class TestDataFactory {
    // 用于返回测试数据的静态方法的工厂类 ,可以被@MethodSource进行调用
    public static List<AddEntity> getAddTestData() throws IOException {
       return TestDataUtil.loadYamlData(EntityFileMapping.ADD_ENTITY);
    }

    public static List<AverageEntity> getAverageTestData() throws IOException {
        return TestDataUtil.loadYamlData(EntityFileMapping.AVERAGE_ENTITY);
    }

}
通过@MethodSource实现参数化
@ParameterizedTest
@MethodSource("com.hogwarts.testdata.TestDataFactory#getAddTestData")
@DisplayName("相加功能")
@Description("使用yaml文件进行添加功能的等价类、边界值烟测试")
public void addYamlTest(AddEntity addEntity) {
    assertEquals(calculator.sum(addEntity.getAddNumbers()), addEntity.getExpect());
}
后续直接通过修改数据源进行用例添加

注意:参数化的方法行为是一致的,只有参数输入不同

断言

测试断言

通过assertEquals实现断言

        //int expected, 期望值
        // int actual, 实际值
        // String message 自定义失败原因
        assertEquals(4, result, "计算错误");

使用hamcrest优化

使用hamcrest结合多断言优化测试用例

注意导包路径

// 定义断言执行数组
ArrayList<Executable> assertList = new ArrayList<>();
// 添加断言方法
assertList.add(() -> assertThat(result, equalToObject(9)));
assertList.add(() -> assertThat(result, equalToObject(0)));
// 多断言每个断言都会运行,可以直接看到所有断言的情况
assertList.add(() -> assertThat(result, equalToObject(10)));
assertAll(assertList);

测试报告

用例指定名称、描述

  • @DisplayName("") 指定测试报告中测试类测试方法名称
  • @Description("") 添加相关描述
    @DisplayName("平均值功能")
    @Description("平均值功能参数化运行yaml文件等价类、边界值测试数据")
    public void averageYamlTest(AverageEntity averageEntity){}
    

运行allure服务

通过命令行启动allure报告

allure serve target\allure-results

指定用例执行(选修)

指定用例顺序

通过@order修改用例指定顺序

// 测试类执行执行顺序类型
@TestMethodOrder(OrderAnnotation.class)
public class CalculatorTest

// 在测试方法上指定执行顺序
@Test
@Order(1)
public void addOrderOne()

并发执行用例

通过配置开启并行执行

# file: src/test/resources/junit-platform.properties
# 开启多线程执行,注意避免共享资源错乱
junit.jupiter.execution.parallel.enabled=true

总结

总的来说,通过参数化测试、多断言和 Allure 报告的使用,我们可以更好地组织和执行测试,并且生成直观清晰的测试报告,方便问题定位和分析。同时,可以通过指定用例执行的顺序和开启并发执行来提高测试效率和速度。