目前,常用的 Java 单元测试框架是 JUnit 和在 JUnit 基础上进一步扩展的 TestNG。为了能很好地在 Maven 中完成测试案例的执行和形成测试报告,这里介绍一下怎样在 JUnit 和 TestNG 框架下编写测试代码。
JUnit 单元测试框架
JUnit 是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架,是一个开放源代码的 Java 测试框架,可以在它的基础上编写和运行可重复的测试。
JUnit 单元测试框架有如下几个特点。
使用断言测试结果。
能共享测试数据。
方便注册和运行测试。
支持图形化测试。
JUnit 单元测试框架的安装比较简单,只需下载 JUnit 的最新压缩包在本地解压后,配置好 JUNIT_HOME 环境变量,并且在 CLASSPATH 目录中追加好 JUnit 的 jar 包就可以了。
对于 IDE 环境的用户,只需将 JUnit 的 jar 包添加到项目的 build path 中就可以了。接下来回顾梳理(以前样例中有编写,只是没有系统介绍)一下怎样在一个 Maven 项目中基于 JUnit 编写测试案例。
在 Maven 项目中,基于 JUnit 编写测试案例一般要两步:一是在 pom.xml 中添加 JUnit 依赖;二是基于 JUnit 规范编写测试代码。
如下所示是 MvnSSMDemo.Service.Impl 项目中关于 JUnit 的配置。
在 pom.xml 中的 JUnit 依赖配置。
cn.com.mvnssh.demo
MvnSSHDemo.DAO
0.0.1-SNAPSHOT
cn.com.mvn.ssh.demo
MvnSSHDemo.Service
0.0.1-SNAPSHOT
cn.com.mvn.ssm.demo
MvnSSMDemo.DAO.MyBatis
0.0.1-SNAPSHOT
test
TestUserServiceImpl.java 类代码如下所示:
package cn.com.mvn.ssh.demo.service.impl; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import cn.com.mvn.ssh.demo.entity.MvnUser; import cn.com.mvn.ssh.demo.entity.Status; import cn.com.mvn.ssh.demo.service.IUserService; import junit.framework.Assert; public class TestUserServiceImpl { private IUserService userService; private ApplicationContext ctx = null; @Before public void init() { this.ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); this.userService = (IUserService) ctx.getBean("userService"); } @Test public void testCreateUser() { MvnUser user = new MvnUser(); user.setUrAge(11); user.setUrPassword("11"); user.setUrStatus(Status.ACTIVE.getStatus()); user.setUrUserName("service1"); this.userService.createUser(user); MvnUser u = this.userService.searchUser("service1"); boolean bool = u != null && u.getUrAge() == 11 && u.getUrStatus().equals(Status.ACTIVE.getStatus()); Assert.assertTrue(bool); // 删除用户 this.userService.deleteUser(u.getUrId()); } @Test public void testEditUser() { MvnUser user = new MvnUser(); user.setUrAge(11); user.setUrPassword("11"); user.setUrStatus(Status.ACTIVE.getStatus()); user.setUrUserName("service1"); this.userService.createUser(user); MvnUser u = this.userService.searchUser("service1"); this.userService.editUser(88, Status.INACTIVE.getStatus(), u.getUrId()); u = this.userService.searchUser("service1"); Assert.assertTrue(u.getUrAge() == 88 && u.getUrStatus().equals(Status.INACTIVE.getStatus())); this.userService.deleteUser(u.getUrId()); } @Test public void testDeleteUser() { MvnUser user = new MvnUser(); user.setUrAge(11); user.setUrPassword("11"); user.setUrStatus(Status.ACTIVE.getStatus()); user.setUrUserName("service1"); this.userService.createUser(user); MvnUser u = this.userService.searchUser("service1"); this.userService.deleteUser(u.getUrId()); MvnUser u2 = this.userService.searchUser(u.getUrId()); Assert.assertTrue(u != null && u2 == null); } @Test public void testSearchUserById() { MvnUser user = this.userService.searchUser(1); Assert.assertNotNull(user); } @Test public void testSearchUserByUserName() { MvnUser user = this.userService.searchUser("zhangsan"); Assert.assertNotNull(user); } @Test public void testSearchUsers() { List userList = this.userService.searchUsers(); Assert.assertTrue(userList != null && userList.size() > 0); } @After public void destory() { this.userService = null; this.ctx = null; } }
pom.xml 中的 JUnit 依赖配置在这里就不过多重复了,这里主要说明测试代码的注意事项。
1)在 Maven 项目中,测试代码有专门的默认目录:src/test/java。
2)一般测试案例代码的包与要测试的目标类的包一样。
3)测试代码的类的命名一般是“Test+目标测试类的类名”。
4)测试代码中的方法有三种。
使用 @Before 标记的,实现初始化执行测试代码需要的资源。
使用 @Test 标记的,跟测试目标类的每个方法一一对应的测试代码。
使用 @After 标记的,完成测试后需要释放的资源。
5)测试方法的逻辑。
准备好测试数据。
根据测试工具和用户需求(目标代码的实现),确定期望结果。
执行测试方法获取实际结果。
断言实际结果是否同期望结果一致。
TestNG测试框架
TestNG 是一个测试框架,也是一个开源的自动化测试框架。很多人把 TestNG 理解成 JUnit、特别是 JUnit4 的下一代。实际上它不只是简单扩展 JUnit,它是一个灵感源于 JUnit,目的是为了更优于 JUnit 的自动测试框架,跟 JUnit 是独立的。
TestNG 消除了大部分旧框架的限制,使开发人员能够编写更加灵活、更加强大的测试程序,而且很大程度上借鉴了 Java 注解,可以使测试代码更好地同 Java 新特征整合。
相对其他测试框架,TestNG 有如下自身的特点。
使用简单的注解说明测试方法。
TestNG 使用 Java 和面向对象编程。
支持综合测试。
独立的编译时间、独立的运行测试代码的配置和数据。
灵活的运行时配置。
支持测试组设置和运行。
支持依赖测试、并行测试、负载测试和局部测试。
灵活的插件 API。
支持多线程测试。
在 Maven 项目中编写和运行 TestNG 是比较方便的。首先要移除以前在 pom 中配置的 JUnit 依赖,添加 TestNG 依赖,代码如下所示。
org.testng
testng
5.9
test
jdk15
同 JUnit 类似,TestNG 的依赖范围是 test。另外,TestNG 使用 classifier jdk15 和 jdk14 为不同的 Java 平台提供支持。
接下来在测试代码中将以前引用的 JUnit 的注解、类改成 TestNG 的。注解名称和类名都一样,只是包名不同,常用的类如下。
org.testng.annotations.Test,测试方法的注解。
org.testng.annotations.BeforeMethod,测试方法运行前执行的方法注解。
org.testng.annotations.AfterMethod,测试方法运行后执行的方法注解。
org.testng.annotations.BeforeClass,所有测试方法运行前执行的方法注解。
org.testng.annotations.AfterClass,所有测试方法运行后执行的方法注解。
org.testng.Assert,断言类。
同运行 JUnit 一样,直接使用 mvn test 命令,Maven 会自动执行符合命名模式的测试类。
TestNG 除了可以同 JUnit 一样自动执行符合命名模式的测试类外,还可以通过 testng.xml 配置文件需要运行的测试集合。例如,可以在 Maven 项目的根目录下创建一个 testng.xml 文件,代码如下:
同时,在 maven-surefire-plugin 中声明 testng.xml,代码如下:
org.apache.maven.pluginsmaven-surefire-plugin2.16testng.xml
另外,TestNG 相对 JUnit 还有一个优势,就是可以使用注解的方式对测试方法进行分组标记。在运行的时候可以指定只执行哪个组的测试方法,或哪些组的测试方法,如下所示。
@Test{groups = {"group1","group2"}}
表示将对应的方法加入 group1 组和 group2 组。
接下来,可以在 maven-surefire-plugin 插件中配置运行哪些组,代码如下:
org.apache.maven.pluginsmaven-surefire-plugin2.16group1,group3
表示执行当前 TestNG 的时候,只会执行 group1 和 group2 两个组的测试方法。