找回密码
 立即注册
查看: 6526|回复: 90

[学术/精华文章] JUnit单元测试框架的使用

[复制链接]
发表于 2016-11-24 15:21 | 显示全部楼层 |阅读模式
我们写单元测试,一般都会用到一个或多个单元测试框架,在这里,我们介绍一下JUnit4这个测试框架。这是Java界用的最广泛,也是最基础的一个框架,其他的很多框架,包括我们后面会看到的Robolectric,都是基于或兼容JUnit4的。然而首先要解决的问题是为什么要使用单元测试框架呢?或者换句话说,单元测试框架能够为我们做什么呢?
从最基本的开始说起,假如我们有这样一个类:
public class Calculator {
public int add(int one int another) {
// 为了简单起见,暂不考虑溢出等情况。
return one + another;
}
public int multiply(int one int another) {
// 为了简单起见,暂不考虑溢出等情况。
return one * another;
}
}

如果不用单元测试框架的话,我们要怎么写测试代码呢?我们恐怕得写出下面这样的代码:
public class CalculatorTest {
public static void main(String[] args) {
Calculator calculator = new Calculator();
int sum = calculator.add(1 2);
if(sum == 3) {
System.out.println("add() works!")
} else {
System.out.println("add() does not works!")
}
int product = calculator.multiply(2 4);
if (product == 8) {
System.out.println("multiply() works!")
} else {
System.out.println("multiply() does not works!")
}
}
}

然后我们再通过某种方式,比如命令行或IDE,运行这个 CalculatorTest main 方法,在看着terminal的输出,才知道测试是通过还是失败。
试想一下,如果我们有很多的类,每个类都有很多方法,那么就要写一堆这样的代码,每个类对于一个含有 main 方法的test类,同时 main 方法里面会有一堆代码。这样既写起来痛苦,跑起来更痛苦,比如说,你怎么样一次性跑所有的测试类呢?所以,一个测试框架为我们做的最基本的事情,就是允许我们按照某种更简单的方式写测试代码,把每一个测试单元写在一个测试方法里面,然后它会自动找出所有的测试方法,并且根据你的需要,运行所有的测试方法,或者是运行单个测试方法,或者是运行部分测试方法等等,同时目前TestBird已经开发出了无需代码便可生成用例进行测试的工具,在一定程度上提升了便利性。

对于上面的 Calculator 例子,如果使用Junit的话,我们可以按照如下的方式写测试代码:
public class CalculatorTest {
@Test
public void testAdd() throws Exception {
Calculator calculator = new Calculator();
int sum = calculator.add(1 2);
Assert.assertEquals(3 sum);
}
@Test
public void testMultiply() throws Exception {
Calculator calculator = new Calculator();
int product = calculator.multiply(2 4);
Assert.assertEquals(8 product);
}
}

每一个被测试的方法( add() multiply() ),写一个对应的测试方法( testAdd() testMultiply() )。那JUnit怎么知道那些是测试方法,哪些不是呢?这个是通过前面的 @Test 注解来标志的,只要有这个注解,JUnit4就会当做是一个测试方法,方法名其实是可以随意起的。当然,名字还是应该起的更有可读性一点,让人一看就知道,这个测试方法是测试了被测的类的那个方法,或者是测试了那个功能点等等。

除了帮我们找出所有的测试方法,并且方便运行意外,单元测试框架还帮我们做了其他事情。在这个系列的第一篇文章 中我们提到,一个测试方法主要包括三个部分:
  1setup
  2、执行操作
  3、验证结果
而一个单元测试框架,可以让我们更方便的写上面的每一步的代码,尤其是第一步和第三部。比如说,在上面的 CalculatorTest 中, testAdd() testMultiply() 都有相同的setup Calculatorcalculator = new Calculator(); ,如果 Calculator 还有其他的方法的话,这行代码就得重复更多次,这种duplication是没必要的。

绝大多数单元测试框架考虑到了这一点,它们知道一个测试类的很多测试方法可能需要相同的setup,所以为我们提供了便捷方法。对于JUnit4,是通过 @Before 来实现的:
public class CalculatorTest {
Calculator mCalculator;
@Before
public void setup() {
mCalculator = new Calculator();
}
@Test
public void testAdd() throws Exception {
int sum = mCalculator.add(1 2);
assertEquals(3 sum);  //为了简洁,往往会static import Assert里面的所有方法。
}
@Test
public void testMultiply() throws Exception {
int product = mCalculator.multiply(2 4);
assertEquals(8 product);
}
}

发表于 2017-2-27 14:57 | 显示全部楼层
很不错
发表于 2017-2-27 14:14 | 显示全部楼层
好帖就是要顶
发表于 2017-2-27 14:05 | 显示全部楼层
顶顶多好
发表于 2017-2-27 14:30 | 显示全部楼层
说的非常好
发表于 2017-2-27 14:45 | 显示全部楼层
不错不错
发表于 2017-3-10 12:02 | 显示全部楼层
真心顶
发表于 2017-3-10 12:03 | 显示全部楼层
说的非常好
发表于 2017-3-10 11:47 | 显示全部楼层
很好哦
发表于 2017-3-10 12:39 | 显示全部楼层
不错不错
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-22 09:34 , Processed in 0.306519 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表