一种新的单元测试的方法
来自http://www.javalinux.it/wordpress/?p=116
个人很认同文章中的这个想法,因此翻译过来。不能保证翻译得正确,因此看原文还是更好的选择。
也希望各位能指出翻译中的错误,
一种新的单元测试的方法意味着什么?难道说Junit或者TestNG还不够好?Junit(这里我提及到它因为它简单,但是在我的讨论中,TestNG也一样简单 from here on I’ll nominate it only for briefness,but TestNG is the same for my discussion)把测试类作为重点,并且所有的测试都是从那里开始。这意味着事实上,被测试类被认为仅仅存在于测试代码中,程序员只能通过它们使用的名字惯例来找到这些被测试类。
在旧版本的Junit中,你设计的测试类,需要强制继承Junit框架中的类,并且将调用的方法需要用”test”开头。因此按这个惯例来命名测试类和测试方法,并把他们与被测试的类和方法“连接”起来。我想你会同意,TestNG和Junit4给了我们更多的自由,去掉这些要求。不管怎样,被测试的类和方法和我们的测试类仍然是这样逻辑的联系在一起,并且很多测试类仍然遵循那些旧的惯例。
但是有很多更好的方式来命名类和方法!我来介绍BDD(Behaviour Driven Development),请注意BDD不是这篇文章的重点,但是它使我这篇文章更加完美。因此,让我们先用少许文字了解BDD吧。
BDD不仅是一个新的写测试的方法,也是一个按约定的新的设计形式
引用behaviour-driven.org来开始我的介绍:
BehaviourDrivenDevelopment grew out of a thought experiment based on NeuroLinguisticProgramming techniques. The idea is that the words you use influence the way you think about something
BDD产生自一个基于神经语言规划学技术的实验的想法。这个想法是你用的语言会影响你考虑问题的方式。
这个想法是需要程序员关注用来描述一个测试类或者方法的词语,因为所选的词语将影响到他们对这个问题的关注点。实际上,采用BDD方法写测试类时,相比这些被测试的类/方法本身,我们将更加关注这些被测试类/方法的行为。当然,这也将改变很多我们写测试代码的方式,比如,我们将对一个方法测试多次来验证每个行为是否正确。
OK, what if I don’t believe on Neuro Linguistic Programming(神经语言规划学)?是否我还不相信神经语言规划学。好的,从一个纯粹的开发者角度来看,我们根据我们的类和方法的行为作为约定来命名测试,因此,这个测试结果将是绝对清晰的(比如,
”shouldAcceptNullValue fails”就是一个清楚的表达,并不需要复杂的报告)。让我们提供一个简单的例子:
@Test( expected = IllegalArgumentException.class ) public void shouldNotPermitMethodNull() throws Exception { [..] } @Test( expected = IllegalArgumentException.class ) public void shouldNotPermitEndPointNull() throws Exception { } @Test public void shouldInitWebParams() throws Exception { } @Test public void getHoldersResultShouldReturnHolderForRightParameters() throws Exception { } @Test public void getHoldersResultShouldIgnoreUnknowntParameters() throws Exception { } @Test public void getHoldersResultShouldIgnoreINParameters() throws Exception { } @Test public void shouldRuninvokeForOneWayMethod() throws Exception { } @Test public void shouldRuninvokeForMethods() throws Exception { } @Test public void shouldRuninvokeForMethodsApplyingMapping() throws Exception { }public class TestedBySample { /** * @param args */ public static void main( String[] args ) { TestedBySample sample = new TestedBySample(); System.out.print(sample.add(1, 2)); } @TestedBy( testClass = "it.javalinux.testedby.TestedBySampleTest", testMethod = "addShouldWork" ) public int add( int i, int j ) { return i + j; } @TestedByList( {@TestedBy( testClass = "it.javalinux.testedby.TestedBySampleTest", testMethod = "addShouldWork" ), @TestedBy( testClass = "it.javalinux.testedby.TestedBySampleTest", testMethod = "addShouldWork2" )} ) public int add2( int i, int j ) { return i + j; } }public interface APIInterface { @TestedBy( testClass = "it.javalinux.testedby.APITest", testMethod = "shouldAddTwoAndThree" ) public int add(int a, int b);} public class APIImplOne { public int add(int a, int b) {return a + b;} public class APIImplTwo { public int add(int a, int b) {return a - b;} public class APITest { private APIInterface instance; @BeforeTestedBy public beforeTestedBy(APIInterface instance) {this.instance = instance; } public void shouldAddTwoAndThree() {assertThat(instance.add(3,2), is(5)); } }"ClassUnderTest.methodUnderTest shouldThrowExceptionWithNullParameter doen't pass"
"Failure: methodUnderTest in ClassUnderTest doesn't throw exception with null parameter, but it should!"