http://touchfu.iteye.com/blog/732930

现状:你是不是还在为自己的TestCase代码杂乱无章而苦恼,咎其根本还在于针对不同的用例,输入参数和mock信息的组装全部作为你的程序代码分布在各个单元测试程序中。

期望:因此为了让测试程序更加优雅的显示作为code的本质,我们需要把输入参数和mock内容与程序本身尽可能的达到松耦合的布局,即程序归程序,用例数据归用例数据。

如何:我们怎么来完成这样的一个分离动作呢,下面讲讲本人实现的基本思路。利用JUNIT4中的参数化测试为基础,通过解析文件来初始化参数信息,并对用例提供注销控制。

下面我们着重介绍下实现BaseTestCase.

  1. @RunWith(Parameterized.class)
  2. @ContextConfiguration(locations = {"XXX.xml"})
  3. public class BaseTestCase extends AbstractJUnit4SpringContextTests{
  4. /** 用例ID */
  5. protected String                     caseId;
  6. /** 描述 */
  7. protected String                     description;
  8. /** 期望值 */
  9. protected String                     expectValue;
  10. /** 测试上下文管理 */
  11. private final TestContextManager     testContextManager;
  12. public BaseTestCase(){
  13. this.testContextManager = new TestContextManager(getClass());
  14. this.caseId = caseId;
  15. this.description = description;
  16. this.expectValue = expectValue;
  17. }
  18. /**
  19. * 依靠<code>DependencyInjectionTestExecutionListener<code>完成注入上下文信息
  20. * @throws Throwable
  21. */
  22. @Before
  23. public void injectDependencies() throws Throwable {
  24. this.testContextManager.prepareTestInstance(this);
  25. }
  26. /**
  27. * 获取用例数据
  28. * @param caseFilePath
  29. * @return
  30. */
  31. protected static Collection<String[]> loadCaseData(String caseFilePath) {
  32. if (StringUtil.isBlank(caseFilePath)) {
  33. throw new IllegalArgumentException("未初始化用例文件信息");
  34. }
  35. List<String[]> caseDataList = FileParser.loadItems("cases/" + caseFilePath);
  36. if (CollectionUtils.isEmpty(caseDataList)) {
  37. throw new IllegalArgumentException("准备数据不能为空");
  38. }
  39. // 剔除第一行标题信息
  40. caseDataList.remove(0);
  41. return caseDataList;
  42. }
  43. }

由于在自己基类使用的runner为Parameterized,与使用SpringJUnit4ClassRunner的不同在于少了自动对测试上下文进行依赖注入关联,因此我们需要自己手工触发完成,大家在类源码里可以注意到这一点。主要还是依赖于DependencyInjectionTestExecutionListener完成。同时由于测试基类集成了AbstractJUnit4SpringContextTests了,在此类的源码里可以看到两个关键点DependencyInjectionTestExecutionListener和其中的ApplicationContext,因此我们在子类里不需要再自己写什么上下文的属性,也不需要再添加依赖注入的执行监听器。

下面再看下FileParser的实现

  1. /**
  2. * <p>文件解析器</p>
  3. * @author Eric.fu
  4. */
  5. public class FileParser {
  6. /** 分隔符 */
  7. private static final String SPLIT_TAG  = ",";
  8. /** 忽略标记 */
  9. private static final String IGNORE_TAG = "#";
  10. /**
  11. * 获取文件内容
  12. * @param filePath
  13. * @return
  14. */
  15. public static List<String[]> loadItems(String filePath) {
  16. List<String[]> itemList = new ArrayList<String[]>();
  17. ClassPathResource resource = new ClassPathResource(".");
  18. BufferedReader reader = null;
  19. try {
  20. String path = resource.getFile().getAbsolutePath();
  21. File file = new File(path + "/META-INF/" + filePath);
  22. reader = new BufferedReader(new FileReader(file));
  23. String tempString = null;
  24. // 一次读入一行,直到读入空为文件结束
  25. while (StringUtil.isNotBlank(tempString = reader.readLine())) {
  26. if (tempString.indexOf(IGNORE_TAG) == 0) {
  27. continue;
  28. }
  29. itemList.add(tempString.split(SPLIT_TAG));
  30. }
  31. reader.close();
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. } finally {
  35. if (reader != null) {
  36. try {
  37. reader.close();
  38. } catch (IOException e1) {
  39. }
  40. }
  41. }
  42. return itemList;
  43. }
  44. }

此类为相当普通的一段读文件的代码,这里有个特殊点在于加了一个忽略标记,用于注释用例数据,即把不跑的数据暂时注释掉,不作为读入参数。

下面再来看下一个简单的测试子类实现

  1. public class SubTestCase extends BaseTestCase {
  2. /** 测试请求 */
  3. protected String            request;
  4. /**
  5. * 构造入款支付清算
  6. */
  7. public SubTestCase(String caseId, String description, String expectValue, String request){
  8. super(caseId, description, expectValue);
  9. this.request = request;
  10. }
  11. @Parameters
  12. public static Collection<String[]> caseData() {
  13. return loadCaseData("case.csv");
  14. }
  15. /**
  16. * 执行
  17. */
  18. @Test
  19. public void execute() {
  20. Assert.notNull(request);
  21. }
  22. }

在子类里通过构造方法初始化参数,参数数据来源为case.csv文件。

文件格式为caseId,description,expectValue,request

本文主要介绍的利用JUNIT4中的参数化测试来完成程序与测试数据的分离,当然如果你用的testNG,则可以用更优雅的provider来完成此项工作。在测试用例中除了让数据与程序分离还是不够的,还需要将mock部分也分离出去,这样才能更好的达到扩展的效果。

Junit4参数化测试实现程序与用例数据分离的更多相关文章

  1. JUnit4参数化测试实例

    在JUnit中,可以同时使用@RunWith 和 @parameter 注解来为单元测试传递参数. 注意: 在Eclipse中因为版本问题,可能无法使用@parameters(name = " ...

  2. 同时使用Junit4的@Parameterized参数化测试和Spring容器

    转载:http://www.jianshu.com/p/d191fe54915f 整合Spring容器 @SpringApplicationConfiguration(classes = Applic ...

  3. 用JUnit4进行参数化测试

    参数化测试是一个JUnit 3不具备的功能. 基本使用方法 @RunWith 当类被@RunWith注解修饰,或者类继承了一个被该注解修饰的类,JUnit将会使用这个注解所指明的运行器(runner) ...

  4. Junit4进行参数化测试

    @RunWith, 当类被@RunWith注解修饰,或者类继承了一个被该注解修饰的类,JUnit将会使用这个注解所指明的运行器(runner)来运行测试,而不是JUnit默认的运行器. 要进行参数化测 ...

  5. 参数化测试与Mock

    参数化测试与Mock 转载自https://blog.csdn.net/sunliduan/article/details/42026509 单元测试概念 说到测试,大家都不会陌生,从我们开始学习编程 ...

  6. 计算某天的下一天:黑盒测试之等价类划分+JUnit参数化测试

    题目要求 测试以下程序:该程序有三个输入变量month.day.year(month.day和year均为整数值,并且满足:1≤month≤12.1≤day≤31和1900≤year≤2050),分别 ...

  7. Google C++单元测试框架GoogleTest---值参数化测试

    值参数化测试允许您使用不同的参数测试代码,而无需编写同一测试的多个副本. 假设您为代码编写测试,然后意识到您的代码受到布尔参数的影响. TEST(MyCodeTest, TestFoo) { // A ...

  8. MSTest不支持参数化测试的解决方案

    之前的项目中做单元测试一直用的是NUnit,这次做新项目,负责人要求统一用MsTest,理由是MsTest是Visual Studio内置的.用就用吧,我没什么意见.不过用了两天,我就发现一个大问题: ...

  9. 参数化测试--sheet表的应用

    自动化测试对录制和编辑好的测试步骤进行回放,这种是线性的自动化测试方式,其缺点是明显的,就是其测试覆盖面比较低.测试回放的只是录制时做出的界面操作,以及输入的测试数据,或者是脚本编辑时指定的界面操作和 ...

随机推荐

  1. arcgis制作兴趣点分布图

    数据准备: 1.矢量:芜湖市区行政区.shp  企业分布点.shp 2.影像:Landsat 8 软件:arcgis 10.3  Envi4.8 目的:制作一幅以市区行政区为底图的企业分布点的图,同时 ...

  2. http 学习 1-2 chapter2-URL与资源

    URL是因特网资源的标准化名称.URL指向每一条电子信息,告诉他们位于何处,以及如何与之进行交互. URL语法,以及各种URL组件的含义及其所做的工作. 很多Web客户端都支持额URL快捷方式,包括相 ...

  3. Android Studio Eclipse Code Formatter

    在从Eclipse转到Android Studio上开发后,如果还想继续使用在Eclipse上制定的自定义的Code Formatter的话,需要按如下步骤操作:1.进入Settings界面,如果能看 ...

  4. POJ 3009 DFS+剪枝

    POJ3009 DFS+剪枝 原题: Curling 2.0 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16280 Acce ...

  5. HTML5 3D爱心动画 晚来的七夕礼物

    在线演示源码下载 这么好看的HTML5爱心动画,我们当然要把源代码分享给大家,下面是小编整理的源代码,主要是HTML代码和CSS代码. HTML代码: <div class=’heart3d’& ...

  6. python学习之关键字

    1.assert 语句形式:assert 布尔表达式[,msg] 解释:assert是检验一个表达式是否为真.若不为真,则触发一个错误. 例如: assert False assert 1==2 as ...

  7. 单例模式读取properties配置文件中的信息

    public class ConfigManager {    private static ConfigManager config = null;    //创建Properties文件  读取配 ...

  8. <%@page contentType="text/html;charset=gbk"%>与<meta http-equiv="Content-Type" content="text/html; charset=GBK">区别

    前一个是在服务端起作用,是告诉应用服务器采用何种编码输出JSP文件流,后一个是在客户端起作用,是告诉浏览器是采用何种编码方式显示HTML页面.     前者由jsp引擎对输出内容进行编码, 后者将由I ...

  9. 命名空间System.Threading命名空间的同步锁 Monitor类

    官方备注: Monitor类通过向单个线程授予对象所来控制对对象的访问.对象所提供限制访问代码块的能力.当一个线程拥有对象的锁时,其他任何线程都不能获取该锁.还可以使用Monitor来确保不会允许其他 ...

  10. Extnet Direct 提交后台事件文件下载设置

    App.direct.MasterData.Export(App.tfSearch.getValue(), {                    isUpload: true            ...