用Junit進(jìn)行單元測(cè)試很方便,尤其是Junit4引入了很多Annotation注解以后。看測(cè)試的示例:
待測(cè)試類:
- public class Calculator {
-
- public int add(int a, int b) {
- return a + b;
- }
-
- public int minus(int a, int b) {
- return a - b;
- }
-
- public int square(int n) {
- return n * n;
- }
-
-
- public void squareRoot(int n) {
- for(; ;)
- ;
- }
-
- public int multiply(int a, int b) {
- return a * b;
- }
-
- public int divide(int a, int b) throws Exception {
- if (0 == b) {
- throw new Exception("除數(shù)不能為零");
- }
- return a / b;
- }
- }
單元測(cè)試類:
- import org.junit.After;
- import org.junit.AfterClass;
- import org.junit.Assert;
- import org.junit.Before;
- import org.junit.BeforeClass;
- import org.junit.Ignore;
- import org.junit.Test;
-
- public class CalculatorTest {
-
- private Calculator cal = new Calculator();
-
- @BeforeClass
- public static void before()
- {
- System.out.println("global");
- }
-
- @AfterClass
- public static void after() {
- System.out.println("global destroy");
- }
-
- @Before
- public void setUp() throws Exception {
- System.out.println("一個(gè)測(cè)試開始。。");
- }
-
- @After
- public void tearDown() throws Exception {
- System.out.println("一個(gè)測(cè)試結(jié)束");
- }
-
- @Test
- @Ignore
- public void testAdd() {
- int result = cal.add(1, 2);
- Assert.assertEquals(3, result);
- }
-
- @Test
- public void testMinus() {
- int result = cal.minus(5, 2);
- Assert.assertEquals(3, result);
- }
-
- @Test
- public void testMultiply() {
- int result = cal.multiply(4, 2);
- Assert.assertEquals(8, result);
- }
-
- @Test(timeout = 1000)
- public void testSquareRoot() {
- cal.squareRoot(4);
- }
-
- @Test(expected = Exception.class)
- public void testDivide() throws Exception {
- System.out.println("teddd");
- cal.divide(4, 0);
- }
-
-
-
-
-
-
-
-
-
-
-
-
- }
在Eclipse里Run As -> JUnit Test,運(yùn)行測(cè)試類,Eclipse的JUnit的View顯示如:
可以看到,CalculatorTest類中總共有5個(gè)測(cè)試用例,ignore了一個(gè),3個(gè)測(cè)試用例通過,testSquareRoot測(cè)試不通過(因?yàn)槌瑫r(shí)),所以整個(gè)的測(cè)試結(jié)果飄紅了。同時(shí),控制臺(tái)的輸出結(jié)果為:
- global
- 一個(gè)測(cè)試開始。。
- 一個(gè)測(cè)試結(jié)束
- 一個(gè)測(cè)試開始。。
- 一個(gè)測(cè)試結(jié)束
- 一個(gè)測(cè)試開始。。
- 一個(gè)測(cè)試結(jié)束
- 一個(gè)測(cè)試開始。。
- teddd
- 一個(gè)測(cè)試結(jié)束
- global destroy
各種注解的說明:
@Test:
表明該方法是一個(gè)測(cè)試方法
@BeforeClass 和 @AfterClass:
測(cè)試用例初始化時(shí)執(zhí)行 @BeforeClass方法,當(dāng)所有測(cè)試執(zhí)行完畢之后,執(zhí)行@AfterClass進(jìn)行收尾工作。標(biāo)注、@BeforeClass 和 @AfterClass的方法必須是static的,因?yàn)榉椒▽⒃陬惐谎b載的時(shí)候就被調(diào)用,那時(shí)候還沒創(chuàng)建測(cè)試對(duì)象實(shí)例。
@Before: 使用了該元數(shù)據(jù)的方法在每個(gè)測(cè)試方法執(zhí)行之前都要執(zhí)行一次。
@After: 使用了該元數(shù)據(jù)的方法在每個(gè)測(cè)試方法執(zhí)行之后要執(zhí)行一次。
@Test(expected=*.class) : 通過@Test元數(shù)據(jù)中的expected屬性驗(yàn)證是否拋出期望的異常,expected屬性的值是一個(gè)異常的類型,如果拋出了期望的異常,則測(cè)試通過,否則不通過。
@Test(timeout=xxx): 該元數(shù)據(jù)傳入了一個(gè)時(shí)間(毫秒)給測(cè)試方法,如果測(cè)試方法在制定的時(shí)間之內(nèi)沒有運(yùn)行完,則測(cè)試也失敗。
@Ignore: 該元數(shù)據(jù)標(biāo)記的測(cè)試方法在測(cè)試中會(huì)被忽略。同時(shí)可以為該標(biāo)簽傳遞一個(gè)String的參數(shù),來表明為什么會(huì)忽略這個(gè)測(cè)試方法。比如:@lgnore("該方法還沒有實(shí)現(xiàn)"),在執(zhí)行的時(shí)候,僅會(huì)報(bào)告該方法沒有實(shí)現(xiàn),而不會(huì)運(yùn)行測(cè)試方法。
在test方法內(nèi)除了使用Assert的assertEquals()方法外,還能使用assertFalse()、assertTrue()、assertNull()、assertNotNull()、assertSame()、assertNotSame()等斷言函數(shù)。而且如果使用的是Junit4,結(jié)合Hamcrest,使用
assertThat([value], [matcher statement])方法可以實(shí)現(xiàn)更靈活的斷言判斷(前提是引入hamcrest的jar包)。
例如:
// is匹配符表明如果前面待測(cè)的object等于后面給出的object,則測(cè)試通過
assertThat( testedObj, is( object) );
// containsString匹配符表明如果測(cè)試的字符串包含指定的子字符串則測(cè)試通過
assertThat( testedString, containsString( "developerWorks" ) );
// greaterThan匹配符表明如果所測(cè)試的數(shù)值testedNumber大于16.0則測(cè)試通過
assertThat( testedNumber, greaterThan(16.0) );
// closeTo匹配符表明如果所測(cè)試的浮點(diǎn)型數(shù)testedDouble在20.0±0.5范圍之內(nèi)則測(cè)試通過
assertThat( testedDouble, closeTo( 20.0, 0.5 ) );
//hasItem匹配符表明被測(cè)的迭代對(duì)象含有元素element項(xiàng)則測(cè)試通過assertThat(iterableObject, hasItem (element));
更多更詳細(xì)的Hamcrest提供的斷言判斷參考:
http://hi.baidu.com/shenhuanyu09/item/2bcfcb981aa3188e581461b4
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////分割線
上面的Caculator待測(cè)試類里,現(xiàn)在我如果想給square方法多弄幾個(gè)測(cè)試用例,按照上面的方法,我應(yīng)該寫好幾個(gè)@Test方法來測(cè)試,或者每次測(cè)完再改一下輸入的值和期望得到的值,好麻煩。JUnit提供如下的測(cè)試:
- import java.util.Arrays;
- import java.util.Collection;
-
- import org.junit.Assert;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.junit.runners.Parameterized;
- import org.junit.runners.Parameterized.Parameters;
-
- @RunWith(Parameterized.class)
- public class CalculatorTest2{
-
- private Calculator cal = new Calculator();
- private int param;
- private int result;
-
-
-
- public CalculatorTest2(int param, int result) {
- this.param = param;
- this.result = result;
- }
-
- @Parameters
- public static Collection data(){
- return Arrays.asList(new Object[][]{
- {2, 4},
- {0, 0},
- {-3, 9},
- });
- }
-
- @Test
- public void squareTest() {
- int temp = cal.square(param);
- Assert.assertEquals(result, temp);
- }
- }
Eclipse里JUnit的運(yùn)行結(jié)果顯示為:
測(cè)試通過了,CalculatorTest2類里的parameter是每次的測(cè)試輸入,result就是測(cè)試的結(jié)果。所有的測(cè)試輸入和期望結(jié)果都在@Parameters標(biāo)注的data函數(shù)的返回的Collection集合里,2的期望得到的平方結(jié)果值是4,0期望得到0,-3期望得到9。
把測(cè)試代碼提交給JUnit框架后,框架如何來運(yùn)行代碼呢?答案就是——Runner。在JUnit中有很多個(gè) Runner,他們負(fù)責(zé)調(diào)用測(cè)試代碼,每一個(gè)Runner都有各自的特殊功能,要根據(jù)需要選擇不同的Runner來運(yùn)行測(cè)試代碼。JUnit中有一個(gè)默認(rèn)Runner,如果沒有指定,那么系統(tǒng)自動(dòng)使用默認(rèn) Runner來運(yùn)行你的代碼。這里參數(shù)化測(cè)試就沒有再用默認(rèn)的Runner了。
再看看打包測(cè)試測(cè)例子:
- import org.junit.runner.RunWith;
- import org.junit.runners.Suite;
-
-
-
-
-
-
-
-
-
-
- @RunWith(Suite.class)
- @Suite.SuiteClasses({ CalculatorTest.class, CalculatorTest2.class })
- public class AllCalculatorTests {
-
- }
這個(gè)測(cè)試類包含了上面的CalculatorTest.class和CalculatorTest2.class里面所有的測(cè)試函數(shù),它的目的就是進(jìn)行打包所有的測(cè)試。
參考:
http://blog.csdn.net/zhuangxiu/article/details/6256893
http://blog.csdn.net/songyinan1989/article/details/7445921
http://www.jb51.net/article/15797.htm
http://jingbo2759.blog.163.com/blog/static/983753152009711103710146/
|