副标题#e#
跟着当前 Java 开拓的加倍成熟,Agile 和 TDD 的加倍风行,自动化测试的呼声也越来越高。若想将单位测试变得自动化,自然 JUnit 这把利器必不行少,这也是 JUnit 自 1997 年降生以来在 Java 开拓业界一直相当风行的原因。
JUnit 是针对 Java 语言的一个单位测试框架,它被认为是迄今为止所开拓的最重要的第三方 Java 库。 JUnit 的利益是整个测试进程无需人的参加,无需阐明和判定最终测试功效是否正确,并且可以很容易地一次性运行多个测试。 JUnit 的呈现促进了测试的流行,它使得 Java 代码更结实,更靠得住,Bug 比以前更少。
JUnit 自从问世以来一直在不断的推出新版本,今朝最新的版本是 2007 年 7 月宣布的 JUnit 4.4,它是继 JUnit4 以来最大的刊行版,提供了许多有用的新特性。本文将假设读者已经具有 JUnit 4 的利用履历。
JUnit 4.4 概述
JUnit 设计的目标就是有效地抓住编程人员写代码的意图,然后快速查抄他们的代码是否与他们的意图相匹配。 JUnit 成长至今,版本不断的翻新,可是所有版本都一致致力于办理一个问题,那就是如何发明编程人员的代码意图,而且如何使得编程人员越发容易地表达他们的代码意图。JUnit 4.4 也是为了如何可以或许更好的到达这个目标而呈现的。
JUnit 4.4 主要提供了以下三个大方面的新特性来更好的抓住编程人员的代码意图:
提供了新的断言语法(Assertion syntax)——assertThat
提供了假设机制(Assumption)
提供了理论机制(Theory)
新的断言语法(Assertion syntax)—— assertThat
JUnit 4.4 进修 JMock,引入了 Hamcrest 匹配机制,使得措施员在编写单位测试的 assert 语句时,可以具有更强的可读性,并且也越发机动。
Hamcrest 是一个测试的框架,它提供了一套通用的匹配符 Matcher,机动利用这些匹配符界说的法则,措施员可以越发准确的表达本身的测试思想,指定所想设定的测试条件。好比,有时候界说的测试数据范畴太准确,往往是若干个牢靠简直定值,这时会导致测试很是懦弱,因为接下来的测试数据只要稍稍有变革,就大概导致测试失败(好比 assertEquals( x, 10 ); 只能判定 x 是否便是 10,假如 x 不便是 10,测试失败);有时候指定的测试数据范畴又不足太准确,这时有大概会造成某些本该会导致测试不通过的数据,仍然会通过接下来的测试,这样就会低落测试的代价。 Hamcrest 的呈现,给措施员编写测试用例提供了一套法则和要领,利用其可以越发准确的表达措施员所期望的测试的行为。(详细 Hamcrest 的利用,请参阅 参考资料)
JUnit 4.4 团结 Hamcrest 提供了一个全新的断言语法——assertThat。措施员可以只利用 assertThat 一个断言语句,团结 Hamcrest 提供的匹配符,就可以表达全部的测试思想。
assertThat 的根基语法如下:
清单 1 assertThat 根基语法
assertThat( [value], [matcher statement] );
value 是接下来想要测试的变量值;
matcher statement 是利用 Hamcrest 匹配符来表达的对前面变量所期望的值的声明,假如 value 值与 matcher statement 所表达的期望值相符,则测试乐成,不然测试失败。
#p#副标题#e#
assertThat 的利益
利益 1:以前 JUnit 提供了许多的 assertion 语句,如:assertEquals,assertNotSame,assertFalse,assertTrue,assertNotNull,assertNull 等,此刻有了 JUnit 4.4,一条 assertThat 即可以替代所有的 assertion 语句,这样可以在所有的单位测试中只利用一个断言要领,使得编写测试用例变得简朴,代码气势气魄变得统一,测试代码也更容易维护。
利益 2:assertThat 利用了 Hamcrest 的 Matcher 匹配符,用户可以利用匹配符划定的匹配准则准确的指定一些想设定满意的条件,具有很强的易读性,并且利用起来越发机动。如清单 2 所示:
清单 2 利用匹配符 Matcher 和不利用之间的较量
// 想判定某个字符串 s 是否含有子字符串 "developer" 或 "Works" 中间的一个
// JUnit 4.4 以前的版本:assertTrue(s.indexOf("developer")>-1||s.indexOf("Works")>-1 );
// JUnit 4.4:
assertThat(s, anyOf(containsString("developer"), containsString("Works")));
// 匹配符 anyOf 暗示任何一个条件满意则创立,雷同于逻辑或 "||", 匹配符 containsString 暗示是否含有参数子
// 字符串,文章接下来会对匹配符举办详细先容
利益 3:assertThat 不再像 assertEquals 那样,利用较量难解的“谓宾主”语法模式(如:assertEquals(3, x);),相反,assertThat 利用了雷同于“主谓宾”的易读语法模式(如:assertThat(x,is(3));),使得代码越发直观、易读。
利益 4:可以将这些 Matcher 匹配符连系起来机动利用,到达更多目标。如清单 3 所示:
清单 3 Matcher 匹配符连系利用
#p#分页标题#e#
// 连系匹配符not和equalTo暗示“不便是”
assertThat( something, not( equalTo( "developer" ) ) );
// 连系匹配符not和containsString暗示“不包括子字符串”
assertThat( something, not( containsString( "Works" ) ) );
// 连系匹配符anyOf和containsString暗示“包括任何一个子字符串”
assertThat(something, anyOf(containsString("developer"), containsString("Works")));
利益 5:错误信息越发易懂、可读且具有描写性(descriptive)。
JUnit 4.4 以前的版本默认堕落伍不会抛出特别提示信息,如:
assertTrue( s.indexOf("developer") > -1 || s.indexOf("Works") > -1 );
假如该断言堕落,只会抛出无用的错误信息,如:junit.framework.AssertionFailedError:null。
假如想在堕落时想打印出一些有用的提示信息,必需得措施员别的手动写,如:assertTrue( "Expected a string containing 'developer' or 'Works'",
s.indexOf("developer") > -1 || s.indexOf("Works") > -1 );
很是的不利便,并且需要特别代码。
JUnit 4.4 会默认自动提供一些可读的描写信息,如清单 4 所示:
清单 4 JUnit 4.4 默认提供一些可读的描写性错误信息
String s = "hello world!";
assertThat( s, anyOf( containsString("developer"), containsString("Works") ) );
// 假如堕落伍,系统会自动抛出以下提示信息:
java.lang.AssertionError:
Expected: (a string containing "developer" or a string containing "Works")
got: "hello world!"
利益 6:开拓人员可以通过实现 Matcher 接口,定制本身想要的匹配符。当开拓人员发明本身的某些测试代码在差异的测试中反复呈现,常常被利用,这时用户就可以自界说匹配符,将这些代码绑定在一个断言语句中,从而可以到达淘汰反复代码而且越发易读的目标。(详细怎么实现自界说可设置的匹配符,请参阅参考资料)
如何利用 assertThat
JUnit 4.4 自带了一些 Hamcrest 的匹配符 Matcher,可是只有有限的几个,在类 org.hamcrest.CoreMatchers 中界说,要想利用他们,必需导入包 org.hamcrest.CoreMatchers.*。
假如想利用一些其他更多的匹配符 Matcher,可以从 Hamcrest 网页下载 hamcrest-library-1.1.jar 和 hamcrest-core-1.1.jar(请参阅 参考资料),并将其插手到工程库中,所有的匹配符都在类 org.hamcrest.Matchers 中界说,要想利用,必需得在代码中 import static org.hamcrest.Matchers.*;。假如利用外部的匹配符,最好就不要再利用 JUnit 4.4 自带的匹配符了,因为这样容易导致匹配符 Matcher 反复界说,编译大概会堕落(ambiguous for the type)。 JUnit 4.4 答允利用 Hamcrest 来利用更多的匹配符,这照旧 JUnit 第一次答允在本身的工程中利用第三方类。
留意:
assertThat 仍然是断言语句,所以要想利用,必需还得 import static org.junit.Assert.*;;
固然 assertThat 可以取代以前所有的断言语句,可是以前的所有 assert 语句仍然可以继承利用;
清单 5 罗列了大部门 assertThat 的利用例子:
清单 5 assertThat 利用举例
//一般匹配符
// allOf匹配符表白假如接下来的所有条件必需都创立测试才通过,相当于“与”(&&)
assertThat( testedNumber, allOf( greaterThan(8), lessThan(16) ) );
// anyOf匹配符表白假如接下来的所有条件只要有一个创立则测试通过,相当于“或”(||)
assertThat( testedNumber, anyOf( greaterThan(16), lessThan(8) ) );
// anything匹配符表白无论什么条件,永远为true
assertThat( testedNumber, anything() );
// is匹配符表白假如前面待测的object便是后头给出的object,则测试通过
assertThat( testedString, is( "developerWorks" ) );
// not匹配符和is匹配符正好相反,表白假如前面待测的object不便是后头给出的object,则测试通过
assertThat( testedString, not( "developerWorks" ) );
//字符串相关匹配符
// containsString匹配符表白假如测试的字符串testedString包括子字符串"developerWorks"则测试通过
assertThat( testedString, containsString( "developerWorks" ) );
// endsWith匹配符表白假如测试的字符串testedString以子字符串"developerWorks"末了则测试通过
assertThat( testedString, endsWith( "developerWorks" ) );
// startsWith匹配符表白假如测试的字符串testedString以子字符串"developerWorks"开始则测试通过
assertThat( testedString, startsWith( "developerWorks" ) );
// equalTo匹配符表白假如测试的testedValue便是expectedValue则测试通过,equalTo可以测试数值之间,字
//符串之间和工具之间是否相等,相当于Object的equals要领
assertThat( testedValue, equalTo( expectedValue ) );
// equalToIgnoringCase匹配符表白假如测试的字符串testedString在忽略巨细写的环境下便是
//"developerWorks"则测试通过
assertThat( testedString, equalToIgnoringCase( "developerWorks" ) );
// equalToIgnoringWhiteSpace匹配符表白假如测试的字符串testedString在忽略头尾的任意个空格的环境下等
//于"developerWorks"则测试通过,留意:字符串中的空格不能被忽略
assertThat( testedString, equalToIgnoringWhiteSpace( "developerWorks" ) );
//数值相关匹配符
// closeTo匹配符表白假如所测试的浮点型数testedDouble在20.0±0.5范畴之内则测试通过
assertThat( testedDouble, closeTo( 20.0, 0.5 ) );
// greaterThan匹配符表白假如所测试的数值testedNumber大于16.0则测试通过
assertThat( testedNumber, greaterThan(16.0) );
// lessThan匹配符表白假如所测试的数值testedNumber小于16.0则测试通过
assertThat( testedNumber, lessThan (16.0) );
// greaterThanOrEqualTo匹配符表白假如所测试的数值testedNumber大于便是16.0则测试通过
assertThat( testedNumber, greaterThanOrEqualTo (16.0) );
// lessThanOrEqualTo匹配符表白假如所测试的数值testedNumber小于便是16.0则测试通过
assertThat( testedNumber, lessThanOrEqualTo (16.0) );
//collection相关匹配符
// hasEntry匹配符表白假如测试的Map工具mapObject含有一个键值为"key"对应元素值为"value"的Entry项则
//测试通过
assertThat( mapObject, hasEntry( "key", "value" ) );
// hasItem匹配符表白假如测试的迭代工具iterableObject含有元素“element”项则测试通过
assertThat( iterableObject, hasItem ( "element" ) );
// hasKey匹配符表白假如测试的Map工具mapObject含有键值“key”则测试通过
assertThat( mapObject, hasKey ( "key" ) );
// hasValue匹配符表白假如测试的Map工具mapObject含有元素值“value”则测试通过
assertThat( mapObject, hasValue ( "key" ) );
假设机制(Assumption)
#p#分页标题#e#
抱负环境下,写测试用例的开拓人员可以明晰的知道所有导致他们所写的测试用例不通过的处所,可是有的时候,这些导致测试用例不通过的处所并不是很容易的被发明,大概埋没得很深,从而导致开拓人员在写测试用例时很难预测到这些因素,并且往往这些因素并不是开拓人员当初设计测试用例时真正目标,他们的测试点是但愿测试出被测代码中此外堕落处所。
好比,一个测试用例运行的 locale(如:Locale.US)与之前开拓人员设计该测试用例时所设想的差异(如:Locale.UK),这样会导致测试不通过,可是这大概并不是开拓人员之前设计测试用例时所设想的测试出来的有用的失败功效(测试点并不是此,好比测试的真正目标是想判定函数的返回值是否为 true,返回 false 则测试失败),这时开拓人员可以通过编写一些特另外代码来消除这些影响(好比将 locale 作为参数传入到测试用例中,每次运行测试用例时,明晰指定 locale),可是耗费时间和精神来编写这些不是测试用例基础目标的特别代码其实是种挥霍,这时就可以利用 Assumption 假设机制来轻松到达特别代码的目标。编写该测试用例时,首先假设 locale 必需是 Locale.UK,假如运行时 locale 是 Locale.UK,则继承执行该测试用例函数,假如是其它的 locale,则跳过该测试用例函数,执行该测试用例函数以外的代码,这样就不会因为 locale 的问题导致测试堕落。
JUnit 4.4 团结 Hamcrest 库提供了 assumeThat 语句,开拓人员可以利用其共同匹配符 Matcher 设计所有的假设条件(语法和 assertThat 一样)。同样为了利便利用,JUnit 4.4 还专门提供了 assumeTrue,assumeNotNull 和 assumeNoException 语句。
假设机制(Assumption)的利益
利益 1:通过对 runtime 变量举办取值假设,从而不会因为一个测试用例的不通过而导致整个测试失败而间断(the test passes),使得测试越发连贯。
#p#分页标题#e#
开拓人员编写单位测试时,常常会在一个测试中包括若干个测试用例函数,这时若是碰着某个测试用例函数不通过,整个单位测试就会终止。这将导致测试不连贯,因为开拓人员往往但愿一次能运行多个测试用例函数,不通过的测试用例函数不要影响到剩下的测试用例函数的运行,不然会给 debug 调试带来很大的难度。
开拓人员编写单位测试时,有时是预测不了传入到单位测试要领中的变量值的,并且这些值有时并不是开拓人员所期望的,因为他们会导致测试用例不通过并间断整个测试,所以开拓人员需要跳过这些导致测试用例函数不通过的异常环境。
清单 6 假设机制利益 1 举例
//@Test 注释表白接下来的函数是 JUnit4 及其今后版本的测试用例函数
@Test
public void testAssumptions() {
//假设进入testAssumptions时,变量i的值为10,假如该假设不满意,措施不会执行assumeThat后头的语句
assumeThat( i, is(10) );
//假如之前的假设创立,会打印"assumption is true!"到节制台,不然直接调出,执行下一个测试用例函数
System.out.println( "assumption is true!" );
}
利益 2:操作假设可以节制某个测试用例的运行时间,让其在本身期望的时候运行(run at a given time)。
清单 7 假设机制利益 2 举例
@Test
//测试用例函数veryLongTest()执行需要很长时间,所以开拓人员不是每次都想运行它,可以通过判定是否界说了
//”DEV”情况变量来选择性地执行该测试用例
public void veryLongTest() throws Exception {
//假设情况变量”DEV”为空,即假如之前通过System.setProperty界说过”DEV”情况变量(不为空),则自动跳过
//veryLongTest中假设后剩下的语句,去执行下一个JUnit测试用例,不然执行假设后接下来的语句
assumeThat( System.getProperty( "DEV" ), nullValue() );
System.out.println("running a long test");
Thread.sleep( 90 * 1000 );
}
如何利用 Assumption 假设机制
开拓人员可以利用 assumeThat 并共同 hamcrest 的匹配符 Matcher,对即将被传入到单位测试用例函数中的 runtime 变量值做准确的假设,假如假设不正确(即当前 runtime 变量的取值不满意所假设的条件),则不会将该变量传给该测试用例中假设后头的语句,即措施会从该 assumeThat 地址的 @Test 测试函数中直接自动跳出(test automatically quietly passes,values that violate assumptions are quietly ignored),去执行下一个 @Test 函数,使得原来会间断的测试此刻不会间断。
利用假设机制必需得留意以下几点:
由于 JUnit 4.4 引用了 Hamcrest 匹配符库,所以利用 assumeThat 就可以编写所有的假设语句。可是为了利便利用,JUnit 4.4 除 assumeThat 之外,还提供了 assumeTrue,assumeNotNull 和 assumeNoException 语句。
要利用 assume* 假设语句,必需得 import static org.junit.Assume.*;。
假如引用了第三方 hamcrest 的匹配符库,必需得 import static org.hamcrest.Matchers.*;,假如引用 JUnit 4.4 自带的匹配符库,需要 import static org.hamcrest.CoreMatchers.*;。
清单 8 假设机制利用举例
例1:
@Test
public void filenameIncludesString() {
//假如文件脱离符不是’/’(forward slash),则不执行assertThat断言测试,直接跳过该测试用例函数
assumeThat(File.separatorChar, is('/'));
//判定文件名fileName是否含有字符串"developerWorks"
assertThat( fileName, containsString( "developerWorks" ) );
}
例2:
@Test
public void filenameIncludesString() {
//bugFixed不是JUnit4.4的函数,是开拓人员本身工程中界说的函数,暗示判定指定的defect是否
//被批改了,假如被批改,则返回true,不然返回false。这里假设缺陷13356被批改后才举办余下单位测试
assumeTrue( bugFixed("13356") );
//判定文件名fileName是否含有字符串"developerWorks"
assertThat( fileName, containsString( "developerWorks" ) );
}
理论机制(Theory)
为什么要引用理论机制(Theory)
当今软件开拓中,测试驱动开拓(TDD — Test-driven development)加倍风行。为什么 TDD 会如此风行呢?因为它确实拥有许多利益,它答允开拓人员通过简朴的例子来指定和表白他们代码的行为意图。
TDD 的利益:
使得开拓人员对即将编写的软件任务具有更清晰的认识,使得他们在思考如何编写代码之前先仔细思考如何设计软件。
对测试开拓人员所实现的代码提供了快速和自动化的支持。
#p#分页标题#e#
提供了一系列可以重用的回归测试用例(regression test case),这些测试用例可以用来检测将来添加的新代码是否改变了以前系统界说的行为(测试代码兼容性)。
然而,TDD 也同样具有必然的范围性。对付开拓人员来说,只用一些详细有限的简朴例子来表达措施的行为往往远远不足。有许多代码行为可以很容易并且准确的用语言来描写,却很难用一些简朴的例子来表达清楚,因为他们需要大量的甚至无限的具编制子才可以到达被描写清楚的目标,并且有时有限的例子基础不能包围所有的代码行为。
以下列出的代码行为反应了 TDD 的范围性:
将十进制整数转换成罗马数字,然后再将其转换回十进制数,并保持原有的数值。(需要大量的测试用例,有限的测试数据大概测不出所实现的代码的错误)。
对一个工具举办操纵,但愿功效仍然便是本来的工具。(需要思量各类百般范例的工具)
在任何一个钱币的 collection 中添加一个工具 dollar,需要发生出别的一个新的与以前差异的 collection 。(需要思量所有的 collection 范例的工具)。
理论(Theory)的呈现就是为了办理 TDD 这个问题。 TDD 为组织筹划开拓流程提供了一个要领,先用一些详细的例子(测试用例 test case)来描写系统代码的行为,然后再将这些行为用代码语句举办归纳综合性的总的告诉(代码实现 implementation)。而 Theory 就是对传统的 TDD 举办一个延伸和扩展,它使得开拓人员从开始的界说测试用例的阶段就可以通过参数集(理论上是无限个参数)对代码行为举办归纳综合性的总的告诉,我们叫这些告诉为理论。理论就是对那些需要无穷个测试用例才气正确描写的代码行为的归纳综合性告诉。结公道论(Theory)和测试一起,可以轻松的描写代码的行为并发明 BUG 。开拓人员都知道他们代码所想要实现的归纳综合性的总的目标,理论使得他们只需要在一个处所就可以快速的指定这些目标,而不要将这些目标翻译成大量的独立的测试用例。
理论机制的利益
利益 1:理论(Theory)使得开拓完全抽象的接口(Interface)越发容易。
利益 2:理论仍然可以重用以前的测试用例,因为以前的很多传统的详细的测试用例仍然可以被轻松的改写成理论(Theory)测试实例。
利益 3:理论(Theory)可以测试出一些原本测试用例没测出来的 bugs 。
利益 4:理论答允共同自动化测试东西举办利用,自动化东西通过大量的数据点来测试一个理论,从而可以放大加强理论的结果。操作自动化东西来阐明代码,找出可以证明理论错误的值。
下面通过一个简朴的例子来慢慢先容理论的利益。
好比设计一个专门用来钱币计较的计较器,首先需要给代码行为编写测试用例(这里以英镑 Pound 的乘法为例),如清单 9 所示:
清单 9 英镑 Pound 乘法的一个测试用例
@Test
public void multiplyPoundsByInteger() {
assertEquals( 10, new Pound(5).times(2).getAmount() );
}
这时很自然的就会想到一个测试用例大概不足,需要再多一个,如清单 10 所示:
清单 10 英镑 Pound 乘法的两个测试用例
@Test
public void multiplyPoundsByInteger () {
assertEquals( 10, new Pound(5).times(2).getAmount() );
assertEquals( 15, new Pound(5).times(3).getAmount() );
}
可是此时您大概又会发明这两个测试用例照旧很有限,您所但愿的是测试所有的整数,而不可是 2,3 和 5,这些只是您所想要的测试的数据的子集,两个测试用例并不能完全与您所想要测试的代码的行为相等价,您需要更多的测试用例,此时就会发明需要许多的特别事情来编写这些测试用例,更可骇的是,您会发明您需要测试用例的并不可是简朴的几个,大概是成千上万个甚至无穷个测试用例才气满意等价您的代码行为的目标。
很自然的,您会想到用清单 11 所示的代码来表达您的测试思想。
清单 11 利用变量帮助编写测试用例
//操作变量来取代详细数据表达测试思想
public void multiplyAnyAmountByInteger(int amount, int multiplier) {
assertEquals( amount * multiplier,
new Pound( amount ).times( multiplier ).getAmount() );
}
操作清单 11 的 multiplyAnyAmountByInteger 要领,可以轻松将测试用例改写成如清单 12 所示:
清单 12 改写的英镑 Pound 乘法的测试用例
@Test
public void multiplyPoundsByInteger () {
multiplyAnyAmountByInteger(5, 2);
multiplyAnyAmountByInteger(5, 3);
}
如清单 12 所示,今后若想增加测试用例,只要不断挪用 multiplyAnyAmountByInteger 要领并赋予参数值即可。
#p#分页标题#e#
要领 multiplyAnyAmountByInteger 就是一个理论的简朴例子,理论就是一个带有参数的要领,其行为就是对任何参数都是正常的返回,不会抛出断言错误和其它异常。理论就是对一组数据举办归纳综合性的告诉,就像一个科学理论一样,假如没有对所有大概呈现的环境都举办尝试,是不能证明该理论是正确的,可是只要有一种错误环境呈现,该理论就不创立。相反地,一个测试就是对一个单独数据的单独告诉,就像是一个科学理论的尝试一样。
如何利用理论机制
在 JUnit 4.4 的理论机制中,每个测试要领不再是由注释 @Test 指定的无参测试函数,而是由注释 @Theory 指定的带参数的测试函数,这些参数来自一个数据集(data sets),数据集通过注释 @DataPoint 指定。
JUnit 4.4 会自动将数据会合界说的数据范例和理论测试要领界说的参数范例举办较量,假如范例沟通,会将数据会合的数据通过参数一一传入到测试要领中。数据会合的每一个数据城市被传入到每个沟通范例的参数中。这时有人会问了,假如参数有多个,并且范例都和数据会合界说的数据沟通,怎么办?谜底是,JUnit 4.4 会将这些数据会合的数据举办一一配对组合(所有的组合环境城市被思量到),然后将这些数据组合统统通过参数,一一传入到理论的测试要领中,可是用户可以通过假设机制(assumption)在断言函数(assertion)执行这些参数之前,对这些通过参数传进来的数据会合的数据举办限制和过滤,到达有目标地部门地将本身想要的参数传给断言函数(assertion)来测试。只有满意所有假设的数据才会执行接下来的测试用例,任何一个假设不满意的数据,城市自动跳过该理论测试函数(假设 assumption 不满意的数据会被忽略,不再执行接下来的断言测试),假如所有的假设都满意,测试用例断言函数不通过才代表着该理论测试不通过。
清单 13 理论机制举例
import static org.hamcrest.Matchers.*; //指定接下来要利用的Matcher匹配符
import static org.junit.Assume.*; //指定需要利用假设assume*来帮助理论Theory
import static org.junit.Assert.*; //指定需要利用断言assert*来判定测试是否通过
import org.junit.experimental.theories.DataPoint; //需要利用注释@DataPoint来指定命据集
import org.junit.experimental.theories.Theories; //接下来@RunWith要指定Theories.class
import org.junit.experimental.theories.Theory; //注释@Theory指定理论的测试函数
import org.junit.runner.RunWith; //需要利用@RunWith指定接下来运行测试的类
import org.junit.Test;
//留意:必需得利用@RunWith指定Theories.class
@RunWith(Theories.class)
public class TheoryTest {
//操作注释@DataPoint来指定一组数据集,这些数据会合的数据用来证明或辩驳接下来界说的Theory理论,
//testNames1和testNames2这两个理论Theory测试函数的参数都是String,所以Junit4.4会将这5个
//@DataPoint界说的String举办两两组合,统统一一传入到testNames1和testNames2中,所以参数名year
//和name是不起任何浸染的,"2007"同样有时机缘传给参数name,"Works"也同样有时机传给参数year
@DataPoint public static String YEAR_2007 = "2007";
@DataPoint public static String YEAR_2008 = "2008";
@DataPoint public static String NAME1 = "developer";
@DataPoint public static String NAME2 = "Works";
@DataPoint public static String NAME3 = "developerWorks";
//留意:利用@Theory来指定测试函数,而不是@Test
@Theory
public void testNames1( String year, String name ) {
assumeThat( year, is("2007") ); //year必需是"2007",不然跳过该测试函数
System.out.println( year + "-" + name );
assertThat( year, is("2007") ); //这里的断言语句没有实际意义,这里举此例只是为了不间断测试
}
//留意:利用@Theory来指定测试函数,而不是@Test
@Theory
public void testNames2( String year, String name ) {
assumeThat(year, is("2007")); //year必需是"2007",不然跳过该测试函数
//name必需既不是"2007"也不是"2008",不然跳过该测试函数
assumeThat(name, allOf( not(is("2007")), not(is("2008"))));
System.out.println( year + "-" + name );
assertThat( year, is("2007") ); //这里的断言语句没有实际意义,这里举此例只是为了不间断测试
}
功效输出:
第一个Theory打印出:
2007-2007
2007-2008
2007-developer
2007-Works
2007-developerWorks
第二个Theory打印出:
2007-developer
2007-Works
2007-developerWorks
竣事语
本文通过具体深入的理论先容和简朴易懂的实例全面分解了 JUnit 4.4 的三个新特性:
提供了新的断言语法(assertion syntax)——assertThat
提供了假设机制(assumptions)
提供了理论机制(Theories)
相信读者看完后必然会对 JUnit 4.4 有着很是深入的相识并可以轻松将其运用到本身的开拓工程中。