junit测试设置不回滚
寻找好名字是手工软件的挑战之一。 您需要随时随地找到它们-类,方法,变量,仅举几例。 但是,什么使名字成为好名字呢? 引用Oncle Bob的话:“三件事:可读性,可读性和可读性!” 他后来通过表达的清晰,简单和密度1对其进行了定义 。
尽管这对我来说很有意义,但我发现自己尤其在测试方法方面有些挣扎。 为了更好地理解我在说什么,需要知道我编写了代码测试驱动程序 。 做了一段时间之后,我逐渐将工作重点从被测单元转移到了测试本身。 这可能是因为我喜欢将一个测试用例视为一项有效的规范和质量保证,因此它非常重要2 。
因此,只要测试失败,理想情况下,我就能一眼就能知道哪个规范被破坏以及为什么。 实现此目的的最佳方法似乎是找到一个表达性的测试名称,因为这是报告视图中显示的第一条信息:
从这个角度来看,我并不总是对这种观点所显示的内容感到满意,因此我花了一些时间进行研究,以了解哪些思想流派可能会有所帮助。 不幸的是,我发现的大多数结果都有些过时,并且-不足为奇-关于该主题的意见分歧。 这篇文章基于这些发现和一些个人经验,代表了我的看法。
根据方法或行为测试名称进行测试?
每种方法的测试形式通常都是由工具提供的,例如,在事后生成单个测试存根。 如果您的Foo
类带有方法bar
则生成的方法将称为testBar
。 我一直对这种开发风格或命名约定的有用性持怀疑态度,并且会像旧的JavaRanch线程中的引用一样争论:“您根本不应该将其视为测试方法,而应该将其视为测试行为。班上的 因此,我喜欢我的测试方法名称来传达预期的行为3 。
有趣的是,我将对那一点改变看法。 如上所述,传达“行为”的想法要求找到一个简明的名称来全面表达该“行为”。 但是随后,术语行为意味着通过一个动作从一个状态过渡到另一种状态,或者用BDD术语表示,例如“当下即给”模式。 老实说,我认为将所有这些信息放在一个单一的名字中通常不是一个好主意4 :
@Test
public voidgivenIsVisibleAndEnabledWhenClickThenListenerIsNotified() {}
@Test
public voidgivenIsVisibleAndNotEnabledWhenClickThenListenerIsNotNotified() {}
@Test
public voidgivenIsNotVisibleAndEnabledWhenClickThenListenerIsNotNotified() {}
也许这只是口味的问题,但是根据我的经验,由于无论选择哪种格式样式,都缺乏简单性和/或清晰度,因此这种方法通常缺乏可读性。 此外,这样的重载名称往往与注释具有相同的问题–随着内容的发展,这些名称很容易过时。 因此,我想改用BUILD-OPERATE-CHECK 5模式。 这将允许将阶段拆分为单独的子方法名称,并将其放置在单个测试中:
@Test
public void testNameHasStillToBeFound() {// do what is needed to match preconditiongivenIsVisibleAndEnabled();// execute the transitionwhenClick();// verify the expected outcomethenListenerIsNotified();
}
不幸的是,这导致我们进入了起点。 但是,如果仔细看一下上面的示例,所有方法都围绕着一个共同的分母。 它们都属于触发转换的同一动作。 在我们的例子中,点击事件。 考虑到从开发过程的角度来看,我认为一个测试用例比被测单元更重要,因此可以将其解释为一种符号,以在开发中的单元中以适当的方法名称来反映操作6 。
因此,出于示例的考虑,假设我们有一个环绕UI控件的ClickAction
。 鉴于上述情况,引入一种名为ClickAction#execute()
的方法对我们来说似乎很合适。 为简单起见,我们也可以将该名称也用于表示从ClickAction
的默认状态到通过ClickAction#execute()
控件构造的转换的测试方法:
class ClickActionTest {@Testpublic void execute() {Control control = mock( Control.class );ClickAction clickAction = new ClickAction( control );clickAction.execute();verify( control ).notifyListeners(...)}
}
为了简单起见,下一个测试名称可能只提及重要的状态信息,因为它不同于默认值并导致另一个结果:
class ClickActionTest {[...]@Testpublic void executeOnDisabledControl() {Control control = mock( Control.class );when( control.isEnabled() ).thenReturn( false );ClickAction clickAction = new ClickAction( control );clickAction.execute();verify( control, never() ).notifyListeners(...)}@Testpublic void executeOnInvisibleControl() {[...]
}
如您所见,这种方法产生了一组测试名称,从技术上讲,它们代表各种“每种方法的测试”模式-但并非出于我认为完全出于不利的原因。 考虑到上下文,我认为这种命名模式很简单,清晰并且具有表达力:
仍未提及预期的测试结果。 乍一看,这似乎并不令人满意,但是从我目前的观点来看,我愿意接受这是一个合理的权衡。 特别是,通常在JUnit报告视图中也会显示测试失败的原因。 因此,可以通过提供有意义的测试失败7来解决该问题。
结论
实际上,我现在正在使用上述测试命名模式一段时间。 到目前为止,效果还不错。 特别是在像我通常使用的非常小的单元上工作时,几乎没有错误解释的空间。 但是,这种方法并不适合所有情况,有时感觉只是更好,而且可读性足以提及结果。 我不会在这里谈论原则,也许我弄错了。 因此,我很高兴能为您提供一些指向更详尽的方法的指针,您可能会意识到这些方法可以扩大我的观点。
- Robert C. Martin关于清洁测试,清洁代码,第9章单元测试↩
- 更糟的是:丢失被测单元或测试用例? 有了良好的测试用例,恢复单元在大多数情况下应该很容易,但是反之亦然,您很容易错过丢失的测试用例中指定的其中一个极端用例↩
- 使用JUnit的方法的命名约定,使用JUnit的方法的命名约定 ↩
- 为避免误解: BDD的功能与众不同,并带有自己的测试框架。 我只是在这里提到它,因为术语“行为”似乎暗示了这一点,而术语“ givenWhenThen”在有关测试名称的许多讨论中不胜枚举。 然而,你居然发现像罗伊Osherove的命名约定标记建议“UnitOfWork_StateUnderTest_ExpectedBehavior”这似乎仍然被广泛接受虽然帖子已经看到大多数的最后十年的日子↩
- Robert C. Martin,《清洁规范》,第9章,清洁测试↩
- 甚至将全部功能提取到一个单独的类中。 但是,这种情况下,在我的岗位描述更具有MoreUnit单位 ↩
- 这可能是一个主题,当我不得不结束时,我就这样保留它! ↩
翻译自: https://www.javacodegeeks.com/2014/03/getting-junit-test-names-right.html
junit测试设置不回滚