zoukankan      html  css  js  c++  java
  • JUnit学习摘要+入门实例

    1.学习摘要

      看《重构-改善既有代码的设计》这本书的时候,里面提到测试环境对于重构的重要性,想到之前在编写代码的时候都是通过System.out和alert来做测试,非常麻烦,而且不够正规,对于即将步入工作的人来说,一个正规的写代码习惯和测试习惯是非常重要的,因此我觉得好好学学如何使用JUnit。

      在JUnit和单元测试入门简介一文中提到“JUnit框架是一个典型的Composite模式:TestSuite可以容纳任何派生自Test的对象;当调用TestSuite对象的run()方法是,会遍历自己容纳的对象,逐个调用它们的run()方法”。

      这又让我想起自己前段时间在读的《研磨设计模式》这本书,读了前面的九章,写了一些博客,但是还没有整理,不过大多也忘了。可能自己没有真正理解吧。其实,一时的理解,如果没有在实际项目中应用,还是很容易遗忘的。希望自己能在重构项目的时候多用一些设计模式上的内容。《研磨设计模式》这本书中的第15章讲的就是组合模式(Composite),有空了就去看一看。

      在使用eclipse进行junit的时候,添加junit包才发现有junit3和junit4两个版本,这两者的区别可以参考JUnit测试框架之JUnit3和JUnit4使用区别的总结

    2.入门实例

    步骤1:创建待测试类

    首先新建一个项目叫JUnit_Test,我们编写一个Calculator类,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。这个类并不是很完美,我们故意保留了一些Bug用于演示,这些Bug在注释中都有说明。该类代码如下:

    package xw.calculator;
    public class Calculator {

    private static int result; // 静态变量,用于存储运行结果
    public void add(int n) {
    result = result + n;
    }
    public void substract(int n) {
    result = result - 1; // Bug: 正确的应该是 result =result-n
    }

    public void multiply(int n) {
    } // 此方法尚未写好

    public void divide(int n) {
    result = result / n;
    }

    public void square(int n) {
    result = n * n;
    }

    public void squareRoot(int n) {
    for (;;)
    ; // Bug : 死循环
    }

    public void clear() { // 将结果清零
    result = 0;
    }

    public int getResult() {
    return result;
    }
    }

    步骤2:在eclipse中为项目添加JUnit环境

    右键JUnit_Test项目,在build path中“add library”,添加JUnit,如下图所示:

    步骤3:创建测试类

    右键Calculator类,选择“new",创建JUnit Test Case

    步骤4:修改测试用例代码

    测试用例代码如下:

    package xw.calculatortest;
    import static org.junit.Assert.*;

    import org.junit.Before;
    import org.junit.Ignore;
    import org.junit.Test;

    import xw.calculator.Calculator;

    public class CalculatorTest {
    private static Calculator calculator = new Calculator();

    // 复原操作,表明对每个Test方法测试以后都会进行这个方法操作。
    @Before
    public void setUp() throws Exception {
    calculator.clear();// 结果清零
    }

    @Test
    public void testAdd() {
    // fail("Not yet implemented");
    calculator.add(2);
    calculator.add(3);
    assertEquals(5, calculator.getResult());
    }

    @Test
    public void testSubstract() {
    // fail("Not yet implemented");
    calculator.add(10);
    calculator.substract(2);
    assertEquals(8, calculator.getResult());
    }

    // 忽略标注,表明这个方法功能还没有实现
    @Ignore("Multiply() Not yet implemented")
    @Test
    public void testMultiply() {
    fail("Not yet implemented");
    }

    @Test
    public void testDivide() {
    // fail("Not yet implemented");
    calculator.add(8);
    calculator.divide(2);
    assertEquals(4, calculator.getResult());
    }

    // Timeout参数表明了你要设定的时间,单位为毫秒,因此1000就代表1秒。
    @Test(timeout = 1000)
    public void squareRoot() {
    calculator.squareRoot(4);
    assertEquals(2, calculator.getResult());

    }

    /**
    * square1/square2/square3分别用来测试正数,0,复数的平方
    */
    @Test
    public void square1() {
    calculator.square(2);
    assertEquals(4, calculator.getResult());
    }

    @Test
    public void square2() {
    calculator.square(0);
    assertEquals(0, calculator.getResult());
    }

    @Test
    public void square3() {
    calculator.square(-3);
    assertEquals(9, calculator.getResult());
    }
    }

    参数化测试与运行器(Runner)

    考虑一种场景,如果要单独测试正数的平方,0的平方以及负数的平方,那么就要创建三个测试方法来进行测试,这样会显得特别繁琐,如步骤4中最后的三个测试方法square1()、square2()和square3()。JUnit考虑到了这种情况,提出了参数化测试方法。这个时候运行器也不是默认的运行器,而是通过@RunWith(Parameterized.class)来标注。

    参数化测试代码如下所示;

    package xw.calculatortest;
    import static org.junit.Assert.*;
    import java.util.Arrays;
    import java.util.Collection;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.Parameterized;
    import org.junit.runners.Parameterized.Parameters;
    import xw.calculator.Calculator;
    @RunWith(Parameterized.class)
    public class SquareTest {
    private static Calculator calculator = new Calculator();
    private int param;
    private int result;

    @Parameters
    public static Collection 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方法测试以后都会进行这个方法操作。
    @Before
    public void setUp() throws Exception {
    calculator.clear();// 结果清零
    }

    @Test
    public void testSquare() {
    calculator.square(param);
    assertEquals(result, calculator.getResult());
    }
    }

    打包测试

    考虑另外一种场景,如果一个项目中有许多个测试类,一个一个去运行会非常繁琐,这个时候就可以考虑使用打包测试。将所有需要运行的测试类集中起来,一次性的运行完毕,大大的方便了我们的测试工作。

    右键Calculator类,新建一个JUnit Test Suite,如下图所示。

    然后选择需要打包测试的测试类,如下图所示:

    打包测试类叫做AllTests,需要打包测试的三个测试类是CalculatorTest,SquareTest和test。点击Finish完成打包测试,生成的打包测试类大吗如下:

    package xw.calculatortest;

    import org.junit.runner.RunWith;
    import org.junit.runners.Suite;
    import org.junit.runners.Suite.SuiteClasses;

    @RunWith(Suite.class)
    @SuiteClasses({ CalculatorTest.class, SquareTest.class, test.class })
    public class AllTests {

    }

    运行结果如下:



     



  • 相关阅读:
    小米范工具系列之一:小米范 web查找器
    不同格式的ip 统一转成ip列表
    Educational Codeforces Round 32
    离散化方式
    线段树合并与分裂
    HDU1074
    容斥原理
    模板
    HDU1024 Max Sum Plus Plus
    CSA Round #56
  • 原文地址:https://www.cnblogs.com/xwdreamer/p/2423136.html
Copyright © 2011-2022 走看看