一、问题描述:
现有Jekins+Maven+Spring项目并没有做系统的单元测试,仅有少量勤快的开发者会为业务模块添加单元测试。为实现项目系统的单元测试过程,本文将TestNG测试框架与现有项目进行整合,从而支持单元测试以及项目在构建前进行项目范围内的单元测试,从而保障项目代码质量,确保项目新的改动不影响原有代码。
二、需求:
2.1 Maven构建的Spring项目中使用TestNG进行单元测试;
2.2 Jekins构建项目时进行批量单元测试得出测试报告,单元测试通过才能成功构建;
三、实现:
3.1 在Maven项目中的pom.xml配置文件中添加如下内容:
//TestNG依赖
//5.11以上版本使用下述配置,5.11及以下版本需要指定使用jdk15版本
<dependencies>
[...]
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.8</version>
<scope>test</scope>
</dependency>
[...]
</dependencies>
//注意,若项目中已有JUnit依赖,可exclude对JUnit的依赖避免冲突
//在本项目中Elasticsearch与TestNG都存在com.google.guava依赖,从而产生冲突,通过exclude其中低版本的guava依赖解决
//若你的项目未使用JUnit、Elasticsearch则不存在冲突使用上述配置即可
<dependencies>
[...]
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.8</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
[...]
</dependencies>
//TestNG调用插件surefire
<plugin>
//TestNG的Maven调用插件
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-testng</artifactId>
<version>2.18.1</version>
</dependency>
//需要TestNG兼容JUnit时添加下述依赖,则可以通过TestNG调用JUnit测试用例
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.18.1</version>
</dependency>
</dependencies>
<configuration>
<suiteXmlFiles>
//testng.xml 为TestNG的调用xml配置,默认放在项目根目录下,其他目录需要指定路径
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
//若你的项目仅用到TestNG不使用JUnit可采用下述简化配置
<plugin>
//TestNG的Maven调用插件
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<suiteXmlFiles>
//testng.xml 为TestNG的调用xml配置,默认放在项目根目录下,其他目录需要指定路径
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
此外可以通过Maven直接配置TestNG的测试运行配置替换上述的suiteXmlFiles部分,但建议还是通过上述通过xml配置的方式把TestNG的配置放到独立的xml中来做。
更多:maven文档:Using TestNG
3.2 配置testng.xml
可通过ide工具或手动创建TestNG配置文件
//调用TestNG测试用例
<!DOCTYPE suite SYSTEM"http://testng.org/testng-1.0.dtd">
//测试套件名称,即本测试的一个名称标识
<suite name="my_test">
<test verbose="1" name="xxx" >
//指定测试该类的测试用例
<classes>
<class name="com.lianjia.configserver.SmokeTest"/>
</classes>
</test>
</suite>
//调用TestNG、JUnit测试用例
<!DOCTYPE suite SYSTEM"http://testng.org/testng-1.0.dtd">
//测试套件名称,即本测试的一个名称标识
<suite name="TestAll">
//允许JUnit测试
<test name="junitTestCases" junit="true">
//该测试覆盖的包名
<packages>
<package name="com.test.*"/>
</packages>
</test>
//TestNG测试配置
<test name="testNGTestCases">
//测试该包下的测试用例
<packages>
<package name="com.test.*"/>
</packages>
</test>
</suite>
通过@Test(groups={"公用测试组",“私用测试组”})标明测试用例属于的分组,在testng.xml中指明需要测试的分组,则可以灵活的运行指定的部分测试。
//调用TestNG分组测试
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1">
<test name="test1">
<groups>
<run>
<include name="functest" />
</run>
</groups>
<classes>
<class name="GroupTestExample" />
</classes>
</test>
</suite>
TestNG配置支持运行指定包、类的测试用例,支持排除指定包、类的测试用例,以及分组测试、并发测试、依赖测试等等,更多设置再次不赘述。
更多:testng配置文件学习
3.3 编写测试用例
3.3.1 测试目录结构
在src/test/java目录下放置项目单元测试用例、调用器;可以定义单元测试用例的基类放到service目录;单元测试用例放在usecase目录;TestNG(或JUnit)均支持java代码调用测试用例,再次称作测试用例调用器,可以放在src/test/java目录下方便位置。
3.3.2 单元测试用例
Spring提供AbstractTestNGSpringConyextTests与AbstractTransactionalTestNGSpringConyextTests(支持事务自动回滚)抽象类用于支持TestNG测试;通过@ContextConfiguration注解支持Spring配置文件的加载,则测试用例中就可以像在Spring项目中一样的使用Bean。可以通过ide直接运行测试用例类或方法或通过Maven调用或者通过下述java代码调用。
建议在每个测试用例中输出表明业务功能、测试预期、测试结果的日志输出,便于查阅定位问题。
import static org.testng.Assert.* 该声明后能够直接在代码中使用org.testng.Assert中的断言方法,简化代码。
可以通过ide直接运行测试用例类或方法或通过Maven调用或者通过下述java代码调用。
开发者开发完业务模块功能后通过调用测试用例,可以进行单元测试。
至此已经可以成功的进行单元测试了,可通过mvn test的方式调用单元测试执行;也可以通过ide直接运行指定的测试用例方法。
3.4 Jekins配置
然而单元测试的执行到目前只能通过开发人员自觉调用来确保单元测试的进行,如果一个同学新提了一新模块代码,应该进行一次覆盖范围足够涉及各影响面的单元测试,从而确保新代码未影响以前的各功能模块。本项目通过Jekins配合TestNG实现该需求,Jekins支持在构建前后调用mvn test进行单元测试,并且支持针对单元测试的多种设置,比如:单元测试不通过则构建失败、生成单元测试报告、生成单元测试覆盖率统计等等。通过集成Jekins能够保障我们通过Jekins构建的代码均进行过单元测试。
配置构建过程,构建时不进行测试,通过下述 “Invoke top-level Maven targets”过程调用测试
配置进行 mvn test,则Jekins构建时会触发Maven调用surefire插件进行TestNG测试
testng-results.xml是TestNG生成的测试报告,Jekins通过该插件拿取该报告并进行显示。若你的项目没有“Publish TestNG Results”插件可以联网下载或到Jekins官网下载插件通过“系统管理->管理插件->高级->上传”的方式离线安装该插件;若你的项目是JUnit测试的可通过“Publish JUnit Results”插件生成JUnit测试报告。
至此你已经可以通过Jekins在构建前进行单元测试,并得到单元测试报告。
单元测试未通过则会构建失败,通过查阅Console Output输出日志或TestNG报告可定位测试失败的单元测试用例。
四、总结
单元测试能够细粒度的检测项目中业务模块的质量,同时能保障项目增加新代码时对旧有模块的影响可见性,此外能为集成测试提供基础。单元测试中若用到外部依赖的接口等场景下可利用mock测试工具进行仿真。后续可以通过指定单元测试规范定义怎么样的场景、方法应该进行单元测试提高单元测试质量,此外,可以通过监控单元测试覆盖率保障单元测试覆盖范围。
参考
用于执行JUnit、TestNG测试用例的Maven插件:Maven Surefire Plugin
Maven中测试插件(surefire)的相关配置及常用方法
eclipse+maven+testng+maven-surefire-plugin使用问题全记录
maven-2 - 在使用maven-surefire-plugin的同一个项目中,如何执行JUnit和TestNG测试?