确定哪些测试用例涵盖了一种方法

时间:2011-08-31 18:47:12

标签: java java-ee selenium junit code-coverage

我正在处理的当前项目要求我编写一个在Web应用程序上运行功能测试的工具,并输出方法覆盖率数据,记录哪个测试用例遍历哪个方法。

详细信息: 正在测试的Web应用程序将是在servlet容器(例如Tomcat)中运行的Java EE应用程序。功能测试将使用JUnit在Selenium中编写。一些方法将被注释,以便在部署到测试环境之前对它们进行检测。执行Selenium测试后,将记录带注释的方法的执行。

问题:这个项目的一大障碍是找到一种方法将测试用例的执行与方法的遍历联系起来,尤其是测试和应用程序在不同的JVM上运行,以及无法在应用程序中传输测试用例的名称,也无法使用线程信息将测试与代码执行相关联。

提出的解决方案:我的解决方案将包括使用执行时间:我扩展JUnit框架以记录测试用例执行的时间,并检测应用程序以节省时间遍历了该方法。我尝试使用相关性将测试用例与方法覆盖率联系起来。

预期问题:此解决方案假定测试用例按顺序执行,测试用例在下一个测试用例开始之前结束。这个假设对JUnit来说是否合理?

问题:简单地说,我是否可以对建议的解决方案提出意见,也许还有关于如何在大多数Java EE应用程序中改进并使其更强大和更具功能的建议?或者导致已经实施的解决方案?

谢谢

编辑:要添加更多需求,该工具应该能够在任何Java EE应用程序上运行,并且需要在应用程序中进行最少量的配置或更改。虽然我知道这不是一个现实的要求,但该工具至少不需要对应用程序本身进行任何大的修改,例如添加类或代码行。

2 个答案:

答案 0 :(得分:0)

您是否看过现有的覆盖工具(Cobertura,Clover,Emma,......)。我不确定其中一个是否能够将覆盖数据链接到测试用例,但至少对于开源的Cobertura,您可能能够执行以下操作:

  • 使用cobertura
  • 来修课
  • 部署已检测的网络应用
  • 启动测试套件
    • 在每次测试之后,调用Web应用程序上的URL,该URL将覆盖数据保存到刚刚运行的测试后命名的某个文件,并重置覆盖率数据
  • 在测试套件之后,为每个保存的文件生成一个cobertura报告。每个报告都将告知测试运行了哪些代码

如果您需要合并报告,我想使用cobertura API从保存的文件集中生成报告应该不会太难。

答案 1 :(得分:0)

您提出的解决方案似乎是合理的解决方案,除了通过计时将测试和请求联系起来的建议解决方案。我之前尝试过做这种事情,但它确实有效。大多数时候。除非你非常仔细地编写JUnit代码,否则你会遇到很多问题,因为两台机器之间的时间不同,或者如果你只有一台机器,只需匹配一台机器。

更好的解决方案是实现 Tomcat Valve ,您可以将其插入到webapp的server.xml的生命周期中。阀门的优势在于您可以在server.xml中定义它们,因此您根本不会触及Web应用程序。

您需要实现invoke()。最好的起点可能是AccessLogValve。这是AccessLogValve中的实现:

/**
 * Log a message summarizing the specified request and response, according
 * to the format specified by the <code>pattern</code> property.
 *
 * @param request Request being processed
 * @param response Response being processed
 *
 * @exception IOException if an input/output error has occurred
 * @exception ServletException if a servlet error has occurred
 */
public void invoke(Request request, Response response) throws IOException,
        ServletException {

    if (started && getEnabled()) {                
        // Pass this request on to the next valve in our pipeline
        long t1 = System.currentTimeMillis();

        getNext().invoke(request, response);

        long t2 = System.currentTimeMillis();
        long time = t2 - t1;

        if (logElements == null || condition != null
                && null != request.getRequest().getAttribute(condition)) {
            return;
        }

        Date date = getDate();
        StringBuffer result = new StringBuffer(128);

        for (int i = 0; i < logElements.length; i++) {
            logElements[i].addElement(result, date, request, response, time);
        }

        log(result.toString());
    } else
        getNext().invoke(request, response);       
}

所有这一切都记录了您访问它的事实。

您将实施一个新的Valve。对于您的请求,您将传递唯一ID作为URL的参数,该URL用于标识您正在运行的测试。你的阀门会在invoke()之前和之后完成所有繁重的工作。如果需要,您可以删除getNext()。invoke()的唯一参数。

要测量覆盖率,您可以使用JB Nizet建议的覆盖工具,具体取决于您传递的唯一ID。

所以,从junit开始,如果您的原始电话是

@Test void testSomething() {
    selenium.open("http://localhost/foo.jsp?bar=14");
}

您可以将其更改为:

@Test void testSomething() {
    selenium.open("http://localhost/foo.jsp?bar=14&testId=testSomething");
}

然后你在阀门中拿起参数testId。