Junit初级篇

@Test介绍



@Test是我们在写测试脚本时最常用到的,大部分情况下如果没用这个注解,一个方法就不能成为测试用例。如下代码是一个最普通的测试脚本:

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

public class GeneralTest {

    @Test
    public void test() {
        int num1 = 1;
        int num2 = 2;
        int sum = num1 + num2;
        Assert.assertEquals(3, sum);
    }

}

运行一下看看:

恭喜,获得一个绿条。这个脚本包含了测试脚本基本的几个元素:参数定义、参数运算、结果校验。@Test在这个测试脚本的作用就是让一个普通的方法(Method)变成一个JUnit可识别的测试脚本。但是@Test除了标记测试脚本的功能外,还有什么功能呢?

先来看看@Test的源码:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {

    /**
     * Default empty exception
     */
    static class None extends Throwable {
        private static final long serialVersionUID = 1L;

        private None() {
        }
    }

    /**
     * Optionally specify <code>expected</code>, a Throwable,
     * to cause a test method to succeed iff
     * an exception of the specified class is thrown by the method.
     */
    Class<? extends Throwable> expected() default None.class;

    /**
     * Optionally specify <code>timeout</code> in milliseconds to
     * cause a test method to fail if it
     * takes longer than that number of milliseconds.
     */
    long timeout() default 0L;
}

从源码可以看出,@Test还有两个属性,分别是expected()timeout(),可以从注解中看到这两个属性的作用:

  • expected():校验测试脚本抛出指定类型的异常
  • timeout():测试脚本的运行时间是否满足要求

下面举个例子看看这个两个属性如何使用:

import org.junit.Test;

public class TimeoutAndExceptionTest {

    @Test(timeout = 1000) //脚本运行时间小于1000毫秒
    public void testTimeout() throws InterruptedException {
        Thread.sleep(900);
    }

    @Test(expected = IllegalArgumentException.class) //脚本抛出参数非法的异常
    public void testExpectedThrowable() {
        throw new IllegalArgumentException();
    }

    @Test(timeout = 1000) //脚本运行时间小于1000毫秒
    public void testTimeoutFailed() throws InterruptedException {
        Thread.sleep(2000);
    }

    @Test(expected = IllegalArgumentException.class) //脚本抛出参数非法的异常
    public void testExpectedThrowableFailed() {
        throw new NullPointerException();
    }

}

运行后发现testTimeoutFailed()testExpectedThrowableFailed()运行失败,错误提示如下:

可见JUnit已经帮助我们完成断言的工作。至此,@Test的功能已经全部介绍完了。

@Ignore介绍



@Ignore是偶尔且一定会用到的注解,从名字就能知道其作用是“忽略”,即忽略一个测试脚本,标注了@Ignore注解的测试脚本将不会被执行。用法很简单,示例如下:

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

public class IgnoreTest {

    @Test
    @Ignore
    public void test() {
        //some test
    }

}

运行一下

发现这个测试脚本的确没被运行。不过如果另外一个人来看这个脚本就会很疑惑这个测试脚本为什么要被忽略。所以必须要说明这个测试脚本被忽略的原因。那在什么地方说明呢?可以先看看@Ignore本身是否提供这个功能,所以先看看@Ignore的源码:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Ignore {
    /**
     * The optional reason why the test is ignored.
     */
    String value() default "";
}

从源码来看,@Ignorevalue()就是为这个需求准备的,可以说明测试脚本被忽略的原因。我们可以将上面的测试脚本修改如下:

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

public class IgnoreTest {

    @Test
    @Ignore("not ready yet!")
    public void test() {
        //some test
    }

}

修改后就清楚多了,无论以后谁来维护这个测试脚本,都可以很直观的看到这个测试脚本是因为“还未准备好”而忽略的。

再运行一下

发现运行结构并没有不同,可见Eclipse并有没读取@Ignorevalue()值,不过并不是所有的IDE都是这样,可以看下IDEA的运行效果。

从运行结果发现,IDEA可以在运行结果展示被忽略的原因。

@Before@After@BeforeClass@AfterClass介绍



@Before@After@BeforeClass@AfterClass也是我们常用的注解,使用频率与@Test一样,一般每个测试脚本都会出现这些注解,用来做测试数据准备和资源回收等工作。那么,首先介绍下这些注解的执行范围。

  • @Bfore:每个测试用例(Method)运行前执行一次
  • @After:每个测试用例(Method)运行后执行一次
  • @BeforeClass:每个测试脚本(Class)运行前执行一次
  • @AfterClass:每个测试脚本(Class)运行前执行一次

每个注解对所标注的方法(Method)的要求如下:

  • @Bfore@After:公共(public)的、非静态(static)的、无返回值(void)、无参数的方法(Method)
  • @BeforeClass@AfterClass:公共(public)的、静态(static)的、无返回值(void)、无参数的方法(Method)

下面用一个简单的例子说明一下这些规则:

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

public class BeforeAndAfterTest {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("BeforeClass");
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("AfterClass");
    }

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

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

    @Test
    public void test01() {
        System.out.println("Test01");
    }

    @Test
    public void test02() {
        System.out.println("Test02");
    }

}

运行一下

只有标注了@Test注解的方法(Method)被识别为测试用例。

再看看控制台(Console)的输出内容

BeforeClass
Before
Test01
After
Before
Test02
After
AfterClass

和上面所说的规则一致。

@RunWith介绍



基于JUnit的测试脚本都是依靠Runner去解析和执行,@Test等所有注解的执行顺序、生命周期也都是由Runner决定的,所以Runner是JUnit的核心。

自然,将Runner作为JUnit的扩展点将使JUnit更易扩展,这个将在高级篇介绍。

从JUnit4.5以后,JUnit的默认Runner改为BlockJUnit4ClassRunner,将原来的JUnit4ClassRunner改为BlockJUnit4ClassRunner继承ParentRunner<T>的形式,增强了JUnit的可扩展性。同时,JUnit也自带很多Runner来丰富自身的功能。

那么,使用其他功能的Runner呢?那就要使用@RunWith注解了,下面用一个简单的小例子演示下@RunWith的使用。

首先需要自定义一个Runner,作用是打印每个运行的测试用例的方法名(Method Name),具体Runner的实现将在高级篇中详细讨论。代码如下:

import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class LoggingRunner extends BlockJUnit4ClassRunner {

    public LoggingRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected void runChild(FrameworkMethod method, RunNotifier notifier) {
        System.out.println(method.getName());
        super.runChild(method, notifier);
    }

}

然后通过@RunWith使用这个注解。

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(LoggingRunner.class) //在这里使用
public class RunWithTest {

    @Test
    public void test01() {
    }

    @Test
    public void test02() {
    }

}

最后运行下看看结果。

test01
test02

正确打印出两个测试用例的方法。

可以看到,@RunWith用法十分简单,但是这是个十分重要的功能,因为后面的中级篇、高级篇中大部分功能都基于一个特殊功能的Runner,都需要使用@RunWith,请牢记。

摘自:http://liwx2000.github.io/junit/2013/05/15/junit-junior.html

时间: 2024-10-05 10:53:05

Junit初级篇的相关文章

【Java】在Eclipse中使用JUnit4进行单元测试(初级篇)

本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的.但是,我们同时应该确保每一个函数都完全正确,因为如果我们今后如果对程序进行扩展,用到了某个函数的其他功能,而这个功能有bug的话,那绝对是一件非常郁闷的事情.所以说,每编写完一个函数之后,都应该对这个函数

在Eclipse中使用JUnit4进行单元测试(初级篇)【转】

来自[http://blog.csdn.net/andycpp/article/details/1327147] 本文绝大部分内容引自这篇文章: http://www.devx.com/Java/Article/31983/0/page/1 我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的.但是,我们同时应该确保每一个函数都完全正确,因为如果我们今后如果对程序进行扩展,用到了某个

内存泄露之常见问题解决--初级篇

身为一个段子猿,我决定来写写最近的学习心得. 1.简介 在整个Android开发过程中,内存泄露是导致OOM的一个重点因素.大概意思就是:GC无法回收原本应该被回收的对象,这个对象就引发了内存泄露.那有什么危害呢?手机的内存大小是有限的,如果不能释放的话,你就无法创建新的对象,你的新界面等等就无法正常运行,然后程序就OOM了(OutOfMemory). 2.OOM以及内存泄露 OOM通俗点讲就是,你家里有2个厕所,本来你和你老婆用的话,都是够用的,有一天你不小心造人了,从此家里有了1+1=3个人

javascript调试之chrome初级篇

请原谅我的喜新厌旧! 以前我是firebug和firefox的忠实粉丝,虽然现在依然对ff心存好感,但是chrome在我心中的地位与日俱增.以前实习时导师看到我在用firebug调试时善意地告诉我以后要习惯用chrome,我还不以为意,直到现在深深地爱上了chrome的简洁方便.我基本不会html和css,js也只会那么一点,所以现在为止基本上不用用到高级一点的调试,so此文为调试之初级篇.

python_way ,day7 面向对象 (初级篇)

面向对象 初级篇 python支持 函数 与 面向对象 什么时候实用面向对象? 面向对象与函数对比 类和对象 创建类 class 类名 def 方法名(self,xxxx) 类里面的方法,只能对象去调用 对象 = 类名() 通过对象执行方法 对象.方法名(xxxx) 设计,增删改查功能 函数式: def fetch(self,host,port name passwd,sql) pass def create(self,host,port name passwd,sql) pass def re

(转)25个增强iOS应用程序性能的提示和技巧--初级篇

(转)25个增强iOS应用程序性能的提示和技巧--初级篇 本文转自:http://www.cocoachina.com/newbie/tutorial/2013/0408/5952.html 在开发iOS应用程序时,让程序具有良好的性能是非常关键的.这也是用户所期望的,如果你的程序运行迟钝或缓慢,会招致用户的差评.然而由于iOS设备的局限性,有时候要想获得良好的性能,是很困难的.在开发过程中,有许多事项需要记住,并且关于性能影响很容易就忘记. 本文收集了25个关于可以提升程序性能的提示和技巧,把

移动端https抓包那些事--初级篇

对于刚刚进入移动安全领域的安全研究人员或者安全爱好者,在对手机APP进行渗透测试的时候会发现一个很大的问题,就是无法抓取https的流量数据包,导致渗透测试无法继续进行下去. 这次给大家介绍一些手机端如何抓取https流量的技巧. 下面将主要通过两个层次篇章来逐步向大家进行介绍: 第一篇章-初级篇:浅层次抓包.对于非root设备(Android)或非越狱设备(iOS)如何抓取https流量: 第二篇章-进阶篇:深层次抓包.对于root设备或者越狱设备如何抓取https流量. 对于非root An

canvas画图——初级篇

         canvas画图之初级篇 小女子准备将canvas画图分为初级篇,中级篇和高级篇来介绍,读者们不要着急哦. 初级篇 一.首先什么是canvas呢? canvas 是 HTML5 提供的一个用于展示绘图效果的标签. canvas 原意画布, 帆 布. 在 HTML 页面中用于展示绘图效果. 最早 canvas 是苹果提出的一个方案, 今天已经在大多数浏览器中实现. canvas 英 ['kænv?s]  美 ['kænv?s]   帆布 画布 二.让我们先来了解下canvas的基

ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇(转)

ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇 阅读目录 ASP.NET Identity 前世今生 建立 ASP.NET Identity 使用ASP.NET Identity ASP.NET Identity 其他API介绍 小节 在之前的文章中,我为大家介绍了OWIN和Katana,有了对它们的基本了解后,才能更好的去学习ASP.NET Identity,因为它已经对OWIN 有了良好的集成. 在这篇文章中,我主要关注ASP.NET Identity的建