Junit初级篇
2015-07-04 14:37
363 查看
@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); } }
运行一下看看:
![](http://liwx2000.github.io/images/junit/general_test.png)
恭喜,获得一个绿条。这个脚本包含了测试脚本基本的几个元素:参数定义、参数运算、结果校验。
@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()运行失败,错误提示如下:
![](http://liwx2000.github.io/images/junit/test_timeout_expected.png)
可见JUnit已经帮助我们完成断言的工作。至此,
@Test的功能已经全部介绍完了。
@Ignore
介绍
@Ignore是偶尔且一定会用到的注解,从名字就能知道其作用是“忽略”,即忽略一个测试脚本,标注了
@Ignore注解的测试脚本将不会被执行。用法很简单,示例如下:
import org.junit.Ignore; import org.junit.Test; public class IgnoreTest { @Test @Ignore public void test() { //some test } }
运行一下
![](http://liwx2000.github.io/images/junit/ignore.png)
发现这个测试脚本的确没被运行。不过如果另外一个人来看这个脚本就会很疑惑这个测试脚本为什么要被忽略。所以必须要说明这个测试脚本被忽略的原因。那在什么地方说明呢?可以先看看
@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 ""; }
从源码来看,
@Ignore的
value()就是为这个需求准备的,可以说明测试脚本被忽略的原因。我们可以将上面的测试脚本修改如下:
import org.junit.Ignore; import org.junit.Test; public class IgnoreTest { @Test @Ignore("not ready yet!") public void test() { //some test } }
修改后就清楚多了,无论以后谁来维护这个测试脚本,都可以很直观的看到这个测试脚本是因为“还未准备好”而忽略的。
再运行一下
![](http://liwx2000.github.io/images/junit/ignore.png)
发现运行结构并没有不同,可见Eclipse并有没读取
@Ignore的
value()值,不过并不是所有的IDE都是这样,可以看下IDEA的运行效果。
![](http://liwx2000.github.io/images/junit/ignore_idea.png)
从运行结果发现,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"); } }
运行一下
![](http://liwx2000.github.io/images/junit/test_before_after.png)
只有标注了
@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
相关文章推荐
- __tostring和__invoke 方法
- 随笔
- **上海团建去哪儿**(室外版,天气不错的情况~)
- printf "%.*s"
- JSON-C 的安装与使用
- Windows环境下搭建Apache+MySQL+PHP的Web开发平台
- 《C语言及程序设计》实践参考——日期结构体
- ASP.NET MVC图片管理(上传,预览与显示)
- Android中的“再按一次返回键退出程序”实现
- 钢琴多层采样问题及解决方案
- 记住密码
- Android通过HttpURLConnection获取JSON并进行UI更新
- 【HAOI2009】【毛毛虫】【树形dp】
- IE浏览器中用Firebug调试网站的方法
- The Suspects-并查集(4)
- Leetcode 166 Fraction to Recurring Decimal
- 赋值与初始化
- mysql-5.6.25-winx64安装
- NGUI中使用U3D粒子特效
- Leetcode 187 Repeated DNA Sequences