• JUnit4 使用指南二 (熟练掌握)


    上一章节中我们只是简单的介绍了下在Eclipse中使用JUnit4的简要过程,这一章节中,我们首先简要的比较下JUnit4与JUnit3的不同之处,然后详细的分析JUnit4常用的一些特性,掌握它们对灵活编写单元测试代码会非常有帮助。

    1. JUnit4 与 JUnit3 的区别

    上一章节中,我们写了一个Calculator的TestCase ”CalculatorTest“,我们分别来看一下JUnit3与JUnit4的代码实现:

    JUnit3的实现

    package com.rigel.ut;

    import org.junit.Assert;
    import junit.framework.TestCase;

    public class CalculatorTest2 extends TestCase {

    private Calculator calc = new Calculator();

    public void testAdd() {
    calc.add(
    0,4);
    int result = 4;
    // 通过 Assert 对 function 功能进行测试
    Assert.assertEquals(result, calc.getResult());
    }

    }
     

    JUnit4的实现

    package com.rigel.ut;

    import org.junit.Assert;
    import org.junit.Test;

    public class CalculatorTest {

    private Calculator calc = new Calculator();

    @Test
    public void testAdd() {
    calc.add(
    0,4);
    int result = 4;
    // 通过 Assert 对 function 功能进行测试
    Assert.assertEquals(result, calc.getResult());
    }
    }

    总 结一下,在JUnit3中,编写的测试类强制要求继承”TestCase“类,而且测试方法必须以”test*“开头;而在JUnit4中,通过元注解代 替对测试方法的一些强制约定,这样可以使得代码更加简化,可懂度也要好很多。当然,由于这个例子比较简单,两者之间很多其他不同之处都没有体现出来,比如 在 JUnit3中的Fixture方法硬性规定为”setUp“ & "tearDown",而在JUnit4中,则只要用”@Before“ & ”@After“元注解来标识方法就可以,至于方法名,则不作限制。

    可参考:http://blog.sina.com.cn/s/blog_4ce9e82e0100bh1t.html

    2. JUnit4中一些常用的元注解

    @Test

    这个注解我们在上例之中已经见过,主要是用来标注测试方法;

    @Test(timeout = *** )

    该元数据传入了一个时间(毫秒)给测试方法,如果测试方法在制定的时间之内没有运行完,则测试也失败;
    @Test(expected=*.class)
    在JUnit4.0之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue(true)来测试。现在,通过@Test元数据中的expected属性。expected属性的值是一个异常的类型。
    @Ignore
    该 元数据标记的测试方法在测试中会被忽略。当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库联接,而 在本地测试的时候,数据库并没有连接),那么使用该标签来标示这个方法。同时,你可以为该标签传递一个String的参数,来表明为什么会忽略这个测试方 法。比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。
    下面我们通过实例来分析这些注解的使用,首先我们扩充下之前写的那个Calculator类,代码如下所示:
    package com.rigel.ut;

    /**
    * 一个计算器功能类
    *
    *
    */
    public class Calculator {

    private int result; /* 保存计算的结果 */

    /**
    * 实现加法功能
    * 为了测试 @Test 注解
    *
    */
    public void add(int a, int b) {
    result
    = a + b;
    }

    /**
    * 实现减法功能
    * 为了函数测试失败的情况,这个函数功能故意写错。
    *
    */
    public void substract(int a, int b) {
    result
    = a - b;
    }

    /**
    * 实现乘法功能,该方法暂未实现
    * 为了方便测试 @Ignore 注解
    *
    */
    public void multiply(int a, int b) {
    // do nothing.
    }

    /**
    * 实现除法功能
    * 为了方便测试 @Test(expected=*.class)注解,即异常情况
    *
    */
    public void devide(int a, int b) {
    result
    = a / b;
    }

    /**
    * 实现平方的功能
    * 方法故意写错,主要为了测试超时的情况,即测试@Test(timeout = ***)
    *
    */
    public void square(int n) {
    // 死循环
    for(;;);
    }

    /**
    * 清除计算结果
    *
    */
    public void clear() {
    result
    = 0;
    }

    public void setResult(int result) {
    this.result = result;
    }
    public int getResult() {
    return this.result;
    }

    }
    针对该Calculator的各功能方法分别测试,TestCase实现如下:
    package com.rigel.ut;

    import org.junit.Assert;
    import org.junit.Ignore;
    import org.junit.Test;

    public class CalculatorTest {

    private Calculator calc = new Calculator();

    @Test
    public void testAdd() {
    calc.add(
    0,4);
    int result = 4;
    Assert.assertEquals(result, calc.getResult());
    }

    @Test
    public void testSubstract() {
    calc.clear();
    calc.substract(
    0,5);
    int result = -5;
    Assert.assertEquals(result, calc.getResult());
    }

    @Ignore
    public void testMultiply() {
    // multiply 功能未实现,该测试方法暂不执行
    }

    @Test(expected
    = ArithmeticException.class)
    public void testDevide() {
    calc.devide(
    5,0);
    }

    @Test(timeout
    = 5000)
    public void testSquare() {
    calc.square(
    5);
    }
    }
    这些测试方法分别针对测试成功、失败、期望出现异常及超时的情况进行分析,最后Testcase Run 的结果如下:

    其中,在 ”Failure Trace“详细解析了失败及Error的原因,如上图,Failure提示的信息为:函数期望值为-1,而测试指定的结果为-5;另外也可以看到@Ignore注解的测试方法“testMultiply”被运行器忽略了,并未执行;而@Test(timeout="***")注解的方法“testSquare”则由于超时抛出Error;

    接下来介绍的元注解对应Fixture方法。所谓Fixture是指在执行一个或者多个测试方法时需要的一系列公共资源或者数据。说的简单点就是“在某些阶段必然被调用的代码”。JUnit4中对应修饰Fixture方法的元注解如下:
    @Before
    @After
    也称为方法级别的Fixture。其在每一个测试方法执行之前,JUnit 会保证带有@Before注解的方法已经提前初始化测试环境,而当此测试方法执行完毕之后,JUnit 又会调用带有@After注解的方法注销测境。这样便可以保证各个独立的测试之间互不干扰,以免其它测试代码修改测试环境或者测试数据影响到其它测试代码 的准确性。其流程如下所示:
    @BeforeClass
    @AfterClass

    也称为类级别的Fixture。其在所有的测试方法执行之前,JUnit 会保证带有@BeforeClass注解的方法已经提前初始化测试环境,而当所有的测试方法执行完毕之后,JUnit 又会调用带有@AfterClass注解的方法注销测试环境。这主要是针对TestCase中,很多测试方法不需要一次次的执行相同的初始化及注销方法,以提高测试的效率;其流程如下图所示:

    接下来测试 Fixture 方法对应的元注解,我们从新写一个TestCase,其内容如下:

    package com.rigel.ut;

    import org.junit.After;
    import org.junit.AfterClass;
    import org.junit.Before;
    import org.junit.BeforeClass;
    import org.junit.Test;

    public class FixtureTest {

    @Before
    public void before() {
    System.out.println(
    "before method running");
    }

    @After
    public void after() {
    System.out.println(
    "after method running");
    }

    @BeforeClass
    public static void beforeClass() {
    System.out.println(
    "before all method running");
    }
    @AfterClass
    public static void afterClass() {
    System.out.println(
    "after all method running");
    }

    @Test
    public void test1() {
    System.out.println(
    "test1 method");
    }

    @Test
    public void test2() {
    System.out.println(
    "test2 method");
    }

    }

    其中,@BeforeClass 和 @AfterClass 对应的是类级别的Fixture,所以方法必须申明为static,TestCase的运行结果如下所示:

    从图中可以看出:

    @BeforeClass 对应的方法最先执行,且只执行了一次;

    @AfterClass 对应的方法最后执行,也只执行了一次;

    @Before 对应的方法执行了两次,其在每个@Test标注的方法之前执行,即在每个测试方法之前执行;

    @After 对应的方法执行了两次,在每个测试方法执行完之后执行;

    总 结一下,本章节首先简要的分析了JUnit4与JUnit3的不同之处,然后详细讲解了JUnit4中常用的元注解的使用。在测试用例中,所有的测试方法 都是通过Assert.assertEquals(...)方法来判定,当然,Assert还有很多其他方法可以使用,其常用的方法如下,具体大家可参考 相应的文档。

    本章节到此结束,下一章节将介绍JUnit4的一些高级特性。

  • 相关阅读:
    复习一allure
    本地push 到git hub 二
    项目过程中,测试总感觉自己的时间不够怎么办?
    记一次接口并发,酿成20万损失的惨案
    记录一次管理员组织应用的运行
    记录一次jmeter脚本开发缺少utf-8惹的祸
    记录一次pycharm中,引入其他类可用,下面总是有波浪线,而且Ctrl+b 无法查看类函数的源码
    Fiddler如何过滤无用的链接
    【bat】将当前文件夹及其子文件夹下的所有文件移动到新文件夹中
    python 安装python-docx模块(如何本地安装)
  • 原文地址:https://www.cnblogs.com/shine_cn/p/2060917.html
Copyright © 2020-2023  润新知