所以如果我的WidgetUnitTest正在测试一个名为Widget的目标,我想我需要在整个测试方法中创建相当数量的Widget.我应该在WidgetUnitTest构造函数中或在setUp()方法中构造这些Widget吗?如果使用1比1的小部件来测试方法,或者最好的做法是否尽可能地重复使用小部件?
最后,断言/失败和测试方法之间应该存在多少粒度?纯粹主义者可能会认为,一个测试方法中应该存在一对一的断言,但是根据该范例,如果Widget有一个叫getBuzz()的getter,我将最终得到与getBuzz()的20个不同的测试方法名字喜欢
@Test public void testGetBuzzWhenFooIsNullAndFizzIsNonNegative() { ... }
而不是一种测试众多场景并承载大量断言的方法:
@Test public void testGetBuzz() { ... }
感谢来自某些JUnit大师的任何见解!
解决方法
有趣的问题首先 – 我在IDE中配置的最终测试模式:
@Test public void shouldDoSomethingWhenSomeEventOccurs() throws Exception { //given //when //then }
在给定的情况下,我将测试设置放在每个测试中是唯一的.
>什么时候是理想的单行 – 你正在测试的东西.
>然后应该包含断言.
我不是一个断言倡导者,但你应该只测试一个行为的单一方面.例如,如果该方法应该返回某些东西,并且还会产生一些副作用,请创建两个相同的测试,同时给出和何时使用.
测试模式也包括抛出异常.这是为了处理Java中烦人的检查异常.如果你测试一些代码,那么你就不会被编译器所困扰.当然,如果测试引发一个异常,它会失败.
建立
测试设置非常重要.一方面,提取常用代码并将其放在setup()/ @ Before方法中是合理的.但是请注意,当读取测试(可读性是单元测试中最大的价值!)时,很容易错过挂起在测试用例开头部分的设置代码.所以相关的测试设置(例如你可以以不同的方式创建窗口小部件)应该去测试方法,但是应该提取基础设施(设置常见的模拟,启动嵌入式测试数据库等).再次提高可读性.
您还知道JUnit每次测试创建了新的测试用例类实例?所以即使你在构造函数中创建了CUT(被测类),每个测试之前调用构造函数.有点恼人
粒度
首先你的测试,并考虑你想要测试的用例或功能,从不考虑:
this is a
Foo
class havingbar()
andbuzz()
methods so I createFooTest
withtestBar()
andtestBuzz()
. Oh dear,I need to test two execution paths throughoutbar()
– so let us createtestBar1()
andtestBar2()
.
shouldTurnOffEngineWhenOutOfFuel()很好,testEngine17()是坏的.
更多关于命名
testGetBuzzWhenFooIsNullAndFizzIsNonNegative名称告诉测试是什么?我知道它测试的东西,但为什么?你不觉得细节太贴心了吗?怎么样:
@Test shouldReturnDisabledBuzzWhenFooNotProvidedAndFizzNotNegative`
它以有意义的方式描述输入和您的意图(假设禁用的嗡嗡声是某种蜂鸣状态/类型).还要注意,我们不再为Foo编写getBuzz()方法名称和null合同(而是我们说:当没有提供Foo时).如果将来用null对象模式替换null怎么办?
也不要怕getBuzz()的20种不同的测试方法.而是考虑您正在测试的20种不同用例.但是,如果您的测试用例类增长太大(因为它通常比测试类大得多),则可以将其提取到几个测试用例中.再一次:FooHappyPathTest,FooBogusInput和FooCornerCases都不错,Foo1Test和Foo2Test都不错.
可读性
争取简短和描述性的名字.那时给出的几条线条很少.而已.创建构建器和内部DSL,提取方法,编写自定义匹配器和断言.测试应该比生产代码更加可读.不要过度模拟.
我发现首先编写一系列空的名为好的测试用例方法是有用的.然后我回到第一个.如果我仍然明白我在什么条件下测试什么,我在此期间实施测试构建类API.然后我实现那个API.智能人称它为TDD(见下文).
推荐阅读:
> Growing Object-Oriented Software,Guided by Tests
> Unit Testing in Java: How Tests Drive the Code
> Clean Code: A Handbook of Agile Software Craftsmanship