单元和集成测试的代码覆盖率

我最近在一个宠物项目中着手构建自动化的UI(集成)测试以及普通的单元测试。 我想将所有这些集成到我的Maven构建中,并提供代码覆盖率报告,以便我可以了解测试覆盖率不足的区域。 我不仅发布了项目的源代码,还整理了一个简单的示例来演示如何获得所有这些设置。 因此,如果您希望集成maven , junit , webdriver (现在为selenium)和emma ,请继续阅读以了解我的工作方式。

首先,所有的源代码都可以在github上找到: https : //github.com/activelylazy/coverage-example 。 我将显示关键片段,但显然有很多细节被忽略了(希望如此)不相关。

示例应用

该示例应用程序不是打破传统,而是一个简单的,即使有点人为的问候世界:

怎么运行的

起始页面是指向hello world页面的简单链接:

<h1>Example app</h1>
<p>See the <a id="messageLink" href="helloWorld.html">message</a></p>

Hello World页面仅显示以下消息:

<h1>Example app</h1>
<p id="message"><c:out value="${message}"/></p>

hello world控制器渲染视图,并传递消息:

public class HelloWorldController extends ParameterizableViewController {// Our message factoryprivate MessageFactory messageFactory;@Overrideprotected ModelAndView handleRequestInternal(HttpServletRequest request,HttpServletResponse response) throws Exception {// Get the success viewModelAndView mav = super.handleRequestInternal(request, response);// Add our messagemav.addObject("message",messageFactory.createMessage());return mav;}@Autowiredpublic void setMessageFactory(MessageFactory messageFactory) {this.messageFactory = messageFactory;}
}

最后,MessageFactory仅返回硬编码的消息:

public String createMessage() {return "Hello world";
}

单元测试

我们定义了一个简单的单元测试,以验证MessageFactory的行为是否符合预期:

public class MessageFactoryTest {// The message factoryprivate MessageFactory messageFactory;@Testpublic void testCreateMessage() {assertEquals("Hello world",messageFactory.createMessage());}@Autowiredpublic void setMessageFactory(MessageFactory messageFactory) {this.messageFactory = messageFactory;}
}

建立

一个基本的maven pom文件足以构建此文件并运行单元测试。 至此,我们有了一个正在运行的应用程序,并对我们可以构建和运行的核心功能(例如它)进行了单元测试。

<project><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>helloworld</artifactId><packaging>war</packaging><version>1.0-SNAPSHOT</version><name>helloworld Maven Webapp</name><build><finalName>helloworld</finalName></build><dependencies>...omitted...</dependencies>
</project>

代码覆盖率

现在,我们集成Emma,以便获得一些代码覆盖率报告。 首先,我们定义一个新的Maven配置文件,这使我们可以控制是否在任何给定的版本上使用emma。

<profile><id>with-emma</id><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>emma-maven-plugin</artifactId><inherited>true</inherited><executions><execution><id>instrument</id><phase>process-test-classes</phase><goals><goal>instrument</goal></goals></execution></executions></plugin></plugins></build>
</profile>

这只是在Maven“过程测试类”阶段调用“仪器”目标。 即,一旦我们编译了类文件,请使用emma对其进行检测。 我们可以通过使用新的配置文件调用Maven来运行它:

mvn clean install -Pwith-emma

构建完成后,我们可以运行Emma生成代码覆盖率报告:
在Windows上:

java -cp %USERPROFILE%/.m2/repository/emma/emma/2.0.5312/emma-2.0.5312.jar emma report -r xml,html -in coverage.ec -in target/coverage.em

在Linux上:

java -cp ~/.m2/repository/emma/emma/2.0.5312/emma-2.0.5312.jar emma report -r xml,html -in coverage.ec -in target/coverage.em

现在,我们可以在coverage / index.html中查看HTML覆盖率报告。 在这一点上,它表明我们有50%的测试覆盖率(按类)。 MessageFactory已完全覆盖,但是HelloWorldController根本没有任何测试。

整合测试

为了测试我们的控制器和JSP,我们将使用WebDriver创建一个简单的集成测试。 这是一个恰巧启动浏览器的JUnit测试。

public class HelloWorldIntegrationTest {// The webdriverprivate static WebDriver driver;@BeforeClasspublic static void initWebDriver() {driver = new FirefoxDriver();}@AfterClasspublic static void stopSeleniumClent() {try {driver.close();driver.quit();} catch( Throwable t ) {// Catch error & log, not critical for testsSystem.err.println("Error stopping driver: "+t.getMessage());t.printStackTrace(System.err);}}@Testpublic void testHelloWorld() {// Start from the homepagedriver.get("http://localhost:9080/helloworld/");HomePage homePage = new HomePage(driver);HelloWorldPage helloWorldPage = homePage.clickMessageLink();assertEquals("Hello world",helloWorldPage.getMessage());}
}

第4-18行只是在测试之前启动Web驱动程序,并在测试完成后将其关闭(关闭浏览器窗口)。
在第22行,我们使用硬编码的URL导航到主页。
在第23行,我们初始化主页的Web Driver 页面对象 。 这封装了页面工作方式的所有细节,从而使测试可以与页面进行功能上的交互,而无需担心机制(使用哪些元素等)。 在第24行,我们使用主页对象单击“消息”链接; 这将导航到hello world页面。 在第25行,我们确认Hello World页面上显示的消息是我们期望的。 注意:我正在使用页面对象将测试规范 (做什么)与测试实现 (如何做)分开。 有关为什么这很重要的更多信息,请参见防止测试变脆 。

主页

主页对象非常简单:

public HelloWorldPage clickMessageLink() {driver.findElement(By.id("messageLink")).click();return new HelloWorldPage(driver);
}

HelloWorldPage

hello world页面同样简单:

public String getMessage() {return driver.findElement(By.id("message")).getText();
}

运行集成测试

要在我们的Maven构建过程中运行集成测试,我们需要进行一些更改。 首先,我们需要从单元测试阶段中排除集成测试:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId>...<configuration>...<excludes><exclude>**/*IntegrationTest.java</exclude><exclude>**/common/*</exclude></excludes></configuration>
</plugin>

然后,我们定义一个新的配置文件,因此我们可以选择运行集成测试:

<profile><id>with-integration-tests</id><build><plugins><plugin><groupId>org.mortbay.jetty</groupId><artifactId>maven-jetty-plugin</artifactId><version>6.1.22</version><configuration><scanIntervalSeconds>5</scanIntervalSeconds><stopPort>9966</stopPort><stopKey>foo</stopKey><connectors><connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"><port>9080</port><maxIdleTime>60000</maxIdleTime></connector></connectors></configuration><executions><execution><id>start-jetty</id><phase>pre-integration-test</phase><goals><goal>run</goal></goals><configuration><daemon>true</daemon></configuration></execution><execution><id>stop-jetty</id><phase>post-integration-test</phase><goals><goal>stop</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.5</version><inherited>true</inherited><executions><execution><id>integration-tests</id><phase>integration-test</phase><goals><goal>test</goal></goals><configuration><excludes><exclude>**/common/*</exclude></excludes><includes><include>**/*IntegrationTest.java</include></includes></configuration></execution></executions></plugin></plugins></build>
</profile>
<个人资料>

<id> with-integration-tests </ id>

<内部版本>

<插件>

<插件>

<groupId> org.mortbay.jetty </ groupId>

<artifactId> maven-jetty-plugin </ artifactId>

<version> 6.1.22 </ version>

<配置>

<scanIntervalSeconds> 5 </ scanIntervalSeconds>

<stopPort> 9966 </ stopPort>

<stopKey> foo </ stopKey>

<连接器>

<连接器实现=” org.mortbay.jetty.nio.SelectChannelConnector”>

<port> $ {test.server.port} </ port>

<maxIdleTime> 60000 </ maxIdleTime>

</ connector>

</ connectors>

</ configuration>

<执行>

<执行>

<id>开始码头</ id>

<phase>集成前测试</ phase>

<目标>

<goal>运行</ goal>

</ goals>

<配置>

<daemon> true </ daemon>

</ configuration>

</ execution>

<执行>

<id>停止码头</ id>

<phase>集成后测试</ phase>

<目标>

<goal>停止</ goal>

</ goals>

</ execution>

</ executions>

</ plugin>

<插件>

<groupId> org.apache.maven.plugins </ groupId>

<artifactId> maven-surefire-plugin </ artifactId>

<version> 2.5 </ version>

<inherited> true </ inherited>

<执行>

<执行>

<id>集成测试</ id>

<phase>集成测试</ phase>

<目标>

<goal>测试</ goal>

</ goals>

<配置>

<排除>

<exclude> ** / common / * </ exclude>

</ excludes>

<包括>

<include> ** / * IntegrationTest.java </ include>

</ includes>

</ configuration>

</ execution>

</ executions>

</ plugin>

</ plugins>

</ build>

</ profile>

这可能看起来很复杂,但实际上我们只是在配置码头来运行我们的集成测试。 然后配置如何自行运行集成测试。
在9-19行中,配置码头-要继续运行的港口以及如何停止码头。
21-30行配置了码头以在Maven构建的“集成前测试”阶段运行。 31-37行配置了要在Maven构建的“集成后测试”阶段停止的码头。 在第40-62行中,我们再次使用maven-surefire-plugin,这次是在构建的“集成测试”阶段运行,仅运行我们的集成测试类。

我们可以使用以下命令运行此构建:

mvn clean install -Pwith-emma -Pwith-integration-tests

这将构建所有内容,运行单元测试,构建战争,启动码头以主持战争,运行我们的集成测试(在其余运行时您将看到一个Firefox窗口弹出),然后关闭码头。 因为战争是通过检测类构建的,所以在我们运行集成测试时,Emma还会跟踪代码覆盖率。

现在,我们可以构建应用程序,运行单元测试和集成测试,收集组合的代码覆盖率报告。 如果我们重新运行emma报告并检查代码覆盖率,我们现在将看到我们具有100%的测试覆盖率-因为控制器也已通过测试覆盖。

问题

有哪些未解决的问题,可以做哪些进一步的扩展?

  • 该构建会生成一个已检测到的WAR –这意味着您需要运行第二个构建(没有emma)才能获得可用于生产的构建。
  • 集成测试对Jetty配置为启动的端口进行硬编码。 意味着测试不能直接在Eclipse中运行。 可以传入此端口,默认为8080,这样集成测试就可以通过maven构建在Eclipse中运行。
  • 在构建服务器上运行时,您可能不希望Firefox随机弹出(如果甚至安装了X); 因此,运行xvfb是一个好主意。 可以将maven设置为在集成测试之前和之后启动和停止xvfb。

参考: 单元和集成测试的代码覆盖范围以及Actively Lazy博客的JCG合作伙伴 Dave提供的信息

相关文章 :
  • 任何软件开发公司应存在的服务,实践和工具,第1部分
  • 任何软件开发公司应存在的服务,实践和工具,第2部分
  • 这是在您的业务逻辑之前!
  • 您的代码中有几个错误?
  • 使用FindBugs产生更少的错误代码
  • Java工具:源代码优化和分析
  • 每个程序员都应该知道的事情
  • 为什么自动化测试可以提高您的开发速度

翻译自: https://www.javacodegeeks.com/2011/10/code-coverage-with-unit-integration.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python学生分布_Python数据分析实战之分布分析

前言 本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。 作者&#xff1a;严小样儿 分布分析法&#xff0c;一般是根据分析目的&#xff0c;将数据进行分组&#xff0c;研究各组别分布规律的一种分析方法。…

hls fifo_HLS优化方法DATAFLOW你用了吗

上期内容&#xff1a;异步跨时钟域电路该怎么约束DATAFLOW作为HLS的一种优化方法&#xff0c;对于改善吞吐率(Throughput)、降低延迟(Latency)非常有效。DATAFLOW的作用对象DATAFLOW可以作用于函数&#xff0c;也可以作用于for循环。如下图所示(图片来源Figure62, Figure 63, u…

在Hibernate,EhCache,Quartz,DBCP和Spring中启用JMX

继续使用JMX的过程&#xff08;请参阅&#xff1a; 人类JMX &#xff09;&#xff0c;我们将学习如何在一些流行的框架中启用JMX支持&#xff08;通常是统计和监视功能&#xff09;。 这些信息大部分都可以在项目的主页上找到&#xff0c;但是我决定在收集这些信息的同时&#…

400多万微信用户如何“变现”?凯叔说了五大秘诀与教训

凯叔&#xff0c;原名王凯&#xff0c;自媒体“凯叔讲故事”创始人&#xff0c;近日在狮享家班委会上做了分享&#xff0c;全是实实在在的实验性方法论。以下是王凯的分享内容&#xff0c;整理 / 垅青 我讲的主题叫“基于内容的MVP探索”&#xff0c;MVP是什么东西&#xff1f;…

使用模拟的单元测试–测试技术5

我的最后一个博客是有关测试代码方法的一系列博客中的第四篇&#xff0c;演示了如何创建使用存根对象隔离测试对象的单元测试。 今天的博客探讨了有时被视为对立的技术&#xff1a;使用模拟对象进行单元测试。 同样&#xff0c;我使用了从数据库检索地址的简单方案&#xff1a;…

多线程中的volatile和伪共享

伪共享 false sharing&#xff0c;顾名思义&#xff0c;“伪共享”就是“其实不是共享”。那什么是“共享”&#xff1f;多CPU同时访问同一块内存区域就是“共享”&#xff0c;就会产生冲突&#xff0c;需要控制协议来协调访问。会引起“共享”的最小内存区域大小就是一个cache…

C语言代码规范(一)缩进与换行

一、缩进的空格数为4个。最好配置代码编辑器将TAB键设置为空格替换&#xff0c;避免出现另一个编辑器打开时格式变乱的情况。 例如Notepad设置 KEIL设置 二、“{” 和 “}”各自独占一行。 不规范例子&#xff1a; for(i 0; i < student_num; i) { if((score[i] > 0…

armv7 cortex a系列编程手册_AWTK能为现代GUI编程带来何种改变?

AWTK是一个伸缩性极强的嵌入式图形框架&#xff0c;它的诞生会给GUI编程研发工程师带来哪些改变&#xff1f;AWTK是一个伸缩性极强的嵌入式图形框架&#xff0c;可在Cortex-M3这样低端的单片机上运行&#xff0c;也可以在Cortex-A7/A8/A9等处理器&#xff0c;甚至DSP以及X86处理…

为什么要编写单元测试–测试技巧8

我对最近在“您应该测试什么”上的博客有很多反应&#xff0c;有些人出于各种原因同意我的想法&#xff0c;另一些人则认为建议某些类可能不需要单元测试是非常危险的。 已经处理了什么测试&#xff0c;今天的博客涉及为什么要编写单元测试&#xff0c;而今天的示例代码是基于一…

c++ 多重背包状态转移方程_动态规划入门——详解经典问题零一背包

本文始发于个人公众号&#xff1a;TechFlow&#xff0c;原创不易&#xff0c;求个关注今天是周三算法与数据结构专题的第12篇文章&#xff0c;动态规划之零一背包问题。在之前的文章当中&#xff0c;我们一起探讨了二分、贪心、排序和搜索算法&#xff0c;今天我们来看另一个非…

python定义一个圆_Python-矩形和圆形

原博文 2019-11-11 12:34 − Exercise 15.1. 定义一个叫做Circle 类&#xff0c;类的属性是圆心 (center) 和半径 (radius) , 其中&#xff0c;圆心 (center) 是一个 Point 类&#xff0c;而半径 (radius) 是一个数字。 实例化一个圆心 (center) 为 (150, 100) &#xff0c;半…

STM32F1笔记(一)GPIO输出

GPIO&#xff1a;General Purpose Input Output &#xff08;通用输入/输出&#xff09;。 GPIO最经典应用&#xff1a;LED灯。 先看电路。声明&#xff1a;参考正点原子战舰开发板。 与LED串联的电阻称为限流电阻。 限流电阻计算公式&#xff1a;R(U-LED压降)/20ma。 U为LE…

dataframe转化为array_【Python专栏】12 种高效 Numpy 和 Pandas 函数为你加速分析

来源&#xff1a;机器之心编译&#xff1a;Jamin、杜伟、张倩我们都知道&#xff0c;Numpy 是 Python 环境下的扩展程序库&#xff0c;支持大量的维度数组和矩阵运算&#xff1b;Pandas 也是 Python 环境下的数据操作和分析软件包&#xff0c;以及强大的数据分析库。二者在日常…

具有GlassFish和一致性的高性能JPA –第1部分

您以前听说过连贯性吗&#xff1f; 大概是。 它是那些著名的内存网格解决方案之一&#xff0c;该解决方案承诺了超快的数据访问速度和对经常使用的数据的无限空间。 一些众所周知的竞争对手是Infinispan &#xff0c; Memcached和Terracotta Ehcache 。 它们都很棒&#xff0c;…

boost原理与sklearn源码_机器学习sklearn系列之决策树

一、 Sklearn库 Scikit learn 也简称 sklearn, 自2007年发布以来&#xff0c;scikit-learn已经成为Python重要的机器学习库了。支持包括分类、回归、降维和聚类四大机器学习算法。还包含了特征提取、数据处理和模型评估三大模块。sklearn是Scipy的扩展&#xff0c;建立在NumPy和…

STM32F1笔记(二)GPIO输入

STM32 GPIO输入的经典应用是按键。 先看电路。声明&#xff1a;参考正点原子战舰开发板。 在这里可以看到&#xff0c;KEY_UP按键是高电平有效的&#xff0c;即当按下该按键时&#xff0c;GPIO读到高电平。 KEY0/1/2是低电平有效的&#xff0c;即当按下该按键时&#xff0c;G…

STM32F1笔记(三)UART/USART

UART&#xff1a;Universal Asynchronous Receiver/Transmitter&#xff08;通用异步收/发器&#xff09; USART&#xff1a;Universal Synchronous/Asynchronous Receiver/Transmitter&#xff08;通用同步/异步串行收/发器&#xff09; 从命名即可看出USART就是UART的基础上…

python安装界面翻译_python环境搭建

如果想要运行python需要有解释器和编辑器。 什么是解释器 解释器我们可以把它理解成翻译官&#xff0c;它是将我们写的python代码翻译成计算机能够懂得机器语言。 然后计算机收到解释器的命令来干活&#xff0c;最终再将结果反馈在解释器中。 解释器推荐使用anaconda3 什么是an…

进阶篇-用户界面:4.Android中常用组件

1.下拉菜单 在Web开发中&#xff0c;HTML提供了下拉列表的实现&#xff0c;就是使用<select>元素实现一个下拉列表&#xff0c;在其中每个下拉列表项使用<option>表示即可。这是在Web开发中一个必不可少的交互性组件&#xff0c;而在Android中的对应实现就是Spinne…

http的“无连接”指的是_http协议无状态中的 quot;状态quot; 到底指的是什么?...

引子&#xff1a;最近在好好了解http&#xff0c;发现对介绍http的第一句话【http协议是无状态的&#xff0c;无连接的】就无法理解了&#xff1a;无状态的【状态】到底指的是什么&#xff1f;&#xff01;找了很多资料不仅没有发现有一针见血正面回答这个问题的&#xff0c;而…