Java笔记10 - 单元测试

  • 使用最常用的测试矿建JUnit

编写JUnit测试

  • 单元测试: 针对最小的功能单元编写测试代码
  • Java程序最小的功能单元是方法
  • 测试驱动开发: 编写接口 -> 编写测试 -> 编写代码 -> ... -> 一边写 -> 一边测.
  • 真是情况: 编写好了实现代码, 需要对已有代码进行测试

JUnit

  • 开源测试框架

  • 简单组织测试代码, 并随时运行.

  • 测试覆盖率, 应该在80%以上.

  • 核心测试方法加入@Test注解

  • 所有带有@test的方法标识为测试方法

  • Assertion断言中定义:

    • assertEquals(): 第一次参数表示期望, 第二个表示结果
    • assertTrue: 期望结果为true
    • assertFalse: 期望结果为false
    • assertNotNull: 期望结果为非null
    • assertArrayEquals(): 期望结果为数组, 并与期望数组的每个元素相等
  • assertEquals(double expected, double actual, double delta): 指定误差值

单元测试的好处

  • 单个方法按照正确预期运行
  • 修改方法后只需要确保对应的单元测试通过
  • 测试代码作为示例代码, 演示如何调用该方法
  • 规范:
    • 单元测试代码非常简单, 一眼看懂, 不能为测试代码编写测试
    • 单元测试相互独立, 不依赖运行
    • 测试时注意边界条件, 0, null, 空字符串""等情况

Fixture

  • JUnit提供编写测试前准备, 测试后清理的固定代码, 称为Fixture
  • 标记@BeforeEach@AfterEach, 运行在@Test方法前后自动运行
  • @BeforeAll@AfterAll, 运行在所有@Test前后运行
    • 只允许一次
    • 只能初始化静态变量
    • 只能标注在静态方法上
  • 总结:
    • 实例变量: 在@BeforeEach中初始化, 在@AfterEach中清理. 因为是不同的实例, 在各个@Test互不影响
    • 静态变量: 在@BeforeAll中初始化, 在@AfterAll中清理, 在各个@Test中均是唯一实例, 影响各个@Test方法
  • 每次运行@Test方法, 首先创建一个XXXTest实例
    • @Test方法内部成员变量独立
    • 成员遍历状态无法共享

异常测试

  • assertThrows来期望捕获一个指定的异常
  • Executable封装了执行的会产生异常的代码.
  @Test
  void testNegative() {
    assertThrows(IllegalArgumentException.class, new Executable() {
      @Override
      public void execute() throws Throwable {
        Factorial.fact(-1);
      }
    });
    assertThrows(IllegalArgumentException.class, () -> {
      Factorial.fact(-1);
    });
  }
  • Java8引入函数式编程, 但方法接口使用->

条件测试

  • @disableto skip this test task
  • JUnit根据不同的条件注解, 决定是否运行当前的@Test方法
  • @EnabledOnOs/@DisabledOnOs: 根据当前操作系统执行测试
  • @EnabledIfSystemProperty: 根据系统变量执行测试
  • @EnabledIfEnvironmentVariable: 根据环境变量进行测试
  • @EnabledIfEnvironmentVariable(named = "DEBUG", matches="true") 需要传入环境变量DEBUG=true
  • 万能的@EnableIf: 可以执行任意的Java语句

参数化测试

  • 待测试的输入和输出是同一组数据: 可以把测试数据组织起来, 用不用的测试数据调用相同的测试方法
  • @ParameterizedTest: 参数化测试注解, 代替@Test
  @ParameterizedTest
  @ValueSource(ints = {-1, -5, -100})
  void testAbsNegative(int x) {
    assertEquals(-x, Math.abs(x));
  
  • 多组参数, 使用@MethodSource指定方法源
  @ParameterizedTest
  @MethodSource
  void testCapitalize(String input, String result) {
    assertEquals(result, StringUtil.capitalize(input));
  }

  static List<Arguments> testCapitalize() {
    return List.of(
        Arguments.arguments("abc", "Abc"),
        Arguments.arguments("APPLE", "Apple"),
        Arguments.arguments("gooD", "Good")
        );
  }
  • 如果静态方法和测试方法不同, @MethodSource允许指定方法名

  • 使用@CsvSource也可以传入参数

  • 每个字符串表示一行

疑问

  • @EnableIf不能用
posted @ 2020-04-27 15:22  张润昊  阅读(234)  评论(0编辑  收藏  举报