写完代码先自测一下web项目或者接口

一般先跑findbug,再跑jacoco。

其实我一直在寻找一个在浏览器里面操作web项目,ide里面的代码颜色就会告诉你哪一行执行过,哪一行没有执行过。

还在研究中,有用过这样插件的或者有这样想法的可以私信我。

因为不是专业测试,懒得写测试case,jacoco可以省心很多。在代码业务比较繁琐的时候,可以在web中直接操作所有的功能,jacoco就可以告诉你有哪些分支还没有测试到,哪些分支已经测试过。

下面正文,如何使用jacoco跑覆盖率。

环境win10上,我这边的jdk是1.7的,tomcat7亲测可用。

https://www.eclemma.org/jacoco/

先上一波地址,进去download一个版本。

然后将其解压得到下面的目录结构。

java 代码覆盖率实现原理 java跑覆盖率_java

lib下面是我们主要用的jar包

java 代码覆盖率实现原理 java跑覆盖率_bundle_02

打开myeclipse,windows>prefernces>MyEclipse>tomcat>tomcat 7x>jdk

java 代码覆盖率实现原理 java跑覆盖率_java_03

 

上面那句是配置内存的,不管他,主要是下面那句配置(当然这个配置可以配置在tomcat/bin目录下的catalina.bat中)

-javaagent:D:\jacoco\lib\jacocoagent.jar=includes=*,output=tcpserver,port=8494,address=127.0.0.1。

javaagent 就是tomcat启动的时候需要随项目启动的。

includes 就是需要监听的classes目录,这里就写*了。

output=tcpserver 这相当于是实时监控代码覆盖率。

port 需要有一个监听端口,随便写一个没有被占用的,写之前记得netstat -aon|findstr "8494" 看看是否被占用。

address 就写本地地址就好

配置完成以后启动tomcat。

这是我们就可以开始我们的测试了,测试完成后,我们需要把exec文件取出来。

随便新建一个java项目,把下面的类贴进去,jar包在刚才jacoco/lib下面都有

package org.jacoco.examples.parser;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

import org.jacoco.core.data.ExecutionDataWriter;
import org.jacoco.core.runtime.RemoteControlReader;
import org.jacoco.core.runtime.RemoteControlWriter;

/**
 * This example connects to a coverage agent that run in output mode
 * <code>tcpserver</code> and requests execution data. The collected data is
 * dumped to a local file.
 */
public final class ExecutionDataClient {

	private static final String DESTFILE = "jacoco-client.exec";

	private static final String ADDRESS = "127.0.0.1";

	private static final int PORT = 8494;

	/**
	 * Starts the execution data request.
	 * 
	 * @param args
	 * @throws IOException
	 */
	public static void main(final String[] args) throws IOException {
		final FileOutputStream localFile = new FileOutputStream(DESTFILE);
		final ExecutionDataWriter localWriter = new ExecutionDataWriter(
				localFile);

		// Open a socket to the coverage agent:
		final Socket socket = new Socket(InetAddress.getByName(ADDRESS), PORT);
		final RemoteControlWriter writer = new RemoteControlWriter(
				socket.getOutputStream());
		final RemoteControlReader reader = new RemoteControlReader(
				socket.getInputStream());
		reader.setSessionInfoVisitor(localWriter);
		reader.setExecutionDataVisitor(localWriter);

		// Send a dump command and read the response:
		writer.visitDumpCommand(true, false);
		if (!reader.read()) {
			throw new IOException("Socket closed unexpectedly.");
		}

		socket.close();
		localFile.close();
	}

	private ExecutionDataClient() {
	}
}

ADDRESS 要和刚才tomcat的配置一致

PORT 要和刚才tomcat的配置一致

然后执行以下main方法,刷新一下这个项目。会在本想目录下产生一个jacoco-client.exec文件。

java 代码覆盖率实现原理 java跑覆盖率_bundle_04

现在我们来用exec文件生成出报表

还在这个项目中新建类

package org.jacoco.examples.expressions;
import java.io.File;
import java.io.IOException;

import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.tools.ExecFileLoader;
import org.jacoco.report.DirectorySourceFileLocator;
import org.jacoco.report.FileMultiReportOutput;
import org.jacoco.report.IReportVisitor;
import org.jacoco.report.html.HTMLFormatter;
 
public class Testjacoco {

    private final String title;

    private final File executionDataFile;
    private final File classesDirectory;
    private final File sourceDirectory;
    private final File reportDirectory;

    private ExecFileLoader execFileLoader;
    public Testjacoco(final File projectDirectory ) {
        this.title = projectDirectory.getName();
        this.executionDataFile = new File("D:/coverage/jacoco-client.exec");//覆盖率的exec文件地址 这个就是刚才生成的文件,引用到就可以了
        this.classesDirectory = new File("D:/java/t7/webapps/xxx/WEB-INF/classes");//目录下必须包含源码编译过的class文件,用来统计覆盖率.tomcat中的class文件地址
//        this.sourceDirectory =null;
        this.sourceDirectory = new File("D:/work/xxx/src");//源码的/src/main/java,只有写了源码地址覆盖率报告才能打开到代码层。使用jar只有数据结果
        this.reportDirectory = new File("D:/work/xxx/jacoco_report");//要保存报告的地址,报告输出的地址
    }

   
    public void create() throws IOException {
        loadExecutionData();
 
        final IBundleCoverage bundleCoverage = analyzeStructure();

        createReport(bundleCoverage);

    }

    private void createReport(final IBundleCoverage bundleCoverage)
            throws IOException {
        final HTMLFormatter htmlFormatter = new HTMLFormatter();
        final IReportVisitor visitor = htmlFormatter
                .createVisitor(new FileMultiReportOutput(reportDirectory));
 
        visitor.visitInfo(execFileLoader.getSessionInfoStore().getInfos(),
                execFileLoader.getExecutionDataStore().getContents());
        visitor.visitBundle(bundleCoverage, new DirectorySourceFileLocator(
                sourceDirectory, "utf-8", 4));
        visitor.visitEnd();

    }

    private void loadExecutionData() throws IOException {
        execFileLoader = new ExecFileLoader();
        execFileLoader.load(executionDataFile);
    }

    private IBundleCoverage analyzeStructure() throws IOException {
        final CoverageBuilder coverageBuilder = new CoverageBuilder();
        final Analyzer analyzer = new Analyzer(
                execFileLoader.getExecutionDataStore(), coverageBuilder);

        analyzer.analyzeAll(classesDirectory);

        return coverageBuilder.getBundle(title);
    }
 
    public static void main(final String[] args) throws IOException {
    	Testjacoco generator = new Testjacoco(new File(""));
            generator.create();
    }
}

jar包还在刚才的jacoco/lib中有

然后在运行一个main方法,就有了刚才测试的覆盖率报告。

以下是生成的文件

java 代码覆盖率实现原理 java跑覆盖率_java 代码覆盖率实现原理_05

 

点开index.html就有刚才测试的覆盖率报告了。

java 代码覆盖率实现原理 java跑覆盖率_java 代码覆盖率实现原理_06

绿色是跑完了

黄色是只跑了一部分,比如&&只跑了左边没有跑右边

红色个就是没有跑过

 

java 代码覆盖率实现原理 java跑覆盖率_java 代码覆盖率实现原理_07

好了 大概就是这样,

虽然还没有达到自己想要的东西,还在不停的尝试。

下面是刚才两个代码的项目地址