现状:你是不是还在为自己的TestCase代码杂乱无章而苦恼,咎其根本还在于针对不同的用例,输入参数和mock信息的组装全部作为你的程序代码分布在各个单元测试程序中。
期望:因此为了让测试程序更加优雅的显示作为code的本质,我们需要把输入参数和mock内容与程序本身尽可能的达到松耦合的布局,即程序归程序,用例数据归用例数据。
如何:我们怎么来完成这样的一个分离动作呢,下面讲讲本人实现的基本思路。利用JUNIT4中的参数化测试为基础,通过解析文件来初始化参数信息,并对用例提供注销控制。
下面我们着重介绍下实现BaseTestCase.
@RunWith(Parameterized.class)
@ContextConfiguration(locations = {"XXX.xml"})
public class BaseTestCase extends AbstractJUnit4SpringContextTests{
/** 用例ID */
protected String caseId;
/** 描述 */
protected String description;
/** 期望值 */
protected String expectValue;
/** 测试上下文管理 */
private final TestContextManager testContextManager;
public BaseTestCase(){
this.testContextManager = new TestContextManager(getClass());
this.caseId = caseId;
this.description = description;
this.expectValue = expectValue;
}
/**
* 依靠<code>DependencyInjectionTestExecutionListener<code>完成注入上下文信息
* @throws Throwable
*/
@Before
public void injectDependencies() throws Throwable {
this.testContextManager.prepareTestInstance(this);
}
/**
* 获取用例数据
* @param caseFilePath
* @return
*/
protected static Collection<String[]> loadCaseData(String caseFilePath) {
if (StringUtil.isBlank(caseFilePath)) {
throw new IllegalArgumentException("未初始化用例文件信息");
}
List<String[]> caseDataList = FileParser.loadItems("cases/" + caseFilePath);
if (CollectionUtils.isEmpty(caseDataList)) {
throw new IllegalArgumentException("准备数据不能为空");
}
// 剔除第一行标题信息
caseDataList.remove(0);
return caseDataList;
}
}
由于在自己基类使用的runner为Parameterized,与使用SpringJUnit4ClassRunner的不同在于少了自动对测试上下文进行依赖注入关联,因此我们需要自己手工触发完成,大家在类源码里可以注意到这一点。主要还是依赖于DependencyInjectionTestExecutionListener完成。同时由于测试基类集成了AbstractJUnit4SpringContextTests了,在此类的源码里可以看到两个关键点DependencyInjectionTestExecutionListener和其中的ApplicationContext,因此我们在子类里不需要再自己写什么上下文的属性,也不需要再添加依赖注入的执行监听器。
下面再看下FileParser的实现
/**
* <p>文件解析器</p>
* @author Eric.fu
*/
public class FileParser {
/** 分隔符 */
private static final String SPLIT_TAG = ",";
/** 忽略标记 */
private static final String IGNORE_TAG = "#";
/**
* 获取文件内容
* @param filePath
* @return
*/
public static List<String[]> loadItems(String filePath) {
List<String[]> itemList = new ArrayList<String[]>();
ClassPathResource resource = new ClassPathResource(".");
BufferedReader reader = null;
try {
String path = resource.getFile().getAbsolutePath();
File file = new File(path + "/META-INF/" + filePath);
reader = new BufferedReader(new FileReader(file));
String tempString = null;
// 一次读入一行,直到读入空为文件结束
while (StringUtil.isNotBlank(tempString = reader.readLine())) {
if (tempString.indexOf(IGNORE_TAG) == 0) {
continue;
}
itemList.add(tempString.split(SPLIT_TAG));
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
return itemList;
}
}
此类为相当普通的一段读文件的代码,这里有个特殊点在于加了一个忽略标记,用于注释用例数据,即把不跑的数据暂时注释掉,不作为读入参数。
下面再来看下一个简单的测试子类实现
public class SubTestCase extends BaseTestCase {
/** 测试请求 */
protected String request;
/**
* 构造入款支付清算
*/
public SubTestCase(String caseId, String description, String expectValue, String request){
super(caseId, description, expectValue);
this.request = request;
}
@Parameters
public static Collection<String[]> caseData() {
return loadCaseData("case.csv");
}
/**
* 执行
*/
@Test
public void execute() {
Assert.notNull(request);
}
}
在子类里通过构造方法初始化参数,参数数据来源为case.csv文件。
文件格式为caseId,description,expectValue,request
本文主要介绍的利用JUNIT4中的参数化测试来完成程序与测试数据的分离,当然如果你用的testNG,则可以用更优雅的provider来完成此项工作。在测试用例中除了让数据与程序分离还是不够的,还需要将mock部分也分离出去,这样才能更好的达到扩展的效果。
分享到:
相关推荐
而Junit参数化测试是JUnit框架的一个强大特性,允许我们使用不同的输入数据多次执行同一个测试用例,这对于验证方法在各种边界条件或输入组合下的行为非常有用。下面我们将详细探讨Junit参数化测试的概念、使用方法...
3. **输入数据**:测试时需要的输入参数和数据。 4. **执行条件**:测试执行的前置条件和顺序。 5. **预期结果**:测试成功时应该得到的输出或系统状态。 6. **测试步骤**:详细的操作步骤,指导测试人员如何进行...
EvoSuite是一个为Java程序自动生成单元测试的工具,它利用进化算法来探索程序的执行路径并生成测试用例,以此来达到较高的代码覆盖率。EvoSuite可以集成到持续集成流程中,与SonarQube结合使用,可以在开发过程中...
Junit4是一款广泛使用的Java单元测试框架,它使得开发者能够方便地编写和运行测试用例,从而验证代码的正确性。本教程将深入探讨Junit4测试用例的使用,帮助你理解和实践其核心概念。 一、Junit4简介 Junit4是JUnit...
* Use parameterized tests:使用参数化测试 * Use mocking frameworks:使用模拟框架 通过本教程,您已经掌握了使用 JUnit 创建测试用例的基础知识。JUnit 是一个强大且灵活的测试框架,帮助您编写可靠的测试用例...
本教程将深入探讨如何利用这些技术实现接口自动化测试用例的管理。 首先,我们要理解接口自动化测试的基本概念。接口自动化测试主要是对应用程序的API(Application Programming Interface)进行测试,确保它们按照...
为了更好地组织测试,可以使用`@RunWith`注解配合测试运行器(如`Parameterized`或`Suite`),实现参数化测试和组合测试。参数化测试允许为同一个测试方法提供多组输入数据,而`Suite`则能将多个测试类组合成一个...
在Selenium和TestNG中,可以通过参数化测试实现数据驱动。例如,我们可以创建一个数据源(如CSV文件或数据库),然后在TestNG的测试方法中引用这些数据,使每个数据行对应一次测试执行。 在压缩包中的"selenium用例...
3. 参数化测试:`@Parameterized`允许通过参数集来运行相同的测试逻辑,适用于数据驱动测试。 4. 集成测试:Junit可以与其他工具(如Mockito、PowerMock)结合,进行模拟对象和静态方法的测试,以及数据库和网络...
JUnit支持注解、参数化测试、异常测试等特性,使得编写和执行单元测试变得更加简单。 4. **自动化测试**:自动化测试是指通过软件工具自动执行预先编写的测试脚本来检查程序功能是否正确的一种方法。相比手动测试,...
6. **参数化测试**:JUnit的`@Parameterized`测试允许你为同一个测试方法提供多组输入数据,验证不同场景下的代码行为。 7. **测试超时**:可以使用`@Test`注解的`timeout`属性设置测试方法的执行时间限制,防止无...
此外,`@Ignore`注解可以用来临时忽略某个测试方法,`@RunWith`可以指定测试运行器,比如用于参数化测试的`Parameterized`运行器。 在压缩包中的"Test"可能包含了多个这样的测试类,每个类代表不同的测试场景,通过...
5. **参数化测试**:`@Parameterized`测试可以使用不同的参数多次运行同一个测试方法,这对于测试多种输入情况非常有用。 6. **超时测试**:`@Test(timeout = 1000)`可以设置测试方法的执行时间限制,超过设定时间...
此外,JUnit4还支持如@Before和@After这样的生命周期方法,可以在每次测试前后进行必要的初始化和清理工作。 总结来说,这个实验通过JUnit4结合黑盒测试的等价类划分和边界值分析,以及白盒测试的路径覆盖,全面地...
除此之外,JUnit4还支持参数化测试,通过`@Parameters`注解和`parameters()`方法可以为测试方法提供多组输入数据,实现对同一函数的多次测试。这对于测试具有多种输入情况的函数非常有用。 异常测试也是JUnit4的一...
在处理多参数测试时,JUnit提供了一个名为`@Parameterized`的注解,用于创建参数化的测试类。通过这个注解,我们可以为每个测试方法传入一组或多组参数,从而实现对多种情况的覆盖。 FizzBuzz问题是软件面试中常见...
为了有效地管理和利用这些测试用例数据,通常会采用一些工具或框架,如TestNG、JUnit等,它们能帮助我们组织和自动化测试用例的执行,生成详细的测试报告,便于分析测试结果。同时,版本控制系统如Git也常用于跟踪和...
其次,JUnit4支持参数化测试,这意味着一个测试方法可以使用不同的参数多次执行。`@Parameters`注解用于提供参数数据,`@Parameterized.Parameters`方法返回一个包含参数的集合。 异常测试也是JUnit4的一个重要特性...