JUnit单元测试
(一)、JUnit介绍:
测试对于保证软件开发质量有着非常重要的作用,单元测试更是必不可少,JUnit是一个非常强大的单元测试包,可以对一个/多个类的单个/多个方法测试,还可以将不同的TestCase组合成TestSuit,使测试任务自动化。
Eclipse同样集成了JUnit,可以非常方便地编写TestCase。
(二)、为什么使用JUnit?
不知道大家以前在对自己的项目是怎么进行测试的。
反正我的测试方法是在一个类中都写一个main函数,然后根据类中方法的参数传入相应的值。
这样做很麻烦,最大的缺点就是如果项目功能模块很多的话,那就完了。
:)
(三)、eclipse中建立一个完整的单元测试
Junit3
package cn.itcast.example;
public class Demo1 {
private int n;
public Demo1(int n) {
this.n = n;
}
// 返回绝对值:
public int foo() {
return n>0 ? n : (-n);
}
}
package cn.itcast.example;
public class Demo2 {
public int add(int x, int y) {
return x + y;
}
public static int divide(int x, int y) {
return x / y;
}
public static int multiple(int x, int y) {
return x * y;
}
}
测试用例
public class Demo1Test extends TestCase { private Demo1 s1, s2;
protected void setUp() throws Exception { s1 = new Demo1(10);
s2 = new Demo1(-7);
}
protected void tearDown() throws Exception { }
public void testFoo() {
assertTrue(s1.foo()==10);
assertTrue(s2.foo()==7);
}
}
public class Demo2Test extends TestCase {
Demo2 demo;
protected void setUp() throws Exception { super.setUp();
demo = new Demo2();
System.out.println("go.........");
}
protected void tearDown() throws Exception { super.tearDown();
}
public void testAdd() {
assertEquals(7, demo.add(3, 4));
}
public void testDivide() {
assertEquals(4, demo.divide(8, 2));
}
public void testMultiple() {
assertEquals(20, demo.multiple(4, 5));
}
}
public class AllTests {
public static Test suite() {
TestSuite suite = new TestSuite("Test for cn.itcast.junit3");
//$JUnit-BEGIN$
suite.addTestSuite(Demo1Test.class);
suite.addTestSuite(Demo2Test.class);
//$JUnit-END$
return suite;
}
}
Junit4
setUp()方法在测试方法前调用,一般用来做测试准备工作。
tearDown()方法在测试方法后调用,一般作测试的清理工作。
setUpBeforeClass()方法在整个类初始化之后调用,一般用来做测试准备工作。
tearDownAfterClass()方法在整个类结束之前调用,一般作测试的清理工作。
constructor()为是否包含构造方法。
@BeforeClass标签注释的方法用于在整个类测试过程的初始化后调用一次,@AfterClass标签注释的方法则是整个测试类结束之前调用一次。
这2个标签的搭配可以避免使用@Before、@After标签组合在每个测试方法前后都调用的弊端,减少系统开销,提高系统测试速度。
(不过对环境独立性要求较高的测试还是应当使用@Before、@After来完成)
@Test标签用来标注待测试的方法,按照类中声明的顺序执行。
Junit4为测试方法增加了判断异常的方式,避免了以前还要通过try/catch块捕捉异常再抛出的复杂方式,简单的这样声明“@Test(expected=ArithmeticException.class)”Junit4就会检查此方法是否抛出ArithmeticException异常,如果抛出则测试通过,没抛出则测试不通过(@Test标签还有一些其他参数,例如超时测试@Test(timeout=1)这样,但是由于并不能准确反应实际时间,所以应用较少,经过我测试误差太大绝对不适合拿来做超时测试的)
@Ignore标签会告诉Junit4忽略它所标注的方法,例如数据库不可用时可以用此标注标注一些测试数据库连接的方法来避免测试失败。
通过@RunWith和@SuiteClasses标签来注释一个空的包含无参数构造函数的类来作为套件类,将需要组成套件运行的类加到@SuiteClasses的属性中即可。
JUnit4不再受命名的限制
JUnit被用来测试代码,并且它是由能够测试不同条件的
断言方法组成:
assertEquals(a, b) 测试a是否等于b(a和b是原始类型数值(primitive value)或者必须为实现比较而具有equal方法)
assertFalse(a) 测试a是否为false(假),a是一个Boolean数值。
assertNotNull(a) 测试a是否非空,a是一个对象或者null。
assertNotSame(a, b) 测试a和b是否没有都引用同一个对象。
参数化测试
你可能遇到过这样的函数,它的参数有许多特殊值,或者说他的参数分为很多个区域。
比如,一个对考试分数进行评价的函数,返回值分别为“优秀,良好,一般,及格,不及格”,因此你在编写测试的时候,至少要写5个测试,把这5中情况都包含了,这确实是一件很麻烦的事情。
测试运行机
JUnit4中,广泛地使用测试运行机。
如果没有指定@RunWith,那么你的类仍然会使用一个默认运行机(org.junit.internal.runners.TestClassRunner)执行。
注意,最初的Calculator类中并没有显式地声明一个测试运行机;因此,它使用的是默认运行机。
一个包含一个带有@Test的方法的类都隐含地拥有一个@RunWith。
事实上,你可以把下列代码添加到Calculator类上,而且其输出结果会完全一样。
在@Parameterized和@Suite的情况下,我需要一个特定的运行机来执行我的测试用例。
这就是为什么我显式地注解了它们。
案例
参考源文件junittest。