【发布时间】:2013-12-26 23:22:01
【问题描述】:
我来自 Perl 背景,我使用 Test::More 处理单元测试。使用该框架,我知道测试发生的顺序并且可以依赖它,我知道 JUnit 框架不鼓励这样做。我已经看到了几种解决此问题的方法,但我想了解正确/预期的做事方式。
在我的 Perl 单元测试中,我会构建测试,知道如果测试 #3 通过,我可以在进一步的测试中做出一些假设。我不太明白如何在 JUnit 世界中构建它,以便我可以使每个测试完全独立。
例如,假设我有一个从字符串中解析日期的类。方法包括:
- 解析一个简单的日期 (YYYY-MM-DD)
- 使用备用分隔符(YYYY_MM_DD 或 YYYY/MM/DD)解析简单日期
- 解析带有月份名称字符串的日期 (YYYY-MON-DD)
- 使用不同语言的字符串月份名称解析日期
- 等等
我通常在编写代码时将尽可能多的外部可访问方法集中到尽可能少的核心方法中,并尽可能多地重用代码(我敢肯定,这是我们大多数人都会做的事情)。所以,假设我对第一种方法有 18 个不同的测试,其中 9 个预计会通过,9 个会抛出异常。对于第二种方法,我只有 3 个测试,每个测试带有可以工作的分隔符 ('_' & '/'),另一个带有不工作的分隔符 ('*'),预计会失败。我可以将自己限制在引入的新代码上,因为我已经知道代码可以正确处理标准边界条件和常见错误,因为前 18 个测试已经通过。
在 Perl 世界中,如果测试 #20 失败,我知道这可能与特定分隔符有关,并且不是一般的日期解析错误,因为所有这些测试都已通过。在 JUnit 世界中,测试以随机顺序运行,如果测试 #20 失败,我不知道是因为一般日期解析问题还是因为分隔符。我必须去看看其他哪些失败了,然后在那里做出一些假设。当然,这并不太难做到,但也许在更大、更复杂的课程中,会更难做到。
其他人如何处理建立一组测试?我应该将每个测试放在一个单独的类中并使用测试套件吗?这似乎很乏味。 (在有人建议我将第一个 18 个放在一个类中,将第二个 3 个放在另一个类中,并为这些分组使用测试套件之前,让我们假设所有 18 个早期测试也都建立在彼此之上)。
再说一次,我知道有一些方法可以解决这个问题(JUnit 4.11+ 中的 FixedMethodOrder 或 JUnit-HierarchicalContextRunner),但我想了解该范式的用途。
【问题讨论】:
-
你不能假设测试的执行顺序。有些运行程序的运行顺序与其他运行程序不同。通常人们每个代码类使用一个测试类。例如,如果您有抛出异常的测试,则将它们标记为此类,它们将成功。 @Test(expected=IndexOutOfBoundsException.class)
标签: java unit-testing junit