1. 程式人生 > >Cobertura 統計多模組maven專案測試覆蓋率

Cobertura 統計多模組maven專案測試覆蓋率

Cobertura 統計單元測試覆蓋率的機制:執行類,並在一個log檔案中記錄哪一行被執行,然後將原始碼和log檔案進行比對。

1. 簡單的情況:單模組maven專案

專案結構


原始碼 src/main/java/se/sigma/calculator/Calculator.java

package se.sigma.calculator;

public class Calculator {
    public int nextFibonacci(int a, int b) {
        return a + b;
    }
}
單元測試src/test/java/se/sigma/calculator/CalculatorTest.java
package se.sigma.calculator;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

public class CalculatorTest {

    @Test
    public void shouldCalculateFibonacci() {
        Calculator calculator = new Calculator();
        int expected = 13;
        int actual = calculator.nextFibonacci(5, 8);

        assertThat(actual, is(expected));
    }
}

我們新增maven cobetura外掛

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>se.thinkcode</groupId>
    <artifactId>one-module-example</artifactId>
    <version>1.0</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>cobertura-maven-plugin</artifactId>
                <version>2.5.1</version>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>cobertura</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>
關鍵部分是cobertura-maven-plugin,它在專案的process-classes階段被執行,生成的報告如下所示



上圖顯示覆蓋率是100%,兩行程式碼都被執行到。程式碼沒有分支,複雜度是1。

點選進入package se.sigma.calculator裡面會得到如下結果圖:


點選進入 Calculator 這個類會得到:


cobetura不僅會記錄每行是否被執行到,還會記錄每行被執行的次數(hits)。

2. 複雜的情況:多模組maven專案

在多模組專案中,我們往往會把原始碼放在一個模組,測試程式碼放在另一個模組(出於專案分解管理或配置檔案的原因)。而maven的模組是一個執行完再執行另一個,導致cobetura的程式碼覆蓋率統計出現問題。

現有多模組專案結構如下:


      功能原始碼放在product模組,單元測試程式碼放在test模組。java檔案的內容和前面的一樣。test模組添加了product模組的依賴,這樣就可以import Calculator這個類。

根專案的pom.xml檔案:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>se.thinkcode</groupId>
    <artifactId>multi-module-failing-example</artifactId>
    <version>1.0</version>
    <packaging>pom</packaging>
    <modules>
        <module>product</module>
        <module>test</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>cobertura-maven-plugin</artifactId>
                <version>2.5.1</version>
                <executions>
                    <execution>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>cobertura</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

<modules>標籤裡包含它的兩個模組 product 和test。同樣加上了 cobertura-maven-plugin來生成測試覆蓋率報告. 

product模組的pom.xml檔案:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>se.thinkcode</groupId>
        <artifactId>multi-module-failing-example</artifactId>
        <version>1.0</version>
    </parent>
    <groupId>se.thinkcode</groupId>
    <artifactId>calculator</artifactId>
    <version>1.0</version>
</project>

test模組的pom.xml檔案:
<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>se.thinkcode</groupId>
        <artifactId>multi-module-failing-example</artifactId>
        <version>1.0</version>
    </parent>
    <groupId>se.thinkcode</groupId>
    <artifactId>calculator-test</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>se.thinkcode</groupId>
            <artifactId>calculator</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</project>

依賴 product 的原始碼,才能引用 Calculator並呼叫它的方法。

測試結果如下:


可以看到覆蓋率是0,而我們知道正確的結果應該是100%。

點選進入package裡面,顯示Calculator.java沒有被執行


點選進入Calculator.java裡面,顯示方法程式碼沒有被執行


maven的專案結構是固定的,一個java模組生成一個target檔案,各模組是隔離的,因此無法跨模組比對執行的測試類和原始碼檔案。這時我們想到另一種專案管理工具Ant。Ant與maven相比,它的靈活在於可以讓使用者自己指定原始碼的位置和編譯後位元組碼的存放位置,如此又可以達到單模組maven專案的效果。

maven+Ant

在前面工程結構的基礎上,我們在根目錄加上Ant的 build.xml 檔案。

multi-module-example
|-- build.xml
|-- pom.xml
|-- product
|   |-- pom.xml
|   `-- src
|       `-- main
|           `-- java
|               `-- se
|                   `-- sigma
|                       `-- calculator
|                           `-- Calculator.java
`-- test
    |-- pom.xml
    `-- src
        `-- test
            `-- java
                `-- se
                    `-- sigma
                        `-- calculator
                            `-- CalculatorTest.java

父專案根目錄pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>se.thinkcode</groupId>
    <artifactId>multi-module-example</artifactId>
    <version>1.1</version>
    <packaging>pom</packaging>
    <modules>
        <module>product</module>
        <module>test</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>.</directory>
                            <includes>
                                <include>**/*.ser</include>
                            </includes>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

maven-clean-plugin是用來清楚之前生成的target檔案(.ser結尾的是cobetura生成的報告)。這裡不用再新增maven-cobetura外掛,cobertura需要單獨下載,在Ant 指令碼中引用。

Cobertura.下載地址 http://cobertura.sourceforge.net/download.html 。我這裡用的是Cobertura 1.9.4.1下載後解壓到 /Users/tsu/java/cobertura-1.9.4.1 ,你可以修改成其他目錄,但是要注意和 build.xml 中指定的路徑一致。

Ant構建指令碼build.xml:

<project>
    <target name="instrument">
        <!-- Add all modules that should be included below -->
        <!-- <antcall target="instrumentAModule">
            <param name="module" value="MODULE_NAME_TO_REPLACE"/>
        </antcall> -->
        <antcall target="instrumentAModule">
            <param name="module" value="product"/>
        </antcall>
    </target>

    <target name="report" depends="merge">
        <property name="src.dir" value="src/main/java/"/>
        <cobertura-report datafile="sum.ser"
                          format="html"
                          destdir="./target/report">
            <!-- Add all modules that should be included below -->
            <!-- fileset dir="./MODULE_NAME_TO_REPLACE/${src.dir}"/ -->
            <fileset dir="./product/${src.dir}"/>
        </cobertura-report>
    </target>

    <target name="merge">
        <cobertura-merge datafile="sum.ser">
            <fileset dir=".">
                <include name="**/cobertura.ser"/>
            </fileset>
        </cobertura-merge>
    </target>

    <target name="instrumentAModule">
        <property name="classes.dir" value="target/classes"/>
        <cobertura-instrument todir="./${module}/${classes.dir}">
            <fileset dir="./${module}/target/classes">
                <include name="**/*.class"/>
            </fileset>
        </cobertura-instrument>
    </target>

    <property environment="env"/>
    <property name="COBERTURA_HOME" value="/Users/tsu/java/cobertura-1.9.4.1"/>
    <property name="cobertura.dir" value="${COBERTURA_HOME}"/>
    <path id="cobertura.classpath">
        <fileset dir="${cobertura.dir}">
            <include name="cobertura.jar"/>
            <include name="lib/**/*.jar"/>
        </fileset>
    </path>
    <taskdef classpathref="cobertura.classpath" resource="tasks.properties"/>
</project>

兩個重要的<targets>是:

  • instrument
  • report

instrument 用Cobertura instrumentation來執行編譯類檔案。

report 將執行的測試類和原始碼組合起來,生成覆蓋率報告。

product模組的pom.xml和之前一致 :

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>se.thinkcode</groupId>
        <artifactId>multi-module-example</artifactId>
        <version>1.1</version>
    </parent>
    <groupId>se.thinkcode</groupId>
    <artifactId>calculator</artifactId>
    <version>1.1</version>
</project>

test模組的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>se.thinkcode</groupId>
        <artifactId>multi-module-example</artifactId>
        <version>1.1</version>
    </parent>
    <groupId>se.thinkcode</groupId>
    <artifactId>calculator-test</artifactId>
    <version>1.1</version>
    <dependencies>
        <dependency>
            <groupId>se.thinkcode</groupId>
            <artifactId>calculator</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.cobertura</groupId>
            <artifactId>cobertura</artifactId>
            <version>1.9.4.1</version>
        </dependency>
    </dependencies>
</project>

test 模組需要新增 Cobertura依賴,這樣在test phase才能記錄執行的蹤跡

專案的執行有以下四步:

  1. Compile all code
  2. Instrument the code
  3. Execute all tests
  4. Consolidate and build the report

即順序執行下面的四條命令:

mvn clean compile
ant instrument
mvn test
ant report

生成的報告:



相關推薦

Cobertura 統計模組maven專案測試覆蓋率

Cobertura 統計單元測試覆蓋率的機制:執行類,並在一個log檔案中記錄哪一行被執行,然後將原始碼和log檔案進行比對。 1. 簡單的情況:單模組maven專案 專案結構 原始碼 src/main/java/se/sigma/calculator/Calcula

SpringCloud下的模組maven專案

編寫一個登陸微服務pf-login,並註冊到Eureka,先看我建立完的目錄結構: 簡單分析一下,最外層是pf-login,下面有client、server、dao三個模組:  ①、client模組用於註冊服務,提供服務的呼叫介面,是呼叫login服務的入口。  ②、s

Maven和Eclipse整合和構建模組Maven專案

最近在工作中越來越經常的用到了Maven作為專案管理和Jar包管理和構建的工具,感覺Maven的確是很好用的。而且要將Maven的功能最大發揮出來,多模組是一個很好的整合例子。 一個Maven專案包括一個MavenProject和多個MavenModule 下面用一個

從svn上檢出模組maven專案

一、SVN上Maven多模組專案結構 使用eclipse匯入SVN上的Maven多模組專案 Maven多模組專案所在SVN目錄 二、eclipse通過SVN匯入到工作空間 工作空間位於F:/HPCWorkspace 2.1 File->Import,選擇從SVN檢出專案下載  2.2 選擇/新建

SpringCloud零基礎上手(二)——SpringBoot模組maven專案

本篇接著上一篇的內容,我們要寫一個服務生產者,向Eureka註冊中心註冊服務。為了後面的內容順利進行,我們建立一個多模組的專案。 編寫一個登陸微服務pf-login,並註冊到Eureka,先看我建立完的目錄結構: 簡單分析一下,最外層是pf-login,

eclipse 模組Maven專案打包指定模組

       一直在各種測試打包多模組下面的單獨模組打包,一直報找不到所依賴模組的jar包,網上各種尋找,沒有找到合適的內容,今天偶然發現有個提示要parent模組執行打包,經測試確實打包成功,記錄一下。         在eclipse中,多模組專案中單獨打包某個web工

Maven構建模組Springboot專案

1 建立空專案 (groupId=com.boomsecret artifactId=boomsecret-java) mvn archetype:generate -DgroupId=com.boomsecret -DartifactId=boomsecret-java -Darc

Maven--搭建模組企業級專案

一. 必要性    所有用Maven管理的真實的專案都應該是分模組的,每個模組都對應著一個pom.xml。它們之間通過繼承和聚合(也稱作多模組,multi-module)相互關聯。那麼,為什麼要這麼做呢?我們明明在開發一個專案,劃分模組後,匯入Eclipse變成了N個專案,這會

使用maven快速搭建SpringBoot模組web專案

maven快速搭建SpringBoot多模組web專案  最近開發用到了SpringBoot框架,在這裡記錄一下搭建專案的過程,應該是比較全的。 前提是你的maven配置正確 建立父專案 File–>new–>maven project 點選Next進入下一步

IntelliJ IDEA 構建maven模組工程專案(詳細圖)

食用前須知 本文以a b c 三個模組為例來搭建專案,以達到通俗易懂的初衷 模組a —– 基模組,就是人們常說的parent 模組b —– 其他模組都需要使用的一些工具,比如時間工具,json工具等 模組c —– 專案主要的內容,一般為

Eclipse+Maven建立模組web專案

簡介 通過Maven建立的多模組專案。 模組是此POM列出並作為一組執行的專案。通過一個pom打包的專案可以將它們列為模組來聚合成一組專案進行構建,這些模組名是這些專案的

maven建立模組web專案

實現步驟 建立專案目錄 進入“工作空間”目錄,建立名為tradework 的資料夾,切換至控制檯,進入該資料夾。  配置模組 生成各個模組 該步驟會依次生成專案的各個模組,但是生成的模組並沒有 建立依賴,只是最簡單的並且符合maven 要求的專案結構的模組,關於什麼是 m

在eclipse中釋出maven模組web專案到tomcat上及單步debug模組jar

1.在eclipse中釋出maven的多模組web專案到tomcat eclipse和maven及tomcat的部署略去,還有maven的基礎知識和使用在此處略去. 按照如下的步驟操作: 將lib和maven模組生成的jar加入到lib下. 注意:到這步可能有

關於maven模組聚合專案部署等問題--

一般我們公司都會有自己用來部署專案的網址: 進入網址後,當然你得有登入的賬號 1)、首先你會看到公司各個(聚合)專案的索引   2)、點選專案索引會列出專案的各個模組,滑鼠移到模組上方

Idea使用Maven建立模組SpringBoot專案問題記錄

軟體版本: Idea 15.0 Maven 3 Spring Boot 1.4 JDK 1.7 專案結構: flyat-admin為後臺 flyat-admin-app為後臺配置(攔截器、監聽器等) flyat-core為核心層(mapper

Netty入門之建立Maven模組依賴專案

新學Netty,編譯執行時踩了一些坑,記錄在此。 essential netty in action中有一個入門demo,EchoServer and EchoClient,用於Netty入門的小demo。 (Essential Netty in Action)EchoCli

在一個idea工作環境中匯入maven專案模組

1.開啟idea,點選File----》 點選New ----》 點選Project  from Existing Sources; 彈出Select File or Directory to imp

Maven(三)——Maven管理模組Web專案例子

在實際的開發中,一個大專案都是由多個子專案組成的,這些子專案之間可以互相依賴,互相呼叫。 maven可以方便的執行多專案間的管理。 以前面的Restaurant專案為例,把做黃燜雞的程式碼放到Kitc

模組Maven(sg-uap)專案部署到tomcat

1, 將專案改為動態web專案 選中專案->右鍵屬性,左側找到Project Facets,在右側的列表裡面勾選Dynamic Web Module,後面版本選擇3.0,提示必須勾選java,在下面找到java 版本1.6勾選,javascript也可以勾選上,點選確

從寫專案到部署linux伺服器全過程-MyEclipse建立模組Maven依賴專案

MyEclipse建立多個Maven依賴專案,以一個first-parent聚合專案,一個first-jar模組專案,一個first-web模組專案為例。 新建一個簡單的maven web 專案,我們已經掌握。詳見MyEclipse新建單個Maven we