java单元测试中的断言
为测试编写断言似乎很简单:我们所需要做的就是将结果与期望进行比较。 通常使用测试框架提供的断言方法(例如assertTrue()或assertEquals())来完成此操作。 但是,在更复杂的测试场景中,使用这样的基本断言来验证测试的结果可能会很尴尬。
主要的问题是,通过使用它们,我们用低级的细节使测试难以理解。 这是不希望的。 在我看来,我们应该争取以商业语言进行测试。
在本文中,我将展示如何使用所谓的“匹配器库”并实现我们自己的自定义断言,以使我们的测试更具可读性和可维护性。
为了演示的目的,我们将考虑以下任务:让我们想象一下,我们需要为应用程序的报告模块开发一个类,当给定两个日期(“ begin”和“ end”)时,该类将提供一个小时的时间这些日期之间的间隔。 然后使用时间间隔从数据库中获取所需的数据,并以精美图表的形式将其呈现给最终用户。
标准方法
让我们以一种写断言的“标准”方式开始。 我们可以在这个示例中使用JUnit ,尽管我们可以同样使用TestNG 。 我们将使用诸如assertTrue(),assertNotNull()或assertSame()之类的断言方法。
下面介绍了属于HourRangeTest类的几个测试之一。 这很简单。 首先,它要求getRanges()方法返回同一天两个日期之间的所有一小时范围。 然后,它验证返回的范围是否完全正确。
private final static SimpleDateFormat SDF
= new SimpleDateFormat("yyyy-MM-dd HH:mm");
@Test
public void shouldReturnHourlyRanges() throws ParseException {
// given
Date dateFrom = SDF.parse("2012-07-23 12:00");
Date dateTo = SDF.parse("2012-07-23 15:00");
// when
final List<Range> ranges = HourlyRange.getRanges(dateFrom, dateTo);
// then
assertEquals(3, ranges.size());
assertEquals(SDF.parse("2012-07-23 12:00").getTime(), ranges.get(0).getStart());
assertEquals(SDF.parse("2012-07-23 13:00").getTime(), ranges.get(0).getEnd());
assertEquals(SDF.parse("2012-07-23 13:00").getTime(), ranges.get(1).getStart());
assertEquals(SDF.parse("2012-07-23 14:00").getTime(), ranges.get(1).getEnd());
assertEquals(SDF.parse("2012-07-23 14:00").getTime(), ranges.get(2).getStart());
assertEquals(SDF.parse("2012-07-23 15:00").getTime(), ranges.get(2).getEnd());
}
这绝对是有效的测试; 但是,它有一个严重的缺点。 // then部分中有很多重复的片段。 显然,它们是使用复制和粘贴创建的,因此经验告诉我,这不可避免地会导致错误。 此外,如果我们要编写更多这样的测试(并且我们当然应该编写更多测试以验证HourlyRange类!),则相同的断言语句将在每个语句中反复重复。
断言的数量过多会削弱当前测试的可读性,但每个断言的复杂性也会削弱当前测试的可读性。 有很多低级噪声,这无助于掌握测试的核心场景。 众所周知,代码的读取次数要比编写的次数要多(我认为这对于测试代码也适用),因此,我们绝对应该提高可读性。
在重写测试之前,我还想强调另一个弱点,这一次是与出现错误时得到的错误消息有关。 例