写完代码先自测一下web项目或者接口
一般先跑findbug,再跑jacoco。
其实我一直在寻找一个在浏览器里面操作web项目,ide里面的代码颜色就会告诉你哪一行执行过,哪一行没有执行过。
还在研究中,有用过这样插件的或者有这样想法的可以私信我。
因为不是专业测试,懒得写测试case,jacoco可以省心很多。在代码业务比较繁琐的时候,可以在web中直接操作所有的功能,jacoco就可以告诉你有哪些分支还没有测试到,哪些分支已经测试过。
下面正文,如何使用jacoco跑覆盖率。
环境win10上,我这边的jdk是1.7的,tomcat7亲测可用。
https://www.eclemma.org/jacoco/
先上一波地址,进去download一个版本。
然后将其解压得到下面的目录结构。
lib下面是我们主要用的jar包
打开myeclipse,windows>prefernces>MyEclipse>tomcat>tomcat 7x>jdk
上面那句是配置内存的,不管他,主要是下面那句配置(当然这个配置可以配置在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文件。
现在我们来用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方法,就有了刚才测试的覆盖率报告。
以下是生成的文件
点开index.html就有刚才测试的覆盖率报告了。
绿色是跑完了
黄色是只跑了一部分,比如&&只跑了左边没有跑右边
红色个就是没有跑过
好了 大概就是这样,
虽然还没有达到自己想要的东西,还在不停的尝试。
下面是刚才两个代码的项目地址