Junit4精简解析

6 篇文章 0 订阅

JUnit4是JUnit框架有史以来的最大改进,其主要目标便是利用Java5的Annotation特性简化测试用例的编写。先简单解释一下什么是Annotation,这个单词一般是翻译成元数据。元数据是什么?元数据就是描述数据的数据。也就是说,这个东西在Java里面可以用来和public、static等关键字一样来修饰类名、方法名、变量名。修饰的作用描述这个数据是做什么用的,差不多和public描述这个数据是公有的一样。想具体了解可以看Core Java2。
废话不多说了,直接进入正题。

比如你在一个叫AddOperation的类中定义一个计算加法的方法

public class AddOperation {
      public int add(int x,int y){
          return x+y;
      }
}

那么我们要测试这个加的方法就可以在同一包下新建一个Junit Test Case文件,里面的重载方法默认就行了。

import junit.framework.TestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

/**
*
* @author bean
*/
public class AddOperationTest extends TestCase{

      public AddOperationTest() {
      }

     @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
    }

    @Before
    public void setUp() throws Exception {
    }

    @After
    public void tearDown() throws Exception {
    }

      @Test
      public void add() {
         System.out.println("add");
          int x = 0;
          int y = 0;
          AddOperation instance = newAddOperation();
          int expResult = 0;
          int result = instance.add(x,y);
          assertEquals(expResult,result);
      }

}

从上面的例子可以看到在JUnit 4中还引入了一些其他的元数据,下面一一介绍:

@BeforeClass
在测试类开始运行时调用这个Annotaion里的方法

@AfterClass
在整个测试类结束时调用这个Annotation里的方法

@Before:
使用了该元数据的方法在每个测试方法执行之前都要执行一次。
某些方法在每次执行前需要一些初始化工作的话,使用@Before做准备工作,然后再测试。

@After:
使用了该元数据的方法在每个测试方法执行之后要执行一次。
进行一些资源释放和内存清理。

注意:@Before和@After标示的方法只能各有一个。这个相当于取代了JUnit以前版本中的setUp和tearDown方法,当然你还可以继续叫这个名字,不过JUnit不会霸道的要求你这么做了。

@Test(expected=*.class)
在JUnit4.0之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue(true)来测试。现在,通过@Test元数据中的expected属性。expected属性的值是一个异常的类型

@Test(timeout=xxx):
该元数据传入了一个时间(毫秒)给测试方法,
如果测试方法在制定的时间之内没有运行完,则测试也失败。

@ignore:
该元数据标记的测试方法在测试中会被忽略。当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方法。比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

@Test(expected = ArithmeticException.class)
异常测试,比如指定可能的一场为算术异常。

@Test(expected = ArithmeticException.class)
  public void divideByZero() ...{
    calculator.divide(0);
   }

介绍完简单的测试之后,再来说下复杂一点的参数测试。

参数化测试。

你可能遇到过这样的函数,它的参数有许多特殊值,或者说他的参数分为很多个区域。比如,一个对考试分数进行评价的函数,返回值分别为“优秀,良好,一般,及格,不及格”,因此你在编写测试的时候,至少要写5个测试,把这5中情况都包含了,这确实是一件很麻烦的事情。我们还使用我们先前的例子,测试一下“计算一个数的平方”这个函数,暂且分三类:正数、0、负数。测试代码如下:

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*; 

public class AdvancedTest ...{ 
private static Calculator calculator = new Calculator();
    @Before
public void clearCalculator() ...{
        calculator.clear();
}

    @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());
}
 }

为了简化类似的测试,JUnit4提出了“参数化测试”的概念,只写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。代码如下:

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters; 
import java.util.Arrays;
import java.util.Collection; 

@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    
public void square() ...{
        calculator.square(param);
        assertEquals(result, calculator.getResult());
    }
 }

下面我们对上述代码进行分析。首先,你要为这种测试专门生成一个新的类,而不能与其他测试共用同一个类,此例中我们定义了一个SquareTest类。然后,你要为这个类指定一个Runner,而不能使用默认的Runner了,因为特殊的功能要用特殊的Runner嘛。@RunWith(Parameterized.class)这条语句就是为这个类指定了一个ParameterizedRunner。第二步,定义一个待测试的类,并且定义两个变量,一个用于存放参数,一个用于存放期待的结果。接下来,定义测试数据的集合,也就是上述的data()方法,该方法可以任意命名,但是必须使用@Parameters标注进行修饰。这个方法的框架就不予解释了,大家只需要注意其中的数据,是一个二维数组,数据两两一组,每组中的这两个数据,一个是参数,一个是你预期的结果。比如我们的第一组{2, 4},2就是参数,4就是预期的结果。这两个数据的顺序无所谓,谁前谁后都可以。之后是构造函数,其功能就是对先前定义的两个参数进行初始化。在这里你可要注意一下参数的顺序了,要和上面的数据集合的顺序保持一致。如果前面的顺序是{参数,期待的结果},那么你构造函数的顺序也要是“构造函数(参数, 期待的结果)”,反之亦然。最后就是写一个简单的测试例了,和前面介绍过的写法完全一样,在此就不多说。

最后上两个完整的代码片(talk is cheap show me the code)

参数测试

Math类

package perMute;

import TreeSet.intCompare;

public class Math {
public Math(){

}
public int add(int i,int j) {
    return i+j;
}
}

MathTest类(参数化测试)

package perMute;
import java.util.Arrays;
import java.util.Collection;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * 参数化测试的类必须有Parameterized测试运行器修饰
 * 
 */
@RunWith(Parameterized.class)
public class mMathTest {
    Math math = new Math();
    private int input1;
    private int input2;
    private int expected;

    /**
     * 准备数据。数据的准备需要在一个方法中进行,该方法需要满足一定的要求:
     * 
     * 1)该方法必须由Parameters注解修饰 2)该方法必须为public static的 3)该方法必须返回Collection类型
     * 4)该方法的名字不做要求 5)该方法没有参数
     * 
     * @return
     */
    @Parameters
    @SuppressWarnings("unchecked")
    public static Collection prepareData() {
        Object[][] object = { { -1, -2, -3 }, { 0, 2, 2 }, { -1, 1, 0 },
                { 1, 2, 3 } };
        return Arrays.asList(object);
    }

    public mMathTest(int input1, int input2, int expected) {
        this.input1 = input1;
        this.input2 = input2;
        this.expected = expected;
    }

    @Test
    public void testAdd() {
        Assert.assertEquals(expected, math.add(input1, input2));
    }

}

快速排序和全排列单元测试

待测试类(三个方法需要被测试)

package perMute;

import java.awt.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class perMute {
    public String[] allSort1(String str) {
        int len = str.length();
        if (len == 0) {
            return null;
        }
        int count = 0, n = 1;
        for (int i = 1; i <= len; i++) {
            n *= i;
        }
        String[] strings = new String[n];
        String mtuxString = str;
        if (len == 1) {
            strings[0] = mtuxString;
        }
        // while (!str.equals(mtuxString)) {
        // mtuxString = swap(mtuxString, n, --n);
        // }
        for (int i = 0; i < n / len; i++) {
            if (i % 2 == 0) {
                for (int j = len - 1; j > 0; j--) {
                    mtuxString = swap(mtuxString, j, j - 1);
                    strings[count++] = mtuxString;
                    if (j == 1) {
                        mtuxString = swap(mtuxString, len - 1, len - 2);
                        strings[count++] = mtuxString;
                    }
                }
            } else {
                for (int j = 1; j <= len - 1; j++) {
                    mtuxString = swap(mtuxString, j, j - 1);
                    strings[count++] = mtuxString;
                    if (j == len - 1) {
                        mtuxString = swap(mtuxString, 0, 1);
                        strings[count++] = mtuxString;
                    }
                }
            }
        }

        return strings;
    }


    public static ArrayList<String> allSort2(String str, int pos) {
        ArrayList<String> list = new ArrayList<String>();
        if(pos==0){
//          str=quickSort(str);
        }
        int len = str.length();
        if (len == 0) {
            list.add("");
            return list;
        }
        list.add(str);
        if (len == 1) {
            return list;
        }
        for (int i = pos; i < len; i++) {
            str = swap(str, i, pos);
            list.add(str);
            if (pos < len - 1) {
                list.addAll(allSort2(str, pos + 1));
            } else {
                return list;
            }
        }
        return list;
    }

    public static String swap(String str, int i, int j) {
        if (str.length() == 0) {
            return null;
        }
        String afterSwap = "";
        char c;
        char[] cs = str.toCharArray();
        c = cs[i];
        cs[i] = cs[j];
        cs[j] = c;
        afterSwap = String.valueOf(cs);
        return afterSwap;
    }

    /**
     * Qucik sort 54,12,9,89,3,19,29,1 (1)选择54作为中轴 并定义tmp=54 1,12,9,89,3,19,29,1
     * (2) 定义一个队尾游标,从后向前扫描,选择小于54的第一个元素,并把它复制到54这个位置 1,12,9,89,3,19,29,89
     * (3)定义一个队首游标,从前向后扫描,扫描到大于54的第一个元素,并把它复制到1这个位置 1,12,9,29,3,19,29,89
     * (4)继续步骤2的扫描,扫描小于54的第一个元素,并把它复制到89这个位置 1,12,9,29,3,19,54,89
     * (5)继续步骤3的扫描,当扫描游标触碰到队尾游标时还未发现大于54的元素,则把tmp复制到队尾游标所指向的位置
     * (1,12,9,29,3,19)54(89) (6)分别对54左右两个数组执行步骤1
     * 
     * @param str
     * @return
     */
    public static String quickSort(String str) {
        int len = str.length();
        if (len == 0) {
            return "";
        }
        if (len == 1) {
            return str;
        }
        String resultStr = "";
        char[] cr = str.toCharArray();
        char pivol = cr[0];
        int i = 0, j = len - 1;
        while (true) {
            if (i < j) {
                while (j >= 0 && j > i) {
                    if (cr[j] > pivol) {
                        j--;
                    } else {
                        cr[i] = cr[j];
                        break;
                    }
                }
                while (i < len && j > i) {
                    if (cr[i] <= pivol) {
                        i++;
                    } else {
                        cr[j] = cr[i];
                        break;
                    }
                }
            } else {
                cr[j] = pivol;
                resultStr = String.valueOf(cr);
                break;
            }
        }
        return quickSort(resultStr.substring(0, j)) + pivol
                + quickSort(resultStr.substring(j + 1, len));
    }

    public static void cout1() {
        System.out.println("class before");
    }

    public static void cout2() {
        System.out.println("method before");
    }

    public static void cout3() {
        System.out.println("class after");
    }

    public static void cout4() {
        System.out.println("method after");
    }

测试类

package perMute;

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;

public class perMuteTest {

    perMute pm = new perMute();

    @BeforeClass
    public static void testBeforeClass() {
        // TODO Auto-generated method stub
        perMute.cout1();
    }

    @Before
    public  void testbefore() {
        // TODO Auto-generated method stub
        perMute.cout2();

    }

    @AfterClass
    public static void testAfterClass(){
        perMute.cout3();

    }

    @After
    public void testAfter(){
        perMute.cout4();

    }


    @Test
    public void testAllSort1() {
        assertNull(pm.allSort1(""));
        String[] strings1 = { "a" };
        assertArrayEquals(strings1, pm.allSort1("a"));
        String[] strings2 = { "ba", "ab" };
        assertArrayEquals(strings2, pm.allSort1("ab"));
        String[] strings3 = { "acb", "cab", "cba", "bca", "bac", "abc" };
        assertArrayEquals(strings3, pm.allSort1("abc"));
        String[] strings4 = { "abdc", "adbc", "dabc", "dacb", "adcb", "acdb",
                "acbd", "cabd", "cadb", "cdab", "dcab", "dcba", "cdba", "cbda",
                "cbad", "bcad", "bcda", "bdca", "dbca", "dbac", "bdac", "badc",
                "bacd", "abcd" };
        assertArrayEquals(strings4, pm.allSort1("abcd"));

    };

    @Ignore("UnImplemented do not test")
    @Test
    public void testAllSort2() {
        fail("Not yet implemented");
    }

    @Test(timeout=10)
    public void testSwap() {
        assertNull("null", pm.swap("", 0, 0));
        assertNull("null", pm.swap("", 0, 2));
        assertEquals(pm.swap("a", 0, 0), "a");
        assertEquals(pm.swap("a", 0, 0), "a");
        assertEquals(pm.swap("abc", 1, 2), "acb");
        assertEquals(pm.swap("abcd", 2, 3), "abdc");
        assertEquals(pm.swap("abcd", 0, 1), "bacd");
    }

    @Test(timeout=50)
    public void testquickSort(){
        assertEquals("", pm.quickSort(""));
        assertEquals("a", pm.quickSort("a"));
        assertEquals("1", pm.quickSort("1"));
        assertEquals("22", pm.quickSort("22"));
        assertEquals("123", pm.quickSort("123"));
        assertEquals("123", pm.quickSort("321"));
        assertEquals("123", pm.quickSort("213"));
        assertEquals("123", pm.quickSort("312"));
        assertEquals("1223", pm.quickSort("3212"));
        assertEquals("123456", pm.quickSort("123456"));
        assertEquals("123456", pm.quickSort("653214"));
        assertEquals("abc", pm.quickSort("abc"));
        assertEquals("abc", pm.quickSort("bca"));
        assertEquals("abc", pm.quickSort("cab"));
        assertEquals("cccc", pm.quickSort("cccc"));
        assertEquals("acuyz", pm.quickSort("acuyz"));
        assertEquals("acuyz", pm.quickSort("uyzca"));
        assertEquals("acuyz", pm.quickSort("czyua"));
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值