使用Junit单位测试,能够一定程度上减小项目bug的产生。很多时候,我们都是在main函数里面单独去测试一个方法,这样的测试非常不方便。使用Junit可以是测试单位和项目代码分离,一次性测试多个方法,并对结果进行评估。
在eclipse中进行单位测试,过程如下 右键项目-》build path》add Library 》添加Junit类库。然后右键项目,添加一个source folder,命名为test。
下面的代码来至于http://www.imooc.com/learn/356。
首先新建一个类。
package com.dong.util; public class Calculate { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int mutiply(int a, int b) { return a * b; } public int divide(int a, int b) { return a / b; } }
然后,我们可以右键该类生成一个Junit test case。这样便会生成一个测试类。
package com.dong.util; import static org.junit.Assert.assertEquals; import org.junit.Test; public class CalculateTest { // @Test // public void test() { // fail("Not yet implemented"); // } @Test public void testAdd() { assertEquals(6, new Calculate().add(3, 3)); } @Test public void testSubtract() { assertEquals(0, new Calculate().subtract(3, 3)); } @Test public void testMutiply() { assertEquals(9, new Calculate().mutiply(3, 3)); } @Test public void testDivide() { assertEquals(1, new Calculate().divide(3, 3)); } }
测试类被和被测试类其实处于同一个包名下面,只是处于不同的source folder下。上述测试样例是最简单的例子,只是调用了assertEqual方法,更多的测试方法可以见文档。
下面是测试类的一些要求。
- 1测试方法必须使用@Test进行修饰
- 2测试方法必须使用public void方法,不能带参数
- 3新建一个源代码目录来存放测试代码
- 4测试类的包应该和被测试类一致
- 5测试单位的每个方法必须可以独立测试,测试方法不能有依赖
- 6测试类使用Test作为类名后最(不是必须)
- 7测试方法使用test作为前缀(不是必须)
下面这个类演示了junit测试时候调用每个方法的次序。
package com.dong.util; import static org.junit.Assert.assertEquals; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class JunitFlowTest { /** * 所有方法被调用前执行。由于是静态的,适合只加载一次的内容。 例如配置文件 * * @throws Exception */ @BeforeClass public static void setUpBeforeClass() throws Exception { System.out.println("@BeforeClass"); } /** * 资源清理 * * @throws Exception */ @AfterClass public static void tearDownAfterClass() throws Exception { System.out.println("@AfterClass"); } /** * 方法执行前 * * @throws Exception */ @Before public void setUp() throws Exception { System.out.println("@@Before"); } /** * 方法执行后 * * @throws Exception */ @After public void tearDown() throws Exception { System.out.println("@@After"); } @Test public void testAdd() { System.out.println("testAdd"); assertEquals(5, new Calculate().add(3, 3)); } @Test public void testMutiply() { assertEquals(9, new Calculate().mutiply(3, 3)); } }
@BeforeClass表示的是测试类测试所用方法前进行的操作。
@AfterClass表示的是测试类测试所有方法后执行的操作。
@Before表示的是执行每个测试方法前进行的操作。
@After表示的是执行每个测试方法后所执行的操作。
下面这个类演示了一些常用的测试注解所使用的方式。
package com.dong.util; import static org.junit.Assert.assertEquals; import org.junit.Ignore; import org.junit.Test; /** * junit注解 * * @author 95 * */ public class AnotationTest { /** * @Test把一个普通方法设置为测试方法 * @Test(expected = ArithmeticException.class) 表示预期会抛出一个异常 * @Test(timeout=毫秒) 测试死循环和性能测试 * @BeforeClass 所有方法执行前执行 * @AfterClass 所有方法执行后执行 * @Before 每个方法执行前执行 * @After 每个方法执行后执行 * @Ignore 忽略 * @RunWith可以更改测试运行器 org.junit.runner.Runner */ /** * @Test(expected = ArithmeticException.class) 表示预期会抛出一个异常 */ @Test public void testDivide() { assertEquals(1, new Calculate().divide(3, 0)); } /** * @Test(timeout=毫秒) 测试死循环和性能测试 */ @Ignore @Test(timeout = 1000) public void testWhile() { while (true) { assertEquals(1, new Calculate().divide(3, 3)); } } @Test(timeout = 2000) public void testReadFile() { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
在一些情况下,可能需要同时测试多个测试用例,如果每次都写assert则显得很麻烦。比如我们想测试加法时候,有这样2个样例 1+2?=3 ,2+2?=4。可以使用如下代码进行实现。
package com.dong.util; import static org.junit.Assert.assertEquals; 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; @RunWith(Parameterized.class) public class ParameterTest { /** * 1更改默认的测试运行期为@RunWith(Parameterized.class) 2声明变量来存放预期值和结果值 * 3声明一个返回值为Collection的公共静态方法,并使用@Parameters修饰 * 4为测试类声明一个带有参数的公共构造函数,并在其中为之声明变量赋值 */ int expected = 0; int input1 = 0; int input2 = 0; @Parameters public static Collection<Object[]> t() { return Arrays.asList(new Object[][] { { 3, 1, 2 }, { 4, 2, 2 } }); } public ParameterTest(int expected, int input1, int input2) { super(); this.expected = expected; this.input1 = input1; this.input2 = input2; } @Test public void testAdd() { assertEquals(expected, new Calculate().add(input1, input2)); } }
当我们一次想运行制定的几个测试类的时候,我们可以使用suite。使用方法如下。
/** * 测试套件 * * @author 95 * */ @RunWith(Suite.class) // 测试套件入口类,一次运行多个类 @Suite.SuiteClasses({ TastTest.class, TastTest1.class, TastTest4.class }) public class SuiteTest { /** * 1、 测试套件就是组织测试类一起运行的 * * 写一个作为测试套件的入口类,这个类不包含其他的方法 更改测试类运行期Suite.class * 将要测试的类作为数组传入到Suite.SuiteClass({}) */ }