使用JUnit进行测试

JUnit 是一个 Java 语言的单元测试框架。它由肯特·贝克和埃里希·伽玛(Erich Gamma)建立,逐渐成为源于 Kent Beck 的 sUnit 的 xUnit 家族中为最成功的一个。 JUnit 有它自己的 JUnit 扩展生态圈。

JUnit 是一个回归测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量。
JUnit 提供:

  • 断言测试预期结果。
  • 测试功能共享通用的测试数据。
  • 测试套件轻松地组织和运行测试。
  • 图形和文本测试运行。

JUnit用于测试:

  • 整个对象
  • 对象的一部分 - 交互的方法或一些方法
  • 几个对象之间的互动(交互)

我们常用的它的两个特点应该就是注解和断言了吧.

一般来讲,源代码中包含明确的输入和输出的每一个方法被认为是一个可测试的单元
一般来说,有两种类型的测试,一是所谓的黑盒测试(black-box testing),另一种 便是所谓的白盒测试(white-box testing),也有称为透明盒(clear-box/glass-box)或结构(structural)测试的。
在黑盒测试中,我们的测试只针对程序的功能说明,而不管程序的具体实现,即不看程序代码。黑盒测试的最大好处是其测试过程不受实现的 潜在影响。如编码者可能对输入数据的一些不合理的假设,例如,输入参数是整数, 编码者可能假设只有正整数,而对0和负数则没作处理。如果读了代码后再去产生输入数据,很可能会受到这种错误假设的误导。黑盒测试的第二个好处是其测试数据与实现 无关,实现如有改变,只要功能说明不变,测试就保持不变。
与黑盒测试相反,白盒测试则需要审阅程序代码。其主要的目的是要产生一些输入 数据,能够测试代码的每个语句(statement coverage)、分支(decision coverage),使得每条路径都能走到,即所谓的”路径完全(path-complete)”。

每次修改程序代码后,所有的测试都需要重新运行,这通常称为回归测试(regression testing)。

版本区别

主要是 JUnit3 和 JUnit4 的使用区别,目前使用的也就这两个版本,多数还是 JUnit4,虽然现在已经有 JUnit5 了,这个…..以后再补充

  1. 在 JUnit3 中需要继承 TestCase 类,但在 JUnit4 中已经不需要继承任何类
  2. 在 JUnit3 中需要覆盖 TestCase 中的 setUp 和 tearDown 方法,其中 setUp 方法会在测试执行前被调用以完成初始化工作,而 tearDown 方法则在结束测试结果时被调用,用于释放测试使用中的资源,而在 JUnit4 中,只需要在方法前加上 @Before,就代表这个方法用于初始化操作,方法名是随意的
  3. 在 JUnit3 中对某个方法进行测试时,测试方法的命令是固定的,例如对 addBook 这个方法进行测试,需要编写名字为 tetAddBook 的测试方法,而在 JUnit4 中没有方法命令的约束,例如对 addBook 这个方法进行测试,那么可以编写 addBookToLibrary 的方法,然后在这个方法的前面加上 @Test,这就代表这个方法是测试用例中的测试方法
  4. 编写 JUnit4 的测试用例和编写一个普通的类没有什么区别,只是需要加上 Annotation 指定要测试的方法,这种松偶合的设计理念相当优秀,能很好把测试分离出来.使用 JUnit4 的 Annotation 功能,需要 JDK 1.5 或以上版本

基本使用

现在基本都是4版本了,所以我也是使用的 JUnit4,一般的习惯是新建一个 test 文件夹保存测试代码,和 src 源代码目录得以区分,最后发布的时候也好删除;要测试那个类写的测试类后面加 Test,比如 MainTest 是 Main 类的测试类,测试类中的方法也是对应的,比如测试类中的 testAdd 方法就是对原始类中 add 方法的测试方法

测试方法一般是使用 public void 来进行修饰的,并且不需要任何参数,各个方法直接也没有关联,稍微想一下就能理解这样设计是很合理的
进行测试的时候可以一起执行也可以单个方法执行,只要你加了 @Test 注解

测试 web 项目也是差不多,只是在 @BeforeClass 的方法中初始化一些对象方便下面测试方法的使用,比如初始化 Spring、Hibernate 等

常用注解

  • @Test:
    将一个普通的方法修饰成为一个测试方法
    测试方法我认为最主要的特点是不是 main 也可以执行
  • @Test(expected=XXX(异常类).class):
    确定会抛出该异常,设定后出现该异常也是绿条通过
  • @Test(timeout=毫秒 ):
    设置执行的时间,用于结束死循环或是性能测试
  • @Ignore:
    所修饰的测试方法会被测试运行器忽略
  • @RunWith:
    可以更改测试运行器默认为 org.junit.runner.Runner
  • @BeforeClass:
    他会在所有的方法运行前被执行,并且只会执行一次,static 修饰,所以是单实例
    适合配置文件的加载或者初始化
  • @AfterClass:
    他会在所有方法运行结束后被执行,只执行一次,static 修饰;一般用于释放资源、关闭连接等
  • @Before:
    会在每一个测试方法被运行前执行一次
  • @After:
    会在每一个测试方法被运行后执行一次

测试套件

测试套件简单说就是把一堆测试类整合起来,一起执行,主要使用了 @RunWith 注解更改默认的测试运行器,并且作为入口类,是不允许这个类中有其他方法的,具体的使用方法在下面:

1
2
3
4
5
@RunWith(Suite.class)  //将测试类改为测试套件类
@Suite.Suite.class({TaskTest1,TaskTest2...}) //用数组的形式将测试的类添加到测试套件中
public classSuiteTest{
//要用public修饰,套件测试类要为空。不能有方法。
}

然后可以进行参数化设置,也就是批量测试,测试一堆数据,一般放在数组或者集合里,使用前也需要使用 @RunWith 注解更改默认的测试运行器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@RunWith(Parameterized.class)
public class ParameterTest {
// 声明变量用来存预期值和结果值
int expected = 0;
int input1 = 0;
int input2 = 0;

// 声明一个返回值为 Collection 的公共静态方法,并使用 @Parameters 进行修饰
@Parameterized.Parameters
public static Collection<Object[]> t(){
return Arrays.asList(new Object[][]{
{3,2,1},
{4,2,2}
});
}

// 设置构造函数,作用就是进行循环赋值了,注意顺序和构造的数组顺序是一致的
public ParameterTest(int expected, int input1, int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
}

//测试方法
@Test
public void testAdd() {
assertEquals(expected,new MainTest().add(input1,input2));
}
}

这样 testAdd 会循环执行两次,每次的参数就是数组设置的那个

使用断言

Java 中的断言就不说了,用的很少,也是比较简单的,感兴趣的可以看看:http://lavasoft.blog.51cto.com/62575/43735/

JUnit 中的所有的断言都包含在 Assert 类中,这个类提供了很多有用的断言方法来编写测试用例,一些常用的断言看下面的表格,当然最全的还是去看官方的 API

描述 方法
检查两个变量或者等式是否平衡 void assertEquals(boolean expected, boolean actual)
检查条件为真 void assertTrue(boolean expected, boolean actual)
检查条件为假 void assertFalse(boolean condition)
检查对象不为空 void assertNotNull(Object object)
检查对象为空 void assertNull(Object object)
检查两个相关对象是否指向同一个对象 void assertSame(boolean condition)
检查两个相关对象是否不指向同一个对象 void assertNotSame(boolean condition)
检查两个数组是否相等 void assertArrayEquals(expectedArray, resultArray)

扩展

如果 JUnit 单元测试满足不了,可以试试基于此的自动化测试 TestNG,它可以配合 extentreports 来进行生成测试报告,使用 API 上跟 JUnit 倒是挺像,没什么学习难度。
当然了,JUnit 也可以使用 extentreports 来生成测试报告,其他的例如使用 ant 也可以;
PS:单元测试、回归测试、冒烟测试、自动化测试、黑盒测试、白盒测试。

喜欢就请我吃包辣条吧!

评论框加载失败,无法访问 Disqus

你可能需要魔法上网~~