diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
index 6e6eec114..79ee123c2 100644
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -1,6 +1,5 @@
-
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 902329bba..14fbe2f2f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@ We use [semantic versioning](http://semver.org/):
- [feature] Use git.commit.id from git.properties instead of branch and timestamp
- [breaking change] Reduce XML report size by only including source file coverage, no class coverage
- [feature] New option `--ignore-uncovered-classes` to further reduce size of XML reports
+- [fix] converter produces duplicate test entries for testwise coverage
# 15.5.0
- [feature] add TIA client library for integrating TIA in your custom test framework
diff --git a/agent/src/test/java/com/teamscale/jacoco/agent/convert/ConverterTest.java b/agent/src/test/java/com/teamscale/jacoco/agent/convert/ConverterTest.java
index 4f6fb819d..a93b715b7 100644
--- a/agent/src/test/java/com/teamscale/jacoco/agent/convert/ConverterTest.java
+++ b/agent/src/test/java/com/teamscale/jacoco/agent/convert/ConverterTest.java
@@ -5,6 +5,9 @@
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
import java.util.Collections;
import static org.assertj.core.api.Assertions.assertThat;
@@ -33,4 +36,39 @@ public void testSmokeTest(@TempDir File tempDir) throws Exception {
assertThat(xml).isNotEmpty().contains(" testExecutionsMap = new HashMap<>();
/** Holds all uniform paths for tests that have been written to the outputFile. */
- private final Set uniformPathsWithCoverage = new HashSet<>();
+ private final Set processedTestUniformPaths = new HashSet<>();
public TestInfoFactory(List testDetails, List testExecutions) {
for (TestDetails testDetail : testDetails) {
@@ -44,7 +44,7 @@ public TestInfoFactory(List testDetails, List testEx
*/
public TestInfo createFor(TestCoverageBuilder testCoverageBuilder) {
String resolvedUniformPath = resolveUniformPath(testCoverageBuilder.getUniformPath());
- uniformPathsWithCoverage.add(resolvedUniformPath);
+ processedTestUniformPaths.add(resolvedUniformPath);
TestInfoBuilder container = new TestInfoBuilder(resolvedUniformPath);
container.setCoverage(testCoverageBuilder);
@@ -65,11 +65,20 @@ public TestInfo createFor(TestCoverageBuilder testCoverageBuilder) {
public List createTestInfosWithoutCoverage() {
ArrayList results = new ArrayList<>();
for (TestDetails testDetails : testDetailsMap.values()) {
- if (uniformPathsWithCoverage.contains(testDetails.uniformPath)) {
+ if (!processedTestUniformPaths.contains(testDetails.uniformPath)) {
TestInfoBuilder testInfo = new TestInfoBuilder(testDetails.uniformPath);
testInfo.setDetails(testDetails);
testInfo.setExecution(testExecutionsMap.get(testDetails.uniformPath));
results.add(testInfo.build());
+ processedTestUniformPaths.add(testDetails.uniformPath);
+ }
+ }
+ for (TestExecution testExecution : testExecutionsMap.values()) {
+ if (!processedTestUniformPaths.contains(testExecution.getUniformPath())) {
+ System.err.println("Test " + testExecution.getUniformPath() + " was executed but no coverage was found. " +
+ "Please make sure that you did provide all relevant exec files and that the test IDs passed to " +
+ "the agent match the ones from the provided test execution list.");
+ processedTestUniformPaths.add(testExecution.getUniformPath());
}
}
return results;