JUnit是一个开放源码的、Java语言的单元测试框架,用于测试指望结果的断言(Assertion);由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,由于程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。多数Java的开发环境都已经集成了JUnit做为单元测试的工具,如Eclipse。程序员
测试通常分为:单元测试、集成测试(主要看一块代码加进去后,系统会不会有问题)、验收测试和压力测试。单元测试的最基本的一个功能是能进行自动化测试。单元测试都是经过断言的方式来肯定结果是否正确,便是用Assert。编程
junit是在极限编程和重构(refactor)中被极力推荐使用的工具,由于在实现自动单元测试的状况下能够大大的提升开发的效率。框架
极限编程:要求在编写代码以前先写测试,这样能够强制你在写代码以前好好的思考代码(方法)的功能和逻辑,不然编写的代码很不稳定,那么你须要同时维护测试代码和实际代码,这个工做量就会大大增长。所以在极限编程中,基本过程是这样的:构思-> 编写测试代码-> 编写代码-> 测试,并且编写测试和编写代码都是增量式的,写一点测一点,在编写之后的代码中若是发现问题能够较快的追踪到问题的缘由,减少回归错误的纠错难度。less
重构:其好处和极限编程中是相似的,由于重构也是要求改一点测一点,减小回归错误形成的时间消耗。maven
在junit3中,若是某个类是测试类,必须将其继承类TestCase,若是某个方法是测试方法,必须让这个方法以testXX开头,若是但愿指定某个测试方法运行以前运行某个初始化方法,这个方法的名称必须是setUp,若是但愿在某个测试方法运行以后运行某个释放资源的方法,这个方法的名称必须是tearDown。
在junit4中,一个POJO类就是一个测试类,测试方法经过@Test来标识,初始化方法经过@Before来标识,释放资源的方法经过@After来标识,可是为了让junit4的测试类在junit3中也可使用,习惯于把初始化方法命名为setUp,释放资源的方法命名为tearDown。Test中的测试方法通常以Test来开始。其中标识为Before注解的方法,每次运行测试类,都会执行标识为@After与@Before的方法。ide
因为JUnit4引用了不少Annotation注解之后,用JUnit进行单元测试比较方便,主要关键点在于:注解,断言的使用;函数
如下为测试的示例:工具
待测试类单元测试
package com.test; /** * 计算类 * @author helen. * @Time 2016年5月13日 * @Version 1.0 */ public class Calculator { public int add(int a, int b) { System.out.println("=======正在执行加法"); return a + b; } public int minus(int a, int b) { System.out.println("=======正在执行减法"); return a - b; } public int square(int n) { System.out.println("=======正在执行平方计算"); return n * n; } //Bug : 死循环 public void squareRoot(int n) { System.out.println("=======正在执行死循环的方法"); for(; ;) ; } public int multiply(int a, int b) { System.out.println("=======正在执行乘法"); return a * b; } public int divide(int a, int b) throws Exception { System.out.println("=======正在执行除法"); if (0 == b) { throw new Exception("除数不能为零"); } return a / b; } }
单元测试类测试
package com.test; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import static org.hamcrest.Matchers.*; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; /** * 计算类单元测试 * @author helen. * @Time 2016年5月13日 * @Version 1.0 */ public class CalculatorTest { private Calculator cal = new Calculator(); /** * 注意 * 必须为静态方法static...由于方法将在类被装载的时候就被调用(那时候还没建立实例) * * @author helen, 2016年5月13日. */ @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("one test begin"); } @After public void tearDown() throws Exception { System.out.println("one test end"); } @Test @Ignore public void testAdd() { int result = cal.add(1, 2); Assert.assertEquals(30, result); } @Test public void testMinus() { int result = cal.minus(5, 2); Assert.assertThat(result, greaterThan(2)); } @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 { cal.divide(4, 0); } }
运行测试用:在Eclipse里Run As -> JUnit Test,运行测试类,Eclipse的JUnit的View显示以及控制台的输出以下截图:
能够看到,CalculatorTest类中总共有5个测试用例,ignore了一个,3个测试用例经过,testSquareRoot测试不经过(由于超时),因此整个的测试结果飘红了。
@Test:
代表该方法是一个测试方法
@BeforeClass 和 @AfterClass:
测试用例初始化时执行 @BeforeClass方法,当全部测试执行完毕以后,执行@AfterClass进行收尾工做。标注、@BeforeClass 和 @AfterClass的方法必须是static的,由于方法将在类被装载的时候就被调用,那时候还没建立测试对象实例。
@Before:
使用了该元数据的方法在每一个测试方法执行以前都要执行一次。
@After:
使用了该元数据的方法在每一个测试方法执行以后要执行一次。
@Test(expected=*.class) :
经过@Test元数据中的expected属性验证是否抛出指望的异常,expected属性的值是一个异常的类型,若是抛出了指望的异常,则测试经过,不然不经过。
@Test(timeout=xxx):
该元数据传入了一个时间(毫秒)给测试方法,若是测试方法在制定的时间以内没有运行完,则测试也失败。
@Ignore:
该元数据标记的测试方法在测试中会被忽略。同时能够为该标签传递一个String的参数,来代表为何会忽略这个测试方法。好比:@lgnore("该方法尚未实现"),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。
在test方法内除了使用Assert的assertEquals()方法外,还能使用assertFalse()、assertTrue()、assertNull()、assertNotNull()、assertSame()、assertNotSame()等断言函数。并且若是使用的是Junit4,结合Hamcrest,使用
assertThat([value], [matcher statement])方法能够实现更灵活的断言判断(前提是引入hamcrest的jar包)。
若是不须要用到assertThat,则只须要用Eclipse自带的junit4工具便可;若是须要用到assertThat,则最好不要Eclipse自带的工具,从新经过maven方式引入jar。
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-all</artifactId> <version>1.3</version> </dependency>
1.JUnit4.4引入了Hamcrest框架,Hamcest提供了一套匹配符Matcher,这些匹配符更接近天然语言,可读性高,更加灵活;
2.使用全新的断言语法:assertThat,结合Hamcest提供的匹配符,只用这一个方法,就能够实现全部的测试;
3.assertThat语法以下:
assertThat(T actual, Matcher<T> matcher);
assertThat(String reason, T actual, Matcher<T> matcher);
其中actual为须要测试的变量,matcher为使用Hamcrest的匹配符来表达变量actual指望值的声明;
4.注意事项:
a.必须导入JUnit4.4以后的版本才能使用assertThat方法;
b.不须要继承TestCase类,可是须要测试方法前必须加“@Test”。
// is匹配符代表若是前面待测的object等于后面给出的object,则测试经过
assertThat( testedObj, is( object) );
// containsString匹配符代表若是测试的字符串包含指定的子字符串则测试经过
assertThat( testedString, containsString( "developerWorks" ) );
// greaterThan匹配符代表若是所测试的数值testedNumber大于16.0则测试经过
assertThat( testedNumber, greaterThan(16.0) );
// closeTo匹配符代表若是所测试的浮点型数testedDouble在20.0±0.5范围以内则测试经过
assertThat( testedDouble, closeTo( 20.0, 0.5 ) );
//hasItem匹配符代表被测的迭代对象含有元素element项则测试经过assertThat(iterableObject, hasItem (element));
一、assertThat( testedNumber, allOf( greaterThan(8), lessThan(16) ) );
注释: allOf匹配符代表若是接下来的全部条件必须都成立测试才经过,至关于“与”(&&)
二、assertThat( testedNumber, anyOf( greaterThan(16), lessThan(8) ) );
注释:anyOf匹配符代表若是接下来的全部条件只要有一个成立则测试经过,至关于“或”(||)
三、assertThat( testedNumber, anything() );
注释:anything匹配符代表不管什么条件,永远为true
四、assertThat( testedString, is( "developerWorks" ) );
注释: is匹配符代表若是前面待测的object等于后面给出的object,则测试经过
五、assertThat( testedString, not( "developerWorks" ) );
注释:not匹配符和is匹配符正好相反,代表若是前面待测的object不等于后面给出的object,则测试经过
一、assertThat( testedString, containsString( "developerWorks" ) );
注释:containsString匹配符代表若是测试的字符串testedString包含子字符串"developerWorks"则测试经过
二、assertThat( testedString, endsWith( "developerWorks" ) );
注释:endsWith匹配符代表若是测试的字符串testedString以子字符串"developerWorks"结尾则测试经过
三、assertThat( testedString, startsWith( "developerWorks" ) );
注释:startsWith匹配符代表若是测试的字符串testedString以子字符串"developerWorks"开始则测试经过
四、assertThat( testedValue, equalTo( expectedValue ) );
注释: equalTo匹配符代表若是测试的testedValue等于expectedValue则测试经过,equalTo能够测试数值之间,字
符串之间和对象之间是否相等,至关于Object的equals方法
五、assertThat( testedString, equalToIgnoringCase( "developerWorks" ) );
注释:equalToIgnoringCase匹配符代表若是测试的字符串testedString在忽略大小写的状况下等于"developerWorks"则测试经过
六、assertThat( testedString, equalToIgnoringWhiteSpace( "developerWorks" ) );
注释:equalToIgnoringWhiteSpace匹配符代表若是测试的字符串testedString在忽略头尾的任意个空格的状况下等
于"developerWorks"则测试经过,注意:字符串中的空格不能被忽略
一、assertThat( testedDouble, closeTo( 20.0, 0.5 ) );
注释:closeTo匹配符代表若是所测试的浮点型数testedDouble在20.0±0.5范围以内则测试经过
二、assertThat( testedNumber, greaterThan(16.0) );
注释:greaterThan匹配符代表若是所测试的数值testedNumber大于16.0则测试经过
三、assertThat( testedNumber, lessThan (16.0) );
注释:lessThan匹配符代表若是所测试的数值testedNumber小于16.0则测试经过
四、assertThat( testedNumber, greaterThanOrEqualTo (16.0) );
注释: greaterThanOrEqualTo匹配符代表若是所测试的数值testedNumber大于等于16.0则测试经过
五、assertThat( testedNumber, lessThanOrEqualTo (16.0) );
注释:lessThanOrEqualTo匹配符代表若是所测试的数值testedNumber小于等于16.0则测试经过
一、assertThat( mapObject, hasEntry( "key", "value" ) ); 注释:hasEntry匹配符代表若是测试的Map对象mapObject含有一个键值为"key"对应元素值为"value"的Entry项则测试经过 二、assertThat( iterableObject, hasItem ( "element" ) ); 注释:hasItem匹配符代表若是测试的迭代对象iterableObject含有元素“element”项则测试经过 三、assertThat( mapObject, hasKey ( "key" ) ); 注释: hasKey匹配符代表若是测试的Map对象mapObject含有键值“key”则测试经过 四、assertThat( mapObject, hasValue ( "key" ) ); 注释:hasValue匹配符代表若是测试的Map对象mapObject含有元素值“value”则测试经过