只要做Java开发的,99%的都用过JUnit。在JUnit4里面除了@Test, @Before, @BeforeClass 这样基本的特性,JUnit4还有些很酷但是大家平时不太用的特性。我这里做一下介绍,大家可以用一下,或者至少把玩一下:) 以下特性都基于4.8版本。
当需要同时测试testcase的时候,你不需要为自己写thread来做这个事情。JUnit4已经有了这个特性,而且还提供多种同步选择。例如:
/** * @author 卢声远<[email protected]> */ public class ParallelComputerTest { @Test public void test() { Class[] cls={ParallelTest1.class,ParallelTest2.class }; //Parallel among classes JUnitCore.runClasses(ParallelComputer.classes(), cls); //Parallel among methods in a class JUnitCore.runClasses(ParallelComputer.methods(), cls); //Parallel all methods in all classes JUnitCore.runClasses(new ParallelComputer(true, true), cls); } public static class ParallelTest1{ @Test public void a(){} @Test public void b(){} } public static class ParallelTest2{ @Test public void a(){} @Test public void b(){} } }
你有3种同步方式:
1: ParallelComputer.classes():所有测试类同时开始执行,但是每个类里面的方法还是顺序执行。在例子里面ParallelTest1 和ParallelTest2 同时开始,但是各自的a(),b() 还是顺序执行。
2: ParallelComputer.methods():测试类顺序执行,但是每个类里面的方法是同时开始执行。在例子里面ParallelTest1 的a() 和b() 同时开始,等结束之后再开始ParallelTest2 。
3: new ParallelComputer(true, true):所有测试类里面方法同时开始执行。在例子里面4个方法同时开始执行。
很有意思吧。
当你有很多testcase,但是你不想每次都执行一遍的时候。你可以把testcase分成若干类,然后就可以分类有选择的来执行这些testcase。
例子:譬如你有2类testcase,一类是重要的用Important.class表示,还有一类不那么重要的用Secondary.class表示。
/** * @author 卢声远<[email protected]> */ interface Important{}; interface Secondary{}; @RunWith(Categories.class) @IncludeCategory(Important.class) @ExcludeCategory(Secondary.class) @SuiteClasses( { CategoryTest.Alpha.class, CategoryTest.Beta.class }) public class CategoryTest { @Category(Important.class) public static class Alpha{//Alpha is Important except b @Test public void a(){} @Test @Category(Secondary.class) public void b(){} } public static class Beta{ @Test @Category(Important.class) public void a(){}//a is Important } }
当你执行后会发现只有Alpha.a() 和Beta.a() 执行到,Alpha.b() 被@ExcludeCategory 掉了。
当需要反复测试大量testcase的时候,你往往比较关注那些前一次失败的case。这个时候你就可以利用MaxCore特性在每次执行testcase的时候优先执行那些上次失败的case。
例如:
/** * @author 卢声远<[email protected]> */ public class MaxCoreTest { private MaxCore fMax; @Before public void createMax() { File fMaxFile= new File("MaxCore.ser"); fMax= MaxCore.storedLocally(fMaxFile); } @Test public void test(){ Request request= Request.aClass(Delta.class); fMax.run(request); fMax.run(request);//b->c->a } public static class Delta{ @Test public void a(){} @Test public void b(){ Assert.fail(); } @Test public void c(){} } }
可以观察到第2次执行的时候Delta.b() 由于第1次的失败而提前到了最先执行。
当需要测试不同输入参数的时候是不是要写一大堆testcase?不需要,因为JUnit4提供了参数化测试数据的特性。例如你想要测试2个整型数据作为输入参数的时候:
/** * @author 卢声远<[email protected]> */ @RunWith(Theories.class) public class DataPointTest { @DataPoint public static int ONE= 1; @DataPoint public static int TWO= 2; /* You could also use @DataPoints instead of @DataPoint @DataPoints public static int[] points= { 1, 2 };*/ @Theory public void test(int first, int second) { } }
通过观察test() 被执行了4次,每次不同的组合作为参数输入。而且如果参数数目过多,你可以通过@DataPoints 一下子把参数都设进去。用过@RunWith(Parameterized.class) 的朋友可以和DataPoint做一下比较。
这个功能也是参数化数据,只不过它是直接在参数上配置。例如:
@Theory public void test2(@TestedOn(ints={1,2})int first) { System.out.println(first); }
结果打印出来"1 ,2" 。
这个我认为倒是一个小功能,它只是把测试失败的结果以比较美观的格式打出来。例如:
Result result = JUnitCore.runClasses(SomeTest.class); System.out.println(new PrintableResult(result.getFailures()));