JUnit4学习笔记2-Eclipse中使用JUint4进行单元测试
1.1 创建JUnit测试
你可以手动引入JUnit4相关jar包,或者使用eclipse向导自动引入
在工程上,右键--属性--Java Build Path--Add Library...
选择JUnit
选择版本--Finish
添加完后可以看到工程中多了个JUnit4的包
测试类生成:
你可以手动写测试类,或者通过eclipse向导自动创建测试类。
在eclipse的Package Explorer视图中右键点击要测试的类,选择New--JUnit Test Case。(此处可以选择测试类生成的包路径)
如图,此处可以修改包路径和类名。之后点击Next。
setup(@Before),tearDown(@After)方法是执行每个测试方法前后调用的。一般用来做测试准备工作和测试清理工作。 setUpBeforeClass(@BeforeClass),tearDownAfterClass(@AfterClass)方法是整个类初始化之后和结束之前调用的。也是用来做测试准备和测试清理工作。 |
此处勾选需要测试的类,点击Finish。
刚创建出来的测试类,只有方法名和相应的注解,并没有相应的测试代码。如:
@Test public void testAdd() { fail("Not yet implemented"); }
需要对方法的内容稍作修改。如:
@Test public void testAdd() { calculator.add(2); calculator.add(3); assertEquals("test 0 + 2 + 3......", 6, calculator.getResult()); }
1.2 运行JUnit测试
运行JUnit测试,右键测试类--Run As--JUnit Test。(如只想测试一个方法,则选中一个方法执行上述操作)
快捷键: Alt+Shift+X, T
测试结果显示
FailureFailure指的是由于预期的结果与实际运行的测试的结果不同而导致的,例如当使用assertEquals()或其它assertXXX()方法断言失败时,就会报出Failure,如果发现Faulure,你就要去检查你的测试方法或者是被测试方法中编写的逻辑是否有误。 ErrorError指的是编写程序时没有考虑到的问题。在执行测试的断言之前,程序就因为某种类型的意外而停止,比喻说我们在操作数组的时候,因为存取超出索引会引发ArrayIndexOutOfBoundsException,这个时候程序就会报出Error,程序将无法运行下去,提前结束,这个时候你要检查被测试方法中是不是有欠缺考虑到地方。 |
1.3 JUnit静态包含(import static…)
import static org.junit.Assert.*; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test;
org.junit.Assert类中的assertTrue,assertFalse 和 assertEquals等方法都是静态方法,通常用法是org.junit.Assert. assertEquals()…,使用静态包含可以直接写方法名调用。
2.1 打包测试
通常在一个项目中,只写一个测试类是不太可能的。我们会写很多测试类。一个一个执行是件麻烦事。JUnit支持打包测试,将所有需要运行的测试类集中起来一次运行完,方便了测试工作。
同样的,也可以手动写一个打包测试类,也可以利用eclipse自带的向导完成。
在待测试的包上,右键--New--Other…--JUnit--JUnit Test Suite--勾选待运行的测试类--Finish。如下图:
生成代码:
package test.com.llhua.junittest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ CalculatorTest.class, PackageTest.class, SquareTest.class }) public class AllTests { }
生成的类有两个新的注解,RunWith和SuiteClasses。
此类不需要添加内容,必须使用public修饰,而且有不带参数的构造函数。
RunWith注解:由此引出Runner(运行器)的概念。在JUnit中有多个Runner负责调用测试代码。如果不指定,则使用默认的Runner,即org.junit.runners.BlockJUnit4ClassRunner。我们也可以继承此类实现自己的Runner。 参考:1.http://unmi.cc/extend-junit-4-customized-runner/ 2. http://www.blogways.net/blog/2013/04/15/junit-usage-4.html |
SuiteClasses注解:将需要测试的测试类组成数组作为SuiteClasses的参数。 |
2.2 异常测试
Java中的异常处理也是重点,在某些条件下需要方法抛出异常,如没有抛出异常,应该也算Bug。例如做除法运算时,传入的除数为0,那必须抛出除数为0异常。此时,需要用到异常测试,使用注解@Test(expected = XXXException.class)。
@Test(expected = ArithmeticException.class) public void divideByZero(){ calculator.divide(0); }
2.3 限时测试
对于逻辑复杂,循环嵌套比较深的程序,很可能出现死循环,因此需要采取一些预防措施。给这些测试函数设定一个执行时间,超过了这个时间,就会被系统强行终止。JUnit支持的限时测试是个不错的解决方案。使用注解:@Test(timeout = XXX(单位毫秒))。
@Test(timeout = 1000)//限时测试,单位毫秒 public void testSquareRoot(){ calculator.squareRoot(4); assertEquals("死循环,限时测试。。。", 2, calculator.getResult()); }
2.4 参数化测试
为了保证单元测试的严谨性,我们需要模拟多个不同的参数,调用待测函数。不同的参数返回不同的值。此时,我们需要编写多个大同小异的测试方法,不断地复制粘贴,很麻烦。针对这种情况,JUnit4提供了Parameterized Runner,使用RunWith注解调用,如图。Parameters注解标注的方法返回待测的参数和测试后的值,两个值前后可以颠倒,顺序和下面构造函数的参数的顺序相同即可。
package test.com.llhua.junittest; import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collection; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.llhua.junittest.Calculator; @RunWith(Parameterized.class) public class SquareTest { private static Calculator calculator = new Calculator(); int param; int result; @Parameters public static Collection<Object[]> data(){ return Arrays.asList(new Object[][]{ {2, 4}, {0, 0}, {-3, 9} }); } public SquareTest(int param, int result){ this.param = param; this.result = result; } @Test public void square(){ calculator.square(param); assertEquals(result, calculator.getResult()); } }
以上的测试类等同于下面的方法。
@Test public void testSquare2(){ calculator.square(2); assertEquals(1, calculator.getResult()); } @Test public void testSquare0(){ calculator.square(0); assertEquals(1, calculator.getResult()); } @Test public void testSquare_3(){ calculator.square(-3); assertEquals(1, calculator.getResult()); }
2.5 Rule
JUnit4中的Rule是一组实现了TestRule接口的共享类。提供了验证、监视TestCase和外部资源管理等能力。JUnit提供了以下几个Rule实现,必要时也可以自己实现Rule。
类名 |
描述 |
TemporaryFolder |
可以运行在测试过程中创建临时文件或者临时目录,当测试结束后,框架会自动删除。 |
ExternalResource |
可以设置测试前后需要做的事情(比如:文件、socket、服务、数据库的连接与关闭) |
ErrorCollector |
ErrorCollector这个Rule,在出现一个错误后,还可以让测试继续进行下去 |
Verifier |
如果,你想在每个测试之后,甚至是在@After之后,想检查些什么,就可以使用Verifier这个Rule |
TestWatcher |
对测试的每个步骤进行监控 |
TestName |
TestName可以获取当前测试方法的名字 |
Timeout |
可以设置某个测试类,所有测试方法的超时时间 |
ExpectedException |
同@Test中的expected字段 |
Rule注解用法:
package test.com.llhua.junittest; import static org.junit.Assert.*; import java.io.File; import java.io.IOException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; public class RuleTester { @Rule public TemporaryFolder folder = new TemporaryFolder(); @Test public void testUsingTempFolder() throws IOException{ // File createFolder = folder.newFolder("newfolder"); File createFile = folder.newFile("myfilefile.txt"); assertTrue(createFile.exists()); } }
Rule参考资料:1.http://www.blogways.net/blog/2013/04/15/junit-usage-5.html
2.http://www.blogjava.net/DLevin/archive/2012/05/12/377955.html
3.1 表格1.Junit4注解
注解 |
描述 |
@Test public void method() |
表示注解的方法是一个测试方法 |
@Test (expected = Exception.class) |
表示该测试方法预期会抛出Exception.class 的异常 |
@Test(timeout=100) |
表示该测试方法预期执行不会超过 100 毫秒,超过了出错 |
@Before public void method() |
表示该方法在每一个测试方法之前运行,通常用于初始化 |
@After public void method() |
表示该方法在每一个测试方法之后运行,可以使用该方法进行释放资源,回收内存之类的操作 |
@BeforeClass public static voidmethod() |
表示该方法只执行一次,并且在所有方法之前执行。一般可以使用该方法进行数据库连接操作,注意该注解使用在静态方法上 |
@AfterClass public static voidmethod() |
表示该方法只执行一次,并且在所有方法之后执行。一般可以使用该方法进行数据库连接关闭操作,注意该注解使用在静态方法上 |
@Ignore |
表示该方法忽略。一般在低层代码有所改动,但是未实现,可以暂时忽略掉。也可以忽略掉执行时间过长的测试。 |
3.2 表格 2. 测试方法
语句 |
描述 |
fail(String) |
表示让测试方法失败。一般用于某些代码执行不到,或者在fail代码之前就失败了。参数是可选的。抛出junit.framework.AssertionFailedError异常 |
assertTrue([message], boolean condition) |
表示给出的条件断言为真 |
assertFalse([message], boolean condition) |
表示给出的条件断言为假 |
assertEquals([String message], expected, actual) |
表示测试两个值的内容相等。注意数组是检查引用相同而不是数组的内容 |
assertEquals([String message], expected, actual, tolerance) |
测试float或double值匹配。容差是小数点后的位数,必须是相同的assertEquals( 1.1f, 1.1111d, 1); |
assertNull([message], object) |
表示检查的对象为空 |
assertNotNull([message],object) |
表示检查的对象为非空 |
assertSame([String], expected, actual) |
表示两个变量指向同一个引用 |
assertNotSame([String], expected, actual) |
表示两个变量指向非同一个引用 |
3.3 参考资料
doc:http://junit.org/javadoc/latest/
概念:http://zh.wikipedia.org/wiki/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95
http://developer.51cto.com/art/201103/252490.htm
Eclipse中使用JUnit4:
http://blog.csdn.net/andycpp/article/details/1327147
http://www.ibm.com/developerworks/cn/java/j-lo-junit4/
http://www.vogella.com/tutorials/JUnit/article.html#eclipse_creatingjunittest
http://www.cnblogs.com/shine_cn/archive/2011/05/28/2060927.html
assertThat:JUnit4.4后出现的强大的方法http://www.taobaotest.com/blogs/show/723http://www.taobaotest.com/blogs/show/723