单元测试总是形式?

97 阅读2分钟

在我开发过程中,我发现我总是容易写出如下的单测,这让我头疼不已,因为我没法再去看他第二次,每次我要修改被测试的类,我

  • 要么 仔细看一遍,费尽心思在单测上加上注释
  • 要么 注释掉这个单测

都是为了让代码合并进去,完成我的开发任务。

个人觉得哪些长篇大论论述单测重要性,怎么写的好,等等等;确实有道理,但是有些说太复杂了,实践成本也比较高,在国内很难适用。

我目前发现了最简单且行之有效的方法,根据《编写可读代码的艺术》这本书来的。 只有1条。

  • 使用“测试专属语言”,让测试代码可读,简短。

想知道这条最简单的原则值的是什么,请向下读。

修改前:【我自己的单测】

@Test
public void format2StrList() {
    final DateFormatter formatter = DateFormatter.getInstance();

    final LocalDate localDate = LocalDate.of(2022, 5, 6);
    final LocalTime localTime = LocalTime.of(13, 14, 2);
    final LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
    final Instant instant = localDateTime.toInstant(ZoneOffset.ofHours(8));
    final Date date = Date.from(instant);

    final String dateFormatted = formatter.format(date);

    assertFalse(StringUtils.isNotBlank(dateFormatted));
    assertEquals("2022-05-06T13:14:02", dateFormatted);
}


@Test
public void formatDateList() {
    final LocalDate localDate = LocalDate.of(2022, 5, 6);
    final LocalTime localTime = LocalTime.of(13, 14, 2);
    final LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
    final Instant instant = localDateTime.toInstant(ZoneOffset.ofHours(8));
    final Date date = Date.from(instant);

    final DateFormatter formatter = DateFormatter.getInstance();

    final Field field = Assertions.assertDoesNotThrow(() -> TestPerson.class.getDeclaredField("dates"));
    final String dateFormatted = formatter.format(field, date);

    assertFalse(StringUtils.isNotBlank(dateFormatted));
    assertEquals("2022-05-06", dateFormatted);

}

修改后:

@Nested
class Format2StrList {
    @Test
    public void value() {
        checkDateFormat2ExceptDatePattern("2022-05-06T13:14:02", "2022-05-06T13:14:02");
    }

    @Test
    public void DBDateFormat() {
        checkFieldDateFormat2ExceptDatePattern(Person.class, "dates",
                "2022-05-06T13:14:02", "2022-05-06");
    }

    @Test
    public void noPattern() {
        checkFieldDateFormat2ExceptDatePattern(Person.class, "noPattern",
                "2022-05-06T13:14:02", "2022-05-06T13:14:02");
    }
}

/**
* 检查根据dateTimeText构造的Date,按照DateFormatter格式化器,是否能格式化为期望的日期格式
*/
void checkDateFormat2ExceptDatePattern(String dateTimeText, String exceptPattern) {
    checkFieldDateFormat2ExceptDatePattern(null, null, dateTimeText, exceptPattern);
}

/**
* 检查根据dateTimeText构造的Date,按照DateFormatter格式化器,是否能格式化为期望的日期格式
*/
void checkFieldDateFormat2ExceptDatePattern(Class<?> cls, String fieldName,
                                        String dateTimeText, String exceptPattern) {
    final LocalDateTime localDateTime = LocalDateTimeUtil.parse(dateTimeText);
    final Date date = localDateTime2Date(localDateTime);

    final DateFormatter formatter = DateFormatter.getInstance();
    final Field field = cls == null ?
            null :
            assertDoesNotThrow(() -> cls.getDeclaredField(fieldName));

    final String dateFormatted = formatter.format(field, date);

    assertFalse(StringUtils.isNotBlank(dateFormatted));
    assertEquals(exceptPattern, dateFormatted);
}

Date localDateTime2Date(LocalDateTime localDateTime) {
    final Instant instant = localDateTime.toInstant(ZoneOffset.ofHours(8));
    return Date.from(instant);
}

你会发现我把对于单个函数,基本的测试框架定义好了,也就是checkFieldDateFormat2ExceptDatePattern这个。

这样,我可以很方便地扩充后续其他的测试。

也就是抽取公共的部分,作为函数,基于此扩展其他单测,这样更清晰和方便