Junit4详解一:Junit总体介绍

来源:互联网 发布:xp关闭445端口 编辑:程序博客网 时间:2024/05/29 19:46

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     @Test4 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 }
复制代码

直接点击右键,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   @Test20   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   @Test27   public void testAssertEquals() {28     org.junit.Assert.assertEquals("failure - strings not same", 5l, 5l);29   }30 31   @Test32   public void testAssertFalse() {33     org.junit.Assert.assertFalse("failure - should be false", false);34   }35 36   @Test37   public void testAssertNotNull() {38     org.junit.Assert.assertNotNull("should not be null", new Object());39   }40 41   @Test42   public void testAssertNotSame() {43     org.junit.Assert.assertNotSame("should not be same Object", new Object(), new Object());44   }45 46   @Test47   public void testAssertNull() {48     org.junit.Assert.assertNull("should be null", null);49   }50 51   @Test52   public void testAssertSame() {53     Integer aNumber = Integer.valueOf(768);54     org.junit.Assert.assertSame("should be same", aNumber, aNumber);55   }56 57   // JUnit Matchers assertThat58   @Test59   public void testAssertThatBothContainsString() {60     org.junit.Assert.assertThat("albumen", both(containsString("a")).and(containsString("b")));61   }62 63   @Test64   public void testAssertThathasItemsContainsString() {65     org.junit.Assert.assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three"));66   }67 68   @Test69   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 assertThat74   @Test75   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   @Test84   public void testAssertTrue() {85     org.junit.Assert.assertTrue("failure - should be true", true);86   }87 }
复制代码

问题一,我可不可以把多个测试类放在一起执行?

回答: 可以。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.class10 })11 12 public class FeatureTestSuite {13   // the class remains empty,14   // used only as a holder for the above annotations15 }
复制代码

 

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 }
复制代码

 

 

复制代码
 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     @Rule21     public ExpectedException thrown = ExpectedException.none();22     23     @Parameters24     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     @Test35     public void test() throws IOException, RuntimeException{36         CaculatorClassForTest cal = new CaculatorClassForTest();37         assertEquals(expector, cal.sum(o1, o2));38     }39     40     @Test41     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     @Test48     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 }
复制代码

 

 以上两个类就是测试了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   @Test12   public void b() {13   }14 }15 16 @Category({SlowTests.class, FastTests.class})17 public class B {18   @Test19   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 Suite27 public class SlowTestSuite {28   // Will run A.b and B.c, but not A.a29 }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 Suite35 public class SlowTestSuite {36   // Will run A.b, but not A.a or B.c37 }
复制代码
 

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         @Override39         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         @Override45         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         @Override57         public int hashCode() {58             return com.google.common.base.Objects.hashCode(getAddress1(), getCity(), getCity(), getState(), getZip());59         }60 61         @Override62         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     }
复制代码

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     }
复制代码

问题三:不想执行某个类的test case 有什么方法?

回答: 用@Ignore, 如果要让某个类都不执行,@Ignore放在类里,如果不想执行某一个方法,只需要放在方法上。

复制代码
1 @Ignore2 public class TestClass{3 4     @Ignore("Test is ignored as a demonstration")5     @Test6     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 和 执行顺序。且听下回分解。

 


0 0