我在使用evosuite时与jacoco产生了冲突导致jacoco代码覆盖率为0,找到了原因所在处,是自动生成代码的配置在pom文件中不生效,问题出在哪里。下面是官方文档的错误产生内容及解决方案和我的部分代码。
现在我希望的是pom文件中的配置能够生效,自动生成的Test中separateClassLoader = false。
官方文档https://www.evosuite.org/documentation/measuring-code-coverage/
pom文件
<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.coderdream</groupId>
<artifactId>bsTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ant-demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<evosuiteVersion>1.0.6</evosuiteVersion>
<customFolder>src/test/java</customFolder>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.evosuite</groupId>
<artifactId>evosuite-standalone-runtime</artifactId>
<version>${evosuiteVersion}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.evosuite.plugins</groupId>
<artifactId>evosuite-maven-plugin</artifactId>
<version>${evosuiteVersion}</version>
<configuration>
<extraArgs>-Duse_separate_classloader=false</extraArgs>
</configuration>
<executions><execution>
<goals> <goal> prepare </goal> </goals>
<phase> process-test-classes </phase>
</execution></executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>org.evosuite.runtime.InitializingListener</value>
</property>
</properties>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${customFolder}</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
ANT build文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:jacoco="antlib:org.jacoco.ant" name="bsTest" default="all" basedir=".">
<!--源代码src路径-->
<property name="src.dir" value="src/main/java"/>
<!--单元测试代码路径-->
<property name="test.dir" value="src/test/java"/>
<!--编译文件class路径-->
<property name="build.dir" value="build"/>
<!--lib包路径-->
<property name="lib.dir" value="lib"/>
<!--生成报告Junit4.xml路径-->
<property name="report.dir" value="report"/>
<property name="MAVEN_HOME" value="C:\Program Files\JetBrains\IntelliJ IDEA 2020.2\plugins\maven\lib\maven3"/>
<!--jacoco-->
<property name="result.dir" location="./target"/>
<property name="result.report.dir" location="${result.dir}/site/jacoco"/>
<property name="result.exec.file" location="${result.dir}/jacoco.exec"/>
<!--<property name="jacocoantPath" location="lib/jacocoant.jar"/>-->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="lib/jacocoant.jar"/>
</taskdef>
<!--设置classpath-->
<path id="compile.path">
<fileset dir="${lib.dir}">
<include name="**/*.jar"/>
</fileset>
<pathelement path="${build.dir}"/>
</path>
<!--初始化,新建文件夹-->
<target name="init">
<mkdir dir="${build.dir}"/>
<mkdir dir="${report.dir}"/>
</target>
<!--清除-->
<target name="clean" description="clean">
<delete dir="${build.dir}"/>
<delete dir="${report.dir}"/>
<delete dir="${result.dir}"/>
<delete dir="${test.dir}"/>
</target>
<!--调用maven的evosuite命令生成Junit测试用例,每个参数必须占据一行-->
<target name="compile-evosuite">
<exec executable="mvn.cmd">
<arg value="-f"/>
<arg value="D:/mycode/bsTest/pom.xml"/>
<arg value="compile"/>
<!--<arg value="-Dcores=4"/>-->
<!--<arg value="-Duse_separate_classloader=false"/>-->
<arg value="-DtargetFolder=src/test/java"/>
<arg value="evosuite:generate"/>
<arg value="evosuite:export"/>
</exec>
</target>
<!--编译测试文件,初始化目录-->
<target name="compile" description="编译">
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="compile.path" includeantruntime="on" debug="true"/>
<javac srcdir="${test.dir}" destdir="${build.dir}" classpathref="compile.path" includeantruntime="on" debug="true"/>
</target>
<!--执行测试案例-->
<target name="junit">
<jacoco:coverage destfile="${result.exec.file}">
<junit printsummary="true" fork="true">
<formatter type="xml" usefile="true"/>
<classpath>
<!--添加测试用例目录-->
<pathelement location="${build.dir}"/>
<!--添加依赖库-->
<path refid="compile.path"/>
</classpath>
<!--执行多个测试用例-->
<batchtest fork="on" todir="${report.dir}" haltonfailure="no">
<fileset dir="${build.dir}">
<include name="**/*Test.class"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<!-- 产生单元测试报表文档 -->
<junitreport todir="${report.dir}">
<fileset dir="${report.dir}">
<include name="TEST-*.xml"/>
</fileset>
<report format="frames" todir="${report.dir}"/>
</junitreport>
</target>
<!-- 生成覆盖率报告 -->
<target name="report">
<jacoco:report>
<executiondata>
<file file="${result.exec.file}" />
</executiondata>
<structure name="JaCoCo Ant Example">
<classfiles>
<!--覆盖率报告的类-->
<fileset dir="${build.dir}" />
</classfiles>
<sourcefiles encoding="UTF-8">
<fileset dir="${src.dir}" />
</sourcefiles>
</structure>
<html destdir="${result.report.dir}" />
<csv destfile="${result.report.dir}/report.csv" />
<xml destfile="${result.report.dir}/report.xml" />
</jacoco:report>
</target>
<target name="all" depends="clean,init,compile-evosuite,compile,junit,report"/>
</project>
自动生成的一个测试用例
/*
* This file was automatically generated by EvoSuite
* Wed Apr 12 08:33:13 GMT 2023
*/
import org.junit.Test;
import static org.junit.Assert.*;
import static org.evosuite.runtime.EvoAssertions.*;
import org.evosuite.runtime.EvoRunner;
import org.evosuite.runtime.EvoRunnerParameters;
import org.junit.runner.RunWith;
@RunWith(EvoRunner.class) @EvoRunnerParameters(mockJVMNonDeterminism = true, useVFS = true, useVNET = true, resetStaticState = true, separateClassLoader = true, useJEE = true)
public class ComplexCalculation_ESTest extends ComplexCalculation_ESTest_scaffolding {
@Test(timeout = 4000)
public void test0() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
int int0 = complexCalculation0.Multiply(0, 0);
assertEquals(0, int0);
}
@Test(timeout = 4000)
public void test1() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
int int0 = complexCalculation0.Multiply((-3998), (-1933));
assertEquals(7728134, int0);
}
@Test(timeout = 4000)
public void test2() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
int int0 = complexCalculation0.Division(1558, (-18696));
assertEquals(0, int0);
}
@Test(timeout = 4000)
public void test3() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
int int0 = complexCalculation0.Division((-1610), 130);
assertEquals((-12), int0);
}
@Test(timeout = 4000)
public void test4() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
// Undeclared exception!
try {
complexCalculation0.Division(1, 0);
fail("Expecting exception: ArithmeticException");
} catch(ArithmeticException e) {
//
// / by zero
//
verifyException("ComplexCalculation", e);
}
}
@Test(timeout = 4000)
public void test5() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
int int0 = complexCalculation0.Multiply((-1610), 864);
assertEquals((-1391040), int0);
}
@Test(timeout = 4000)
public void test6() throws Throwable {
ComplexCalculation complexCalculation0 = new ComplexCalculation();
int int0 = complexCalculation0.Division((-1610), (-1610));
assertEquals(1, int0);
}
}
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在你的pom文件中,你把evosuite-maven-plugin
插件的configuration
标签单独提出来了,并放在了pluginManagement
标签下。但是,pluginManagement
只是用来管理插件版本的,所以你需要将evosuite-maven-plugin
插件的配置放到实际的plugins
标签下面。
修改pom文件如下:
<build>
<plugins>
<plugin>
<groupId>org.evosuite.plugins</groupId>
<artifactId>evosuite-maven-plugin</artifactId>
<version>${evosuiteVersion}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<use_separate_classloader>false</use_separate_classloader>
</configuration>
</execution>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<properties>
<property>
<name>listener</name>
<value>org.evosuite.runtime.report.data.JUnit4TestFrameworkEmitter</value>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
上面的代码将evosuite-maven-plugin
插件的配置放在了插件内部的executions
标签下,并添加了一个export
的目标用于将测试用例导出到文件中。同时,也修改了maven-surefire-plugin
插件的版本号。
修改完pom文件之后,你需要运行mvn clean install
来重新构建你的项目,确保这些配置在生成的测试代码中生效。
另外,在你的ANT build文件中,你需要确保地址lib/jacocoant.jar
确实存在。如果不存在,你需要将该包从其他地方拷贝过来(例如,从一个Maven项目中)。
上述修改可能没有考虑到你的具体情况,并不保证一定有效,但是按照上述的方向进行修改,应该可以解决你遇到的问题。
如果我的回答解决了您的问题,请采纳!
你可以检查以下几点来解决这个问题:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>generate-test</id>
<phase>generate-test-sources</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.evosuite.EvoSuite</mainClass>
<arguments>
<argument>-projectCP</argument>
<classpath/>
<argument>-class</argument>
<class-to-test/>
<argument>-generateSuite</argument>
<argument>-Djacoco-agent.path=/path/to/jacoco/agent.jar</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
问题出在自动生成的代码中的 separateClassLoader 配置无法生效,导致 Jacoco 代码覆盖率为 0。
解决这个问题的一种方法是,在 pom.xml 文件中,将 evosuite 插件的配置添加到 maven-surefire-plugin 插件的配置中,以确保配置能够生效。具体来说,您需要在 maven-surefire-plugin 插件的 标签中添加以下配置:
<argLine>-Duse_separate_classloader=false</argLine>
这样可以禁用自动生成的测试代码的 separateClassLoader,以确保它们与 Jacoco 代码覆盖率的测量能够正常工作。
下面是示例代码,展示了如何将 evosuite 插件的配置添加到 maven-surefire-plugin 插件的配置中:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<argLine>-Duse_separate_classloader=false</argLine>
<properties>
<property>
<name>listener</name>
<value>org.apache.maven.surefire.junit4.JUnit4Provider</value>
</property>
</properties>
</configuration>
</plugin>
<plugin>
<groupId>org.evosuite.plugins</groupId>
<artifactId>evosuite-maven-plugin</artifactId>
<version>1.0.6</version>
<configuration>
<!-- Add your Evosuite configuration here -->
</configuration>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
您可以将上面的代码添加到您的 pom.xml 文件中,并根据需要修改 evosuite 插件的配置,以确保自动生成的测试代码能够正常运行并与 Jacoco 代码覆盖率测量配合使用。
你好,针对你的情况,你可以尝试按照如下步骤解决:
1.在pom.xml中添加以下配置信息:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Duser.language=en -Duser.region=US -noverify -XX:-UseSplitVerifier -Xmx512m -Dfile.encoding=UTF-8</argLine>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<childDelegation>true</childDelegation>
<useSystemClassLoader>false</useSystemClassLoader>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<systemProperties>
<property>
<name>evosuite.testclass</name>
<value>${test}</value>
</property>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
2.添加jacoco的配置信息(如已添加请忽略):
<project>
...
<reporting>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-unit.exec</destFile>
<dataFile>${project.build.directory}/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
</configuration>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</reporting>
...
</project>
3.执行以下命令生成测试用例:
mvn evosuite:generate evosuite:export
通过执行以上步骤,你可以实现在pom文件中进行自动生成代码的配置,其中separateClassLoader = false 是默认配置,无需额外添加。同时,注意确保 Jacoco 插件和 EvoSuite 插件的版本兼容性,这样你就能够正确使用 EvoSuite 和 Jacoco 了,希望对你有所帮助!