【原創】Junit4詳解一:Junit總體介紹


    Junit是一個可編寫重復測試的簡單框架,是基於Xunit架構的單元測試框架的實例。Junit4最大的改進是大量使用注解(元數據),很多實際執行過程都在Junit的后台做完了,而且寫test case 的類不需要繼承TestCase,只需要在所要做test case的方法前加@Test 注解即可。

如:

1 import static org.junit.Assert.*;
2 2 public class TestCaculatorClass {
3 3     @Test
4 4     public void test() throws IOException, RuntimeException{
5 5         CaculatorClassForTest cal = new CaculatorClassForTest();
6 6         assertEquals(30, cal.sum(10, 20));
7 7     }
8 8 }
View @Test Code

直接點擊右鍵,run as... Junit Test即可運行此test case。

Assert類里面有很多assert方法,包括:assertEquals(), assertNotNull(),assertTtrue(),assertFalse(),assertThat()等,其中assertThat用的是match的形式。

因此,Junit提供很多中Match,其中CoreMatchers是其中一個比較完善的實現類。具體有上面方法可以查閱CoreMatchers類。

 1 import static org.hamcrest.CoreMatchers.allOf;
 2 import static org.hamcrest.CoreMatchers.anyOf;
 3 import static org.hamcrest.CoreMatchers.equalTo;
 4 import static org.hamcrest.CoreMatchers.not;
 5 import static org.hamcrest.CoreMatchers.sameInstance;
 6 import static org.hamcrest.CoreMatchers.startsWith;
 7 import static org.junit.Assert.assertThat;
 8 import static org.junit.matchers.JUnitMatchers.both;
 9 import static org.junit.matchers.JUnitMatchers.containsString;
10 import static org.junit.matchers.JUnitMatchers.everyItem;
11 import static org.junit.matchers.JUnitMatchers.hasItems;
12 
13 import java.util.Arrays;
14 
15 import org.hamcrest.core.CombinableMatcher;
16 import org.junit.Test;
17 
18 public class AssertTests {
19   @Test
20   public void testAssertArrayEquals() {
21     byte[] expected = "trial".getBytes();
22     byte[] actual = "trial".getBytes();
23     org.junit.Assert.assertArrayEquals("failure - byte arrays not same", expected, actual);
24   }
25 
26   @Test
27   public void testAssertEquals() {
28     org.junit.Assert.assertEquals("failure - strings not same", 5l, 5l);
29   }
30 
31   @Test
32   public void testAssertFalse() {
33     org.junit.Assert.assertFalse("failure - should be false", false);
34   }
35 
36   @Test
37   public void testAssertNotNull() {
38     org.junit.Assert.assertNotNull("should not be null", new Object());
39   }
40 
41   @Test
42   public void testAssertNotSame() {
43     org.junit.Assert.assertNotSame("should not be same Object", new Object(), new Object());
44   }
45 
46   @Test
47   public void testAssertNull() {
48     org.junit.Assert.assertNull("should be null", null);
49   }
50 
51   @Test
52   public void testAssertSame() {
53     Integer aNumber = Integer.valueOf(768);
54     org.junit.Assert.assertSame("should be same", aNumber, aNumber);
55   }
56 
57   // JUnit Matchers assertThat
58   @Test
59   public void testAssertThatBothContainsString() {
60     org.junit.Assert.assertThat("albumen", both(containsString("a")).and(containsString("b")));
61   }
62 
63   @Test
64   public void testAssertThathasItemsContainsString() {
65     org.junit.Assert.assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));
66   }
67 
68   @Test
69   public void testAssertThatEveryItemContainsString() {
70     org.junit.Assert.assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n")));
71   }
72 
73   // Core Hamcrest Matchers with assertThat
74   @Test
75   public void testAssertThatHamcrestCoreMatchers() {
76     assertThat("good", allOf(equalTo("good"), startsWith("good")));
77     assertThat("good", not(allOf(equalTo("bad"), equalTo("good"))));
78     assertThat("good", anyOf(equalTo("bad"), equalTo("good")));
79     assertThat(7, not(CombinableMatcher.<Integer> either(equalTo(3)).or(equalTo(4))));
80     assertThat(new Object(), not(sameInstance(new Object())));
81   }
82 
83   @Test
84   public void testAssertTrue() {
85     org.junit.Assert.assertTrue("failure - should be true", true);
86   }
87 }
View Assert Code

問題一,我可不可以把多個測試類放在一起執行?

回答: 可以。org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);利用這樣,把test case 的類放進去,然后放在main()方法里執行。

問題二,@RunWith這個注解有什么作用?

回答:Junit4的默認runner為BlockJunit4ClassRunner,但是Junit4包括第三方軟件還提供很多其他的runner,這樣如果,我們想讓我們的測試類用專門的runner來運行,這時候就可以用@RunWith(Suit.class

)標注測試類。其他特殊的runner有:

1. Suite: 字面理解是一個套裝,通俗地講,就是你可以把很多測試類放在一起,然后建一個類,標注為Suite.class,那么如果執行這個類,就會把所有的測試類一起執行。

 1 import org.junit.runner.RunWith;
 2 import org.junit.runners.Suite;
 3 
 4 @RunWith(Suite.class)
 5 @Suite.SuiteClasses({
 6   TestFeatureLogin.class,
 7   TestFeatureLogout.class,
 8   TestFeatureNavigate.class,
 9   TestFeatureUpdate.class
10 })
11 
12 public class FeatureTestSuite {
13   // the class remains empty,
14   // used only as a holder for the above annotations
15 }
View Suite Code

 

2. Parameterized:根據所設計的參數來執行測試。假設我們要測試某一個方法,它有兩個參數,每個參數需要設計不同值,那么我們最開始就是需要為每個參數設計一個測試方法,這樣就很麻煩,10種case就得10個方法,但是有了Parameterized runner,我們可以設計一個方法,多種參數來執行test case。

 1 package com.citi.risk.core.test.impl;
 2 
 3 public class CaculatorClassForTest {
 4     
 5     private int o1;
 6     private int o2;
 7     public int getO1() {
 8         return this.o1;
 9     }
10     public void setO1(int value) {
11         this.o1 = value;
12     }
13     public int getO2() {
14         return this.o2;
15     }
16     public void setO2(int value) {
17         this.o2 = value;
18     }
19     
20     
21     public CaculatorClassForTest() {}
22     public CaculatorClassForTest(int o1, int o2) {
23         this.o1 = o1;
24         this.o2 = o2;
25     }
26     
27     public int sum(int o1, int o2){
28         if(o1 > 200) {
29             throw new RuntimeException("o1 is too big");
30         }
31         if(o2 > 200) {
32             throw new RuntimeException("o2 is too big");
33         }
34         int sum;
35         sum = o1 + o2;
36         return sum;
37     }
38 }
View CaculatorClassForTest Code

 

 

 1 package com.citi.risk.core.test.impl;
 2 
 3 import static org.junit.Assert.*;
 4 
 5 import java.io.IOException;
 6 import java.util.List;
 7 
 8 import org.junit.Rule;
 9 import org.junit.Test;
10 import org.junit.rules.ExpectedException;
11 import org.junit.runner.RunWith;
12 import org.junit.runners.Parameterized;
13 import org.junit.runners.Parameterized.Parameter;
14 import org.junit.runners.Parameterized.Parameters;
15 
16 import com.google.common.collect.Lists;
17 
18 @RunWith(Parameterized.class)
19 public class TestCaculatorClass {
20     @Rule
21     public ExpectedException thrown = ExpectedException.none();
22     
23     @Parameters
24     public static List<Object[]> data() {
25         return Lists.asList(new Object[]{-1, 1, 0}, new Object[][]{{20, 20, 40},{30, 30, 60},{-5, -5, -10}});
26     }
27     @Parameter(value = 0)
28     public int o1;
29     @Parameter(value = 1)
30     public int o2;
31     @Parameter(value = 2)
32     public int expector;
33     
34     @Test
35     public void test() throws IOException, RuntimeException{
36         CaculatorClassForTest cal = new CaculatorClassForTest();
37         assertEquals(expector, cal.sum(o1, o2));
38     }
39     
40     @Test
41     public void testO1Exception(){
42         CaculatorClassForTest cal = new CaculatorClassForTest();
43         thrown.expect(RuntimeException.class);
44         thrown.expectMessage("o1 is too big");
45         cal.sum(300, 100);
46     }
47     @Test
48     public void testO2Exception(){
49         CaculatorClassForTest cal = new CaculatorClassForTest();
50         thrown.expect(RuntimeException.class);
51         thrown.expectMessage("o2 is too big");
52         cal.sum(100, 300);
53     }
54     
55 }
View TestCaculatorClass Code

 

 以上兩個類就是測試了Parameterized runner, 參數會自動匹配。它其實就是,看我們傳入幾種case, 也就是List.size(),然后,把類里面的方法,循環重復執行size()數目。

3. Categories:容易理解就是分類執行。假設我們有一種case: 我們寫好了兩個測試類,類A,類B,A有兩個方法a(), b(),這時候我們有一個類來執行這兩個類的test case,但是我們在類A里只想執行A.b(),但卻不執行A.a(),這個時候我們可以用Categories runner。

 1 public interface FastTests { /* category marker */ }
 2 public interface SlowTests { /* category marker */ }
 3 
 4 public class A {
 5   @Test
 6   public void a() {
 7     fail();
 8   }
 9 
10   @Category(SlowTests.class)
11   @Test
12   public void b() {
13   }
14 }
15 
16 @Category({SlowTests.class, FastTests.class})
17 public class B {
18   @Test
19   public void c() {
20 
21   }
22 }
23 
24 @RunWith(Categories.class)
25 @IncludeCategory(SlowTests.class)
26 @SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
27 public class SlowTestSuite {
28   // Will run A.b and B.c, but not A.a
29 }
30 
31 @RunWith(Categories.class)
32 @IncludeCategory(SlowTests.class)
33 @ExcludeCategory(FastTests.class)
34 @SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
35 public class SlowTestSuite {
36   // Will run A.b, but not A.a or B.c
37 }
View Categories Code
 

4. Enclosed:如果我們把tests放在了內部類,這時候執行外部類是無法執行里面的test cases,這種情況下,就應該在outer class 用Enclosed runner。

要測試的類 Address:

 1 package abstractions.domain;
 2 
 3     import java.io.Serializable;
 4 
 5     import com.google.common.collect.ComparisonChain;
 6 
 7     public class Address implements Serializable, Comparable<Address> {
 8 
 9         private static final long serialVersionUID = 1L;
10         private final String address1;
11         private final String city;
12         private final String state;
13         private final String zip;
14 
15         private Address(Builder builder) {
16             this.address1 = builder.address1;
17             this.city = builder.city;
18             this.state = builder.state;
19             this.zip = builder.zip;
20         }
21 
22         public String getAddress1() {
23             return address1;
24         }
25 
26         public String getCity() {
27             return city;
28         }
29 
30         public String getState() {
31             return state;
32         }
33 
34         public String getZip() {
35             return zip;
36         }
37 
38         @Override
39         public int compareTo(Address that) {
40             return ComparisonChain.start().compare(this.zip, that.zip).compare(this.state, that.state)
41                     .compare(this.city, that.city).compare(this.address1, that.address1).result();
42         }
43 
44         @Override
45         public boolean equals(Object obj) {
46             if (obj == null) { return false; }
47             if (getClass() != obj.getClass()) { return false; }
48             final Address that = (Address) obj;
49 
50             return com.google.common.base.Objects.equal(this.address1, that.address1)
51                     && com.google.common.base.Objects.equal(this.city, that.city)
52                     && com.google.common.base.Objects.equal(this.state, that.state)
53                     && com.google.common.base.Objects.equal(this.zip, that.zip);
54         }
55 
56         @Override
57         public int hashCode() {
58             return com.google.common.base.Objects.hashCode(getAddress1(), getCity(), getCity(), getState(), getZip());
59         }
60 
61         @Override
62         public String toString() {
63             return com.google.common.base.Objects.toStringHelper(this).addValue(getAddress1()).addValue(getCity()).addValue(getState()).addValue(getZip()).toString();
64         }
65 
66         public static class Builder {
67 
68             private String address1;
69             private String city;
70             private String state;
71             private String zip;
72 
73             public Builder address1(String address1) {
74                 this.address1 = address1;
75                 return this;
76             }
77 
78             public Address build() {
79                 return new Address(this);
80             }
81 
82             public Builder city(String city) {
83                 this.city = city;
84                 return this;
85             }
86 
87             public Builder state(String state) {
88                 this.state = state;
89                 return this;
90             }
91 
92             public Builder zip(String zip) {
93                 this.zip = zip;
94                 return this;
95             }
96         }
97     }
View Address Code

test case:

  1 package abstractions.domain;
  2 
  3     import static org.hamcrest.Matchers.is;
  4     import static org.junit.Assert.assertThat;
  5 
  6     import java.io.Serializable;
  7 
  8     import org.junit.Before;
  9     import org.junit.Test;
 10     import org.junit.experimental.runners.Enclosed;
 11     import org.junit.runner.RunWith;
 12 
 13     import testhelpers.ComparabilityTestCase;
 14     import testhelpers.EqualsHashCodeTestCase;
 15     import testhelpers.SerializabilityTestCase;
 16 
 17     /**
 18      * The Class AddressTest.
 19      */
 20     @RunWith(Enclosed.class)
 21     public class AddressTest {
 22 
 23         /**
 24          * The Class AddressComparabilityTest.
 25          */
 26         public static class AddressComparabilityTest extends ComparabilityTestCase<Address> {
 27 
 28             @Override
 29             protected Address createEqualInstance() throws Exception {
 30                 return new Address.Builder().address1("2802 South Havana Street").city("Aurora").state("CO").zip("80014").build();
 31             }
 32 
 33             @Override
 34             protected Address createGreaterInstance() throws Exception {
 35                 return new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 36             }
 37 
 38             @Override
 39             protected Address createLessInstance() throws Exception {
 40                 return new Address.Builder().address1("14 Broad St").city("Nashua").state("NH").zip("03064").build();
 41             }
 42         }
 43 
 44         /**
 45          * The Class AddressEqualsHashCodeTest.
 46          */
 47         public static class AddressEqualsHashCodeTest extends EqualsHashCodeTestCase {
 48 
 49             @Override
 50             protected Address createInstance() throws Exception {
 51                 return new Address.Builder().address1("2802 South Havana Street").city("Aurora").state("CO").zip("80014").build();
 52             }
 53 
 54             @Override
 55             protected Address createNotEqualInstance() throws Exception {
 56                 return new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 57             }
 58         }
 59 
 60         /**
 61          * The Class AddressSerializabilityTest.
 62          */
 63         public static class AddressSerializabilityTest extends SerializabilityTestCase {
 64 
 65             @Override
 66             protected Serializable createInstance() throws Exception {
 67                 return new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 68             }
 69         }
 70 
 71         public static class AddressMiscTest {
 72 
 73             private Address address;
 74 
 75             /**
 76              * Setup.
 77              *
 78              * @throws Exception the exception
 79              */
 80             @Before
 81             public void setUp() throws Exception {
 82                 address = new Address.Builder().address1("9839 Carlisle Boulevard NE").city("Albuquerque").state("NM").zip("87110").build();
 83             }
 84 
 85             /**
 86              * Test builder.
 87              */
 88             @Test
 89             public void testBuilder() {
 90                 assertThat(address.getAddress1(), is("9839 Carlisle Boulevard NE"));
 91                 assertThat(address.getCity(), is("Albuquerque"));
 92                 assertThat(address.getState(), is("NM"));
 93                 assertThat(address.getZip(), is("87110"));
 94             }
 95 
 96             @Test
 97             public void testToString() {
 98                 assertThat(address.toString(), is("Address{9839 Carlisle Boulevard NE, Albuquerque, NM, 87110}"));
 99             }
100         }
101     }
View AddressTest Code

問題三:不想執行某個類的test case 有什么方法?

回答: 用@Ignore, 如果要讓某個類都不執行,@Ignore放在類里,如果不想執行某一個方法,只需要放在方法上。

1 @Ignore
2 public class TestClass{
3 
4     @Ignore("Test is ignored as a demonstration")
5     @Test
6     public void testSane() {
7         assertThat(1, is(1));
8     }
9 }

問題四:某個test case執行時間太長,有什么辦法終止?

回答: Junit4提供了timeout屬性。

1 @Test(timeout=1000)
2 public void testWithTimeout() {
3   ...
4 }

 

Junit4還有更重要的@Rule 和 執行順序。且聽下回分解。

 

草原戰狼淘寶小店:http://xarxf.taobao.com/ 淘寶搜小矮人鞋坊,主營精致美麗時尚女鞋,為您的白雪公主挑一雙哦。謝謝各位博友的支持。

===============================================================================

==========================    以上分析僅代表個人觀點,歡迎指正與交流   ==========================

==========================    草原戰狼博客,轉載請注明出處,萬分感謝   ==========================

===============================================================================

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM