如何使用理論機(jī)制
在 JUnit 4.4 的理論機(jī)制中,每個(gè)測(cè)試方法不再是由注釋 @Test 指定的無(wú)參測(cè)試函數(shù),而是由注釋 @Theory 指定的帶參數(shù)的測(cè)試函數(shù),這些參數(shù)來(lái)自一個(gè)數(shù)據(jù)集(data sets),數(shù)據(jù)集通過(guò)注釋 @DataPoint 指定。
JUnit 4.4 會(huì)自動(dòng)將數(shù)據(jù)集中定義的數(shù)據(jù)類型和理論測(cè)試方法定義的參數(shù)類型進(jìn)行比較,如果類型相同,會(huì)將數(shù)據(jù)集中的數(shù)據(jù)通過(guò)參數(shù)一一傳入到測(cè)試方法中。數(shù)據(jù)集中的每一個(gè)數(shù)據(jù)都會(huì)被傳入到每個(gè)相同類型的參數(shù)中。這時(shí)有人會(huì)問(wèn)了,如果參數(shù)有多個(gè),而且類型都和數(shù)據(jù)集中定義的數(shù)據(jù)相同,怎么辦?答案是,JUnit 4.4 會(huì)將這些數(shù)據(jù)集中的數(shù)據(jù)進(jìn)行一一配對(duì)組合(所有的組合情況都會(huì)被考慮到),然后將這些數(shù)據(jù)組合統(tǒng)統(tǒng)通過(guò)參數(shù),一一傳入到理論的測(cè)試方法中,但是用戶可以通過(guò)假設(shè)機(jī)制(assumption)在斷言函數(shù)(assertion)執(zhí)行這些參數(shù)之前,對(duì)這些通過(guò)參數(shù)傳進(jìn)來(lái)的數(shù)據(jù)集中的數(shù)據(jù)進(jìn)行限制和過(guò)濾,達(dá)到有目的地部分地將自己想要的參數(shù)傳給斷言函數(shù)(assertion)來(lái)測(cè)試。只有滿足所有假設(shè)的數(shù)據(jù)才會(huì)執(zhí)行接下來(lái)的測(cè)試用例,任何一個(gè)假設(shè)不滿足的數(shù)據(jù),都會(huì)自動(dòng)跳過(guò)該理論測(cè)試函數(shù)(假設(shè) assumption 不滿足的數(shù)據(jù)會(huì)被忽略,不再執(zhí)行接下來(lái)的斷言測(cè)試),如果所有的假設(shè)都滿足,測(cè)試用例斷言函數(shù)不通過(guò)才代表著該理論測(cè)試不通過(guò)。
清單 13 理論機(jī)制舉例
import static org.hamcrest.Matchers.*; //指定接下來(lái)要使用的Matcher匹配符
import static org.junit.Assume.*; //指定需要使用假設(shè)assume*來(lái)輔助理論Theory
import static org.junit.Assert.*; //指定需要使用斷言assert*來(lái)判斷測(cè)試是否通過(guò)
import org.junit.experimental.theories.DataPoint; //需要使用注釋@DataPoint來(lái)指定數(shù)據(jù)集
import org.junit.experimental.theories.Theories; //接下來(lái)@RunWith要指定Theories.class
import org.junit.experimental.theories.Theory; //注釋@Theory指定理論的測(cè)試函數(shù)
import org.junit.runner.RunWith; //需要使用@RunWith指定接下來(lái)運(yùn)行測(cè)試的類
import org.junit.Test;
//注意:必須得使用@RunWith指定Theories.class
@RunWith(Theories.class)
public class TheoryTest {
//利用注釋@DataPoint來(lái)指定一組數(shù)據(jù)集,這些數(shù)據(jù)集中的數(shù)據(jù)用來(lái)證明或反駁接下來(lái)定義的Theory理論,
//testNames1和testNames2這兩個(gè)理論Theory測(cè)試函數(shù)的參數(shù)都是String,所以Junit4.4會(huì)將這5個(gè)
//@DataPoint定義的String進(jìn)行兩兩組合,統(tǒng)統(tǒng)一一傳入到testNames1和testNames2中,所以參數(shù)名year
//和name是不起任何作用的,"2007"同樣有機(jī)會(huì)會(huì)傳給參數(shù)name,"Works"也同樣有機(jī)會(huì)傳給參數(shù)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來(lái)指定測(cè)試函數(shù),而不是@Test
@Theory
public void testNames1( String year, String name ) {
assumeThat( year, is("2007") ); //year必須是"2007",否則跳過(guò)該測(cè)試函數(shù)
System.out.println( year + "-" + name );
assertThat( year, is("2007") ); //這里的斷言語(yǔ)句沒(méi)有實(shí)際意義,這里舉此例只是為了不中斷測(cè)試
}
//注意:使用@Theory來(lái)指定測(cè)試函數(shù),而不是@Test
@Theory
public void testNames2( String year, String name ) {
assumeThat(year, is("2007")); //year必須是"2007",否則跳過(guò)該測(cè)試函數(shù)
//name必須既不是"2007"也不是"2008",否則跳過(guò)該測(cè)試函數(shù)
assumeThat(name, allOf( not(is("2007")), not(is("2008"))));
System.out.println( year + "-" + name );
assertThat( year, is("2007") ); //這里的斷言語(yǔ)句沒(méi)有實(shí)際意義,這里舉此例只是為了不中斷測(cè)試
}
結(jié)果輸出:
第一個(gè)Theory打印出:
2007-2007
2007-2008
2007-developer
2007-Works
2007-developerWorks
第二個(gè)Theory打印出:
2007-developer
2007-Works
2007-developerWorks
結(jié)束語(yǔ)
本文通過(guò)詳細(xì)深入的理論介紹和簡(jiǎn)單易懂的實(shí)例全面剖析了 JUnit 4.4 的三個(gè)新特性:
提供了新的斷言語(yǔ)法(assertion syntax)——assertThat提供了假設(shè)機(jī)制(assumptions)
提供了理論機(jī)制(Theories)
相信讀者看完后一定會(huì)對(duì) JUnit 4.4 有著非常深入的了解并可以輕松將其運(yùn)用到自己的開(kāi)發(fā)工程中。