精华内容
下载资源
问答
  • 而maven的模块是一执行完再执行另一,导致cobetura的代码覆盖率统计出现问题。 maven的项目结构是固定的,一java模块生成一target文件,各模块是隔离的,因此无法跨模块比对运行的测试类和源代码文件。这时...


    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

    生成的报告:





    展开全文
  • Jacoco服务器增量覆盖率统计(支持模块)

    千次阅读 热门讨论 2019-06-18 09:54:22
    统计后端代码覆盖时,一般都使用的是Jacoco,但是Jacoco本身并不支持增量统计,当有一新需求出现时,经过一轮轮的测试,并不能直观的从全量覆盖中找出我们想要的那部分统计率。 二、增量统计思路 (不想看...

    目录

    一、背景

    二、增量统计思路

    三、如何使用增量插件


    一、背景

           在统计后端代码覆盖率时,一般都使用的是Jacoco,但是Jacoco本身并不支持增量统计,当有一个新需求出现时,经过一轮轮的测试,并不能直观的从全量覆盖率中找出我们想要的那部分统计率。

    二、增量统计思路

    (不想看思路的,直接拉到最后)

    首先我们要想清楚几个问题:

    1:什么叫增量?

    2:怎么获取增量文件?

    3:怎么找出增量文件中修改的部分?

    4:怎么让Jacoco只统计这部分代码的覆盖率?

    以下我们就来分析这4个问题:

    什么叫增量?

    当前发布的版本中后端修改的class文件或者是新增的class文件即是增量文件。

    怎么获取增量文件?怎么找出增量文件中修改的部分?

    每次Git提交的时候都是有记录的,我们可以从git下手找出我们想要的。

    1:先用log找到提交的版本号

    2:根据版本号去获取2次版本直接的差异文件

    git diff beab05eab0499458734e9c6c1d340ef06de677df 35aa4ac5fb0497a96f9d4c4d4b6a2a70323a3082

     得到的结果如下: 

    diff --git a/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java b/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java
    index 3c52f59..1911441 100644
    --- a/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java
    +++ b/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java
    @@ -43,4 +43,16 @@ 
    class JacocoOrders {
             p.destroy();
             return success;
         }
    +
    +    public static void main(String[] args) {
    +
    +        try {
    +            JacocoOrders jacocoOrders = new JacocoOrders();
    +            boolean fail =
    +                    jacocoOrders.exec("mvn clean package -f /Users/xx/IdeaProjects/testworks/logcollector".split(" "));
    +        } catch (Exception e) {
    +            e.printStackTrace();
    +        }
    +
    +    }
     }
    diff --git a/src/main/java/com/dxy/platform/utils/CaseRun.java b/src/main/java/com/dxy/platform/utils/CaseRun.java
    index 146c6a9..830425a 100644
    --- a/src/main/java/com/dxy/platform/utils/CaseRun.java
    +++ b/src/main/java/com/dxy/platform/utils/CaseRun.java
    @@ -250,7 +250,7 @@ 
    public class CaseRun {
             compareInfo.setHopeData(caseInfo.getHopeValue());
             compareInfo.setHeader(caseInfo.getHeaderValue());
    
    -        if (infos == null || EmptyUtil.isEmpty(caseInfo.getHopeValue())) {
    +        if (infos == null) {
                 compareInfo.setErrorMessage(errorInfo);
             } else {
                 // code 是否是200 不是直接返回;是200 对比数据
    diff --git a/src/main/java/com/dxy/platform/utils/GroupsRun.java b/src/main/java/com/dxy/platform/utils/GroupsRun.java
    index 60a25b9..f219c16 100644
    :
    diff --git a/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java b/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java
    index 3c52f59..1911441 100644
    --- a/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java
    +++ b/src/main/java/com/dxy/platform/jacoco/JacocoOrders.java
    @@ -43,4 +43,16 @@ 
    class JacocoOrders {
             p.destroy();
             return success;
         }
    +
    +    public static void main(String[] args) {
    +
    +        try {
    +            JacocoOrders jacocoOrders = new JacocoOrders();
    +            boolean fail =
    +                    jacocoOrders.exec("mvn clean package -f /Users/xx/IdeaProjects/testworks/logcollector".split(" "));
    +        } catch (Exception e) {
    +            e.printStackTrace();
    +        }
    +
    +    }
     }

    分析这些差异(这里只是简单的讲解一下,详细的讲解可以百度):

    diff --git :

    表示是有修改的差异文件,

    a/ 修改前的文件,b/修改后的文件

    --- a/ :表示改动前的文件

    +++ b/:表示改动后的文件

    @@ -43,4 +43,16 @@:

    @@之间的表示修改的地方

    -43,4:表示修改前的文件是从第43行开始,连续修改到后面4行

    +43,16 表示修改后的文件是从第43行开始,连续修改到后面16行

    现在我们知道了哪些是修改的文件且修改的地方我们也知道怎么找出来了。

    怎么让Jacoco只统计这部分代码的覆盖率?

    这里使用的是ant build.xml形式去配置的,只需要在统计代码的时候,使用<include></include>标签,告诉Jacoco我只想统计这些文件即可。

    (这里省去了Jacoco 服务器环境的搭建,百度一搜全是)

    三、如何使用增量插件

    下载插件: incremental.jar

    链接:https://pan.baidu.com/s/1Wv0IFwNCbBxoHdNPP9R3vg  密码:gudd

    创建一个yml文件,配置内容如下:
    jacoco:
      path:
        source:  #必填 拉取代码存放路径
        report:  #必填 存放报告路径
      git:
        url:  #必填 仅支持https
        user:  #必填
        pswd:  #必填
        branch:  # 默认master
        source:  "/api/src/main/java,/service/src/main/java" # 源码路径,多模块的话用,分隔 默认src/main/java/
        classes:  "/api/target/dist/classes,/service/target/classes" # 编译后路面 多模块的话用,分隔 默认 target/classes/
        v1:  # v1,v2不填写默认比较最新2个版本 新版本号
        v2:  # 旧版本号
        include: "**/test.class,**/test2.class,**/tst/test3.class" #包含类
        exclude: #排除类
      server:
        ip:  #必填
        port:  #必填

    使用命令:java -jar incremental.jar -f [你的yml配置文件路径]

    写这个插件用的时间比较少,很多细节没处理好,

    展开全文
  • 发现cobertura对jdk1.8支持不够好,每次遇到lamba表达式时,都会报warn,且cobertura对模块支持不够友好(需要使用ant,没有实际测试过)且年久失修(好久都没人更新),故使用了JaCoCo进行模块代码覆盖率统计;...

    之前一直使用cobertura进行代码覆盖率统计,但是切换到Springboot2且jdk升级到1.8后,发现cobertura对jdk1.8支持不够好,每次遇到lamba表达式时,都会报warn,且cobertura对多模块支持不够友好(需要使用ant,没有实际测试过)且年久失修(好久都没人更新),故使用了JaCoCo进行多模块代码覆盖率统计;

    初步方案如下:

    项目结构:

    说明:web为启动模块,依赖关系:web->service->manager->dao->entity+common

    注:test模块是为了统一代码覆盖率报告而单独建的模块,且test->web+service+manager+dao+entity+common(test依赖其他所有子模块)

    最外层父POM:

    <build>
        <plugins>
            <!-- jacoco插件 -->
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.2</version>
                <executions>
                    <execution>
                        <id>prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>report-aggregate</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>report-aggregate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

    </build>

    子模块POM:

    子模块POM只需继承(parent)父POM即可

    问题:

    实际测试过程中,会在每个子模块中target/site/jacoco-aggregate文件夹下生成index.html,通过浏览器查看该index.html即可直观的看到当前代码测试的覆盖率报告;

    但是实际测试结果并不好,多模块统计结果是进行合并了,但是只有当前模块pom中显式的依赖了其他模块,才会在当前模块的报告中去回去合并显式声明的其他模块,例如:web->service->manager,实际在web中的target/site/jacoco-aggregate/index.html只能查看到service(显式依赖)的统计结果,无法查看到manager(传递依赖)的统计结果,并且web中的index.html也无法查看到自己模块(web)的统计信息;

    最终解决方案:

    新建了test模块,当前模块里什么代码都没有,但是POM中显式依赖了其他所有模块,显式依赖就是为了聚合其他所有模块的统计报告;

    test模块POM:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>com.mx.server.tsp</groupId>
        <artifactId>mx-vehicle-parts-management-test</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>mx-vehicle-parts-management-test</name>

        <parent>
            <groupId>com.mx.server.tsp</groupId>
            <artifactId>mx-vehicle-parts-management</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </parent>

        <dependencies>
            <!-- 依赖所有子模块  -->
            <dependency>
                <groupId>com.mx.server.tsp</groupId>
                <artifactId>mx-vehicle-parts-management-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.mx.server.tsp</groupId>
                <artifactId>mx-vehicle-parts-management-service</artifactId>
            </dependency>

            <dependency>
                <groupId>com.mx.server.tsp</groupId>
                <artifactId>mx-vehicle-parts-management-manager</artifactId>
            </dependency>
            <dependency>
                <groupId>com.mx.server.tsp</groupId>
                <artifactId>mx-vehicle-parts-management-dao</artifactId>
            </dependency>
            <dependency>
                <groupId>com.mx.server.tsp</groupId>
                <artifactId>mx-vehicle-parts-management-entity</artifactId>
            </dependency>
            <dependency>
                <groupId>com.mx.server.tsp</groupId>
                <artifactId>mx-vehicle-parts-management-common</artifactId>
            </dependency>
        </dependencies>
        
    </project>
     

    综上,为了合并多module的代码测试覆盖率统计报告,

    (1)采用了JaCoCo插件,

    (2)且单独为了聚合统计报告而新建了一个test模块,当前模块没有任何代码,只是显式依赖了其他所有子模块

    (3)在项目根目录下执行mvn install后,即可通过test模块下的target/site/jacoco-aggregate/index.html查考到合并后的代码测试覆盖率报告;

    缺陷:

    test模块除了生成聚合报告,没有任何实际作用,且所有Springboot多模块项目为了聚合代码测试覆盖率报告都需要单独建立一个test模块,成本有点大,且引入了多余的test模块(破环了项目原有结构),希望日后找到更好的方法......

     

    展开全文
  • JavaScript覆盖率统计实现

    千次阅读 2014-10-17 15:36:41
    主要需求 1、 支持browser & nodejs ...用户写单元测试用例的时候,不需要为了支持覆盖率统计多写代码,之前写的用例无需修改就可以直接统计覆盖率情况。 原理 javascript覆盖率的相关文章比较少,下面的

    主要需求

    1、 支持browser & nodejs

    因为javascript既可以在浏览器环境运行,也可以在nodejs环境运行,因此需要能够统计两种环境下单元测试的覆盖率情况。

    2、 透明、无缝

    用户写单元测试用例的时候,不需要为了支持覆盖率统计多写代码,之前写的用例无需修改就可以直接统计覆盖率情况。

    原理

    javascript覆盖率的相关文章比较少,下面的图是通过阅读开源javascript覆盖率工具istanbul及开源测试框架Karma的覆盖率插件karma-coverage得出的。javascript覆盖率统计的核心思想是,在源代码相应的位置注入统计代码,当代码运行之后,根据统计代码统计的数据确定程序运行的路径,最终生成覆盖率统计报告。

    1. 转换(instrument)

    • 使用开源工具Esprima对源代码进行语法分析生成语法树
    • 在语法树相应的位置注入统计代码,在程序执行到这个位置的时候对相应的全局变量赋值,确保执行之后能够根据全局变量知道代码的执行流程
    • 使用开源工具Escodegen根据注入之后的语法树生成对应的javascript代码,即转换之后的代码(instrumented code)

    注:这里进行语法分析的好处是,针对书写不规范的代码(比如一行多个语句),依然能够很好统计出分支覆盖和组合覆盖等信息。

    2. 执行(run)

    这一步需要先载入转换后的代码:

    • nodejs:直接通过对require语句进行hook来无缝实现,后面会详细介绍
    • 浏览器环境:需要将转换后的代码传给浏览器。如果是karma之类的带server的测试框架,需要通过socket传输至浏览量器,执行完之后再将包含覆盖率信息的执行结果传回server,生成测试报告

    然后执行单元测试,产生的统计信息会挂在全局变量this下面。对于浏览器环境,this就是window,而对于nodejs环境this就是global

    3. 生成报告(report)

    这一步会根据全局标量中的覆盖率信息生成特定格式的报告,如html、lcov、cobertura、teamcity等。

    一个例子

    //source code
    function abs(num){
        if(abs > 0)
            return num;
        else
            return -num;
    }
    
    //instrumented code
    var __cov_iypKC$dWI6uJFmvxThycaA = (Function('return this'))();
    if (!__cov_iypKC$dWI6uJFmvxThycaA.__coverage__) { __cov_iypKC$dWI6uJFmvxThycaA.__coverage__ = {}; }
    __cov_iypKC$dWI6uJFmvxThycaA = __cov_iypKC$dWI6uJFmvxThycaA.__coverage__;
    if (!(__cov_iypKC$dWI6uJFmvxThycaA['/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js'])) {
       __cov_iypKC$dWI6uJFmvxThycaA['/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js'] = {"path":"/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js","s":{"1":1,"2":0,"3":0,"4":0},"b":{"1":[0,0]},"f":{"1":0},"fnMap":{"1":{"name":"abs","line":1,"loc":{"start":{"line":1,"column":-15},"end":{"line":1,"column":17}}}},"statementMap":{"1":{"start":{"line":1,"column":-15},"end":{"line":6,"column":1}},"2":{"start":{"line":2,"column":1},"end":{"line":5,"column":14}},"3":{"start":{"line":3,"column":2},"end":{"line":3,"column":13}},"4":{"start":{"line":5,"column":2},"end":{"line":5,"column":14}}},"branchMap":{"1":{"line":2,"type":"if","locations":[{"start":{"line":2,"column":1},"end":{"line":2,"column":1}},{"start":{"line":2,"column":1},"end":{"line":2,"column":1}}]}}};
    }
    __cov_iypKC$dWI6uJFmvxThycaA = __cov_iypKC$dWI6uJFmvxThycaA['/Users/lonfee88/Codes/testframe/coverage-jasmine-istanbul-karma/abs.js'];
    function abs(num){__cov_iypKC$dWI6uJFmvxThycaA.f['1']++;__cov_iypKC$dWI6uJFmvxThycaA.s['2']++;if(abs>0){__cov_iypKC$dWI6uJFmvxThycaA.b['1'][0]++;__cov_iypKC$dWI6uJFmvxThycaA.s['3']++;return num;}else{__cov_iypKC$dWI6uJFmvxThycaA.b['1'][1]++;__cov_iypKC$dWI6uJFmvxThycaA.s['4']++;return-num;}}
    

    node.js集成覆盖率

    通过hook可以直接无缝的加载转换后的代码,可以对下面两种语句进行hook:

    • require
    • vm.createScript

    对require进行hook的代码是通过对Module._extensions['.js']进行赋值实现的:

    function hookRequire(matcher, transformer, options) {
        options = options || {};
        var fn = transformFn(matcher, transformer, options.verbose),
            postLoadHook = options.postLoadHook &&
                typeof options.postLoadHook === 'function' ? options.postLoadHook : null;
    
        Module._extensions['.js'] = function (module, filename) {
            var ret = fn(fs.readFileSync(filename, 'utf8'), filename);
            if (ret.changed) {//载入instrument之后的代码并运行
                module._compile(ret.code, filename);
            } else {//载入原来的代码并运行
                originalLoader(module, filename);
            }
            if (postLoadHook) {
                postLoadHook(filename);
            }
        };
    }
    

    hook使覆盖率的集成变得简单,甚至不需要写代码,比如Mocha的覆盖率集成,只需要改用如下的调用方式即可:

    istanbul cover _mocha -- -R spec test/spec
    

    浏览器集成覆盖率

    浏览器集成覆盖率就稍微麻烦一点,好在istanbul提供了API:

    1. 转换代码(调用istanbul的Instrumenter接口)
    2. 将instrumented code发送到浏览器(自己实现
    3. 将包含覆盖率信息的执行结果发回server(自己实现
    4. 根据返回的覆盖率信息生成覆盖率报告(调用istanbul的Reporter接口)
    展开全文
  • 统计 Golang 项目的测试覆盖

    万次阅读 2018-05-12 16:52:49
    我们的项目主要基于 Golang 开发,公司要求统计测试覆盖。所以,我们摸索了一下在 Golang 下如何统计整个项目得测试覆盖: 以下内容均基于 Go SDK 1.10.1 获得,不保证可以向下兼容 先直接上结果: go ...
  • 1:既然是模块的代码覆盖率统计,所以子模块必须也要是jacoco插桩的方式打开子模块代码覆盖率统计开关; 2:处理子模块与主模块的依赖关系,使子模块也要debug的方式打包(android正常打包是以release方式)...
  • JUnit测试用例覆盖率统计

    千次阅读 2018-12-30 18:20:24
    单元测试覆盖率统计我们的较的就是JaCoCo,该用具已经集成到jmockit的jar包中,如果我们使用的是maven项目,则在pom.xml中把jacoco对应的属性设置上即可,如果是非maven项目需要如何做呢? 上一篇博客已经知道在...
  • 基本的R包已经实现了传统多元统计的很功能,然而CRNA的许多其它包提供了更深入的多元统计方法,下面要综述的包主要分为以下几部分:  1) 多元数据可视化(Visualising multivariate data):  绘图方法:  ...
  • 1、说明-使用插件 maven-surefire-plugin jacoco-maven-plugin 要求:版本大于0.7.7 ...2、使用方法 2.1、第一步:parent.pom.xml 中声明 &lt;pluginManagement&gt; &lt;plugins&gt; ...
  • 正如我的另外一篇文章种所描述的方法: ...其他标签统计某某行为最近三月的数据可能通过对数据进行筛选计算,可以降低统计的数据量,无非是脚本而已。但是这里必须从基表中统计客户行为,数据量相当可观。 ...
  • 一张表存储了学生的成绩,班级号等信息,统计各个班的合格(>=60)、优秀(>=80)。要考虑到有的班级没有人通过或者合格的情况。 建表: create table score(s_id number(10),num number(3),class_id number(10))...
  • jacoco统计自动化代码覆盖

    万次阅读 热门讨论 2018-07-10 13:40:07
    jacoco统计自动化代码覆盖 1. 简介 1.1. 什么是Jacoco Jacoco是一开源的代码覆盖工具,可以嵌入到Ant 、Maven中,并提供了EclEmma Eclipse插件,也可以使用JavaAgent技术监控Java程序。很第三方的工具...
  • 统计 Android 单元测试代码覆盖

    千次阅读 2015-09-24 17:26:30
    为程序编写单元测试对于我一境界比较low的程序员来说,简直就是噩梦,但是不得承认,为项目写测试是非常正确、必要的工作,尤其是当项目越来越大,代码越来越,测试代码可以及时检查出一次改动所带来的影响。...
  • 李航·《统计学习方法》学习笔记

    千次阅读 2017-12-03 15:12:45
    第一章 统计学习的方法概论 1 统计学习概述统计学习的过程 统计学习的分类 监督学习的分类 1 生成方法与判别模方法 11 生成方法 11 判别方法 2 分类问题标注问题和回归问题 21 分类问题 22 标注问题 23 回归问题 2 ...
  • GCOV+LCOV 代码调试和覆盖率统计工具

    万次阅读 2017-10-27 20:03:15
    GitHub GCOV+LCOV 代码调试和覆盖率统计工具 AderXCoding/system/tools/gdb/gcov 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作因本人技术水平和知识面...
  • 统计学习方法学习笔记一

    千次阅读 2017-03-16 09:23:04
    第一章 统计学习方法概论 统计学习的主要特点是 统计学习的对象 统计学习方法的分类 统计学方法的三要素 统计学方法的步骤 统计学习的研究 监督学习supervised leaning 三要素 模型 策略 算法 训练误差与测试误差 ...
  • 现在android 开发都喜欢模块化的方式,然后以aar文件的方式导入到主项目,但是这对于统计代码覆盖就有点麻烦了,因为统计时候都忽略这些第三方库,那么我们如何将这些aar文件纳入到代码覆盖统计中来呢?...
  • 使用Google Analytics统计用户留存

    千次阅读 2015-05-22 09:26:40
    http://www.analyticskey.com/google-analytics-liu-cun/ ...使用Google Analytics统计用户留存 ...访客留存或注册用户留存要怎么统计,很朋友都在纠结这问题。这复合指标虽然有着一较明确的定义,
  • 现有多个数据集,表结构都是一样的,现在需要找出这些数据集有多少数据量是重复的。假设有4个数据集,找出这4个数据集的重复的量,这里统计重复的量包括两两重复的量,三个都重复的量,四个都重复的量。根据排列组合...
  • - 李航《统计学习方法》第二章——Python实现感知器模型(MNIST数据集) - 李航《统计学习方法》第三章——Python实现KNN算法(MNIST数据集) - 李航《统计学习方法》第四章——Python实现朴素贝叶斯分类...
  • 李航《统计学习方法》第二章——Python实现感知器模型(MNIST数据集) 李航《统计学习方法》第三章——Python实现KNN算法(MNIST数据集) 李航《统计学习方法》第四章——Python实现朴素贝叶斯分类器...
  • 统计报表测试方法

    千次阅读 2011-08-23 22:17:39
    报表的测试主要分为以下几方面:界面,安全性,准确性,展示速度(性能)  数据统计方面  1、报表统计数据的正确性;  2、报表统计数据的完整性;  3、报表统计数据的合法性;比如,统计金额字段需求要求有“$”...
  • 统计数据收集方式与收集方法

    千次阅读 2020-03-05 23:39:46
    统计数据来源 直接来源(一手数据):观察实验、统计调查 间接来源(二手数据):网络数据、公开出版物 二手数据收集方式 1.公开出版物 (《 中国统计年鉴》、《中国统计摘要》、《中国 人口统计年鉴》、《世界经济...
  •  很时候会需要提供一些统计记录的,比如某个服务一月的被调用量、接口的调用次数、成功调用次数等等。 优点:  使用AOP+Hendler对业务逻辑代码无侵入,完全解耦。通过spring boot自带的健康检查接口(/h...
  • PowerMock写的单元测试用例,sonar中覆盖显示问题 sonar中没有覆盖的显示问题 sonar中覆盖显示不正确 sonar中单元测试用例数不正确问题 sonar中没有覆盖的显示问题 pom文件中jacoco-maven-plugin配置不...
  •   计算一分三,即平均分、合格、优秀和高分,是成绩统计中最常见也是最需要的统计数据。 3.1计算一分三 实例3-2 3.2计算离均 3.1计算一分三   计算一分三,即平均分、合格、优秀和高分...
  • 统计学习笔记(1)——统计学习方法概论

    万次阅读 多人点赞 2012-12-20 12:11:47
    统计学习是一门概率论、统计学、信息论、计算理论、最优化理论及计算机科学等多个领域的交叉学科。  统计学习的对象是数据,它从数据出发,提取数据的特征,抽象出数据的模型,发现数据中的知识,又回到对数据的...
  • 1、统计学习三要素除了介绍一些基本概念之外,李航《统计学习方法》第一章的重点是提出了统计学习的三要素,即 方法 = 模型 + 策略 + 算法 更确切地说,统计学习方法包括模型的假设空间、模型选择的准则以及模型...
  • 最近在做针对Android应用程序代码覆盖统计工作,刚开始从论文中看到大多数研究者采用emma这工具来统计Android应用程序代码覆盖,但是我看过一些资料后发现emma只能对eclipse中的Android项目进行插装,由于...
  • 统计学习方法-支持向量机SVM

    万次阅读 多人点赞 2013-10-29 16:25:15
    统计机器学习的精密思维相比,传统的机器学习基本上属于摸着石头过河,传统的机器学习方法构造分类系统完全成了一种技巧,一人做的结果可能很好,另一人差不多的方法做出来却很差,缺乏指导和原则。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 328,503
精华内容 131,401
关键字:

多个率的比较用什么统计方法