diff --git a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/source/SourceViewModel/index.properties b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/source/SourceViewModel/index.properties
index be06b04d5..6f7147695 100644
--- a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/source/SourceViewModel/index.properties
+++ b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/source/SourceViewModel/index.properties
@@ -1,8 +1,8 @@
 reason.1=\
-  You did not enable storing of source files (see parameter 'sourceFiles').
+  You did not enable storing of source files (see parameter 'sourceCodeRetention').
 
 reason.2=\
-  Code Coverage API plugin did not find the source files.
+  Code Coverage plugin did not find the source files.
 
 reason.3=\
   You do not have sufficient permissions to view source files.
diff --git a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageQualityGate/help-criticality.html b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageQualityGate/help-criticality.html
index e2322e414..5eb583672 100644
--- a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageQualityGate/help-criticality.html
+++ b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageQualityGate/help-criticality.html
@@ -11,7 +11,7 @@
         
         FAILURE
         
-            Fail the build if the quality gate has been missed.
+            Fail the step if the quality gate has been missed.
         
     
 
diff --git a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageRecorder/help-failOnError.html b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageRecorder/help-failOnError.html
index c5deb289f..ee8c20f36 100644
--- a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageRecorder/help-failOnError.html
+++ b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageRecorder/help-failOnError.html
@@ -1,6 +1,6 @@
 
-    This toggle determines if the coverage plugin should fail the build whenever an error occurred during processing
+    This toggle determines if the coverage plugin should fail the step whenever an error occurred during processing
     of the coverage results. Several errors might occur: file pattern matches no files, source files
     could not be copied, etc. By default, these errors are logged in a separate view but the build status will
-    not be altered. If you would rather like to fail the build on such errors, please tick this checkbox.
+    not be altered. If you would rather like to fail the step on such errors, please tick this checkbox.
 
diff --git a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageStep/help-failOnError.html b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageStep/help-failOnError.html
index c5deb289f..ee8c20f36 100644
--- a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageStep/help-failOnError.html
+++ b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/CoverageStep/help-failOnError.html
@@ -1,6 +1,6 @@
 
-    This toggle determines if the coverage plugin should fail the build whenever an error occurred during processing
+    This toggle determines if the coverage plugin should fail the step whenever an error occurred during processing
     of the coverage results. Several errors might occur: file pattern matches no files, source files
     could not be copied, etc. By default, these errors are logged in a separate view but the build status will
-    not be altered. If you would rather like to fail the build on such errors, please tick this checkbox.
+    not be altered. If you would rather like to fail the step on such errors, please tick this checkbox.
 
diff --git a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/Messages.properties b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/Messages.properties
index 7ac7b2960..0beb594c7 100644
--- a/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/Messages.properties
+++ b/plugin/src/main/resources/io/jenkins/plugins/coverage/metrics/steps/Messages.properties
@@ -16,7 +16,7 @@ Change_Coverage_Type=Change Coverage
 Change_Coverage_Delta_Type=Change Coverage Delta
 Indirect_Coverage_Changes_Type=Indirect Coverage Changes
 
-QualityGate.Failure=Fail the build if the quality gate has been missed
+QualityGate.Failure=Fail the step if the quality gate has been missed
 QualityGate.Unstable=Set the build status to unstable if the quality gate has been missed
 
 Column.File=File
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeFacadeTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeFacadeTest.java
index b757075fe..bb7ffd164 100644
--- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeFacadeTest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeFacadeTest.java
@@ -59,7 +59,7 @@ private SourceCodeFacade createSourceCodeFacade() {
     }
 
     private FileNode createFileCoverageNode() {
-        FileNode file = new FileNode("");
+        FileNode file = new FileNode("", "path");
         List lines = Arrays.asList(10, 11, 12, 16, 17, 18, 19);
         for (Integer line : lines) {
             file.addModifiedLines(line);
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java
index b8b5492e2..0dd78efa6 100644
--- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/source/SourceCodeITest.java
@@ -2,14 +2,17 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Paths;
 import java.util.List;
 import java.util.Optional;
 
 import org.junit.jupiter.api.Test;
 
 import edu.hm.hafner.coverage.Coverage.CoverageBuilder;
+import edu.hm.hafner.coverage.FileNode;
 import edu.hm.hafner.coverage.Metric;
 import edu.hm.hafner.coverage.Node;
+import edu.hm.hafner.util.PathUtil;
 
 import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
 import org.jenkinsci.plugins.workflow.job.WorkflowJob;
@@ -45,6 +48,7 @@ abstract class SourceCodeITest extends AbstractCoverageITest {
     static final String PATH_UTIL_PACKAGE_PATH = "edu/hm/hafner/util/";
     private static final String PATH_UTIL_SOURCE_FILE_PATH = PATH_UTIL_PACKAGE_PATH + PATH_UTIL_FILE_NAME;
     static final String AGENT_LABEL = "coverage-agent";
+    private static final PathUtil UTIL = new PathUtil();
 
     /** Verifies that the plugin reads source code from the workspace root. */
     @Test
@@ -76,7 +80,8 @@ void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException
         String sourceDirectory = createExternalFolder();
 
         WorkflowJob job = createPipeline();
-        copySourceFileToAgent("ignore/", localAgent, job);
+        var subFolder = "ignore/";
+        copySourceFileToAgent(subFolder, localAgent, job);
         copyReports(localAgent, job);
 
         job.setDefinition(createPipelineWithSourceCode(EVERY_BUILD, sourceDirectory));
@@ -84,22 +89,23 @@ void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException
         Run, ?> firstBuild = buildSuccessfully(job);
 
         assertThat(getConsoleLog(firstBuild))
+                .contains("-> finished resolving of absolute paths (found: 0, not found: 1)")
                 .contains("-> finished painting (0 files have been painted, 1 files failed)")
                 .contains(String.format(
                         "[-ERROR-] Removing source directory '%s' - it has not been approved in Jenkins' global configuration.",
                         sourceDirectory));
 
-        verifySourceCodeInBuild(firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
+        verifySourceCodeInBuild("", firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
         localAgent.setLabelString("");
     }
 
-    private Run, ?> runCoverageWithSourceCode(final String sourceDirectory)
+    private Run, ?> runCoverageWithSourceCode(final String sourceDir)
             throws IOException {
         var localAgent = crateCoverageAgent();
 
         WorkflowJob job = createPipeline();
         copyReports(localAgent, job);
-        copySourceFileToAgent(sourceDirectory, localAgent, job);
+        copySourceFileToAgent(sourceDir, localAgent, job);
 
         // get the temporary directory - used by unit tests - to verify its content
         File temporaryDirectory = new File(System.getProperty("java.io.tmpdir"));
@@ -107,28 +113,29 @@ void coveragePluginPipelineNotRegisteredSourceCodeDirectory() throws IOException
         assertThat(temporaryDirectory.isDirectory()).isTrue();
         File[] temporaryFiles = temporaryDirectory.listFiles();
 
-        job.setDefinition(createPipelineWithSourceCode(EVERY_BUILD, sourceDirectory));
+        job.setDefinition(createPipelineWithSourceCode(EVERY_BUILD, sourceDir));
         Run, ?> firstBuild = buildSuccessfully(job);
         assertThat(getConsoleLog(firstBuild))
+                .contains("-> resolved absolute paths for all 1 source files")
                 .contains("-> finished painting successfully");
-        verifySourceCodeInBuild(firstBuild, ACU_COBOL_PARSER, PATH_UTIL);
+        verifySourceCodeInBuild(sourceDir, firstBuild, ACU_COBOL_PARSER, PATH_UTIL);
 
         Run, ?> secondBuild = buildSuccessfully(job);
-        verifySourceCodeInBuild(secondBuild, ACU_COBOL_PARSER, PATH_UTIL);
-        verifySourceCodeInBuild(firstBuild, ACU_COBOL_PARSER, PATH_UTIL); // should be still available
+        verifySourceCodeInBuild(sourceDir, secondBuild, ACU_COBOL_PARSER, PATH_UTIL);
+        verifySourceCodeInBuild(sourceDir, firstBuild, ACU_COBOL_PARSER, PATH_UTIL); // should be still available
 
-        job.setDefinition(createPipelineWithSourceCode(LAST_BUILD, sourceDirectory));
+        job.setDefinition(createPipelineWithSourceCode(LAST_BUILD, sourceDir));
         Run, ?> thirdBuild = buildSuccessfully(job);
-        verifySourceCodeInBuild(thirdBuild, ACU_COBOL_PARSER, PATH_UTIL);
-        verifySourceCodeInBuild(firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
-        verifySourceCodeInBuild(secondBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
+        verifySourceCodeInBuild(sourceDir, thirdBuild, ACU_COBOL_PARSER, PATH_UTIL);
+        verifySourceCodeInBuild(sourceDir, firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
+        verifySourceCodeInBuild(sourceDir, secondBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
 
-        job.setDefinition(createPipelineWithSourceCode(NEVER, sourceDirectory));
+        job.setDefinition(createPipelineWithSourceCode(NEVER, sourceDir));
         Run, ?> lastBuild = buildSuccessfully(job);
-        verifySourceCodeInBuild(lastBuild, NO_SOURCE_CODE, NO_SOURCE_CODE);
-        verifySourceCodeInBuild(firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
-        verifySourceCodeInBuild(secondBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
-        verifySourceCodeInBuild(thirdBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
+        verifySourceCodeInBuild(sourceDir, lastBuild, NO_SOURCE_CODE, NO_SOURCE_CODE);
+        verifySourceCodeInBuild(sourceDir, firstBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
+        verifySourceCodeInBuild(sourceDir, secondBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
+        verifySourceCodeInBuild(sourceDir, thirdBuild, NO_SOURCE_CODE, NO_SOURCE_CODE); // should be still available
 
         assertThat(temporaryDirectory.listFiles()).isEqualTo(temporaryFiles);
 
@@ -157,31 +164,37 @@ private CpsFlowDefinition createPipelineWithSourceCode(final SourceCodeRetention
                 + "}", true);
     }
 
-    private void verifySourceCodeInBuild(final Run, ?> build, final String acuCobolParserSourceCodeSnippet,
+    private void verifySourceCodeInBuild(final String pathPrefix, final Run, ?> build, final String acuCobolParserSourceCodeSnippet,
             final String pathUtilSourceCodeSnippet) {
         List actions = build.getActions(CoverageBuildAction.class);
         var builder = new CoverageBuilder().setMetric(Metric.LINE).setMissed(0);
         assertThat(actions).hasSize(2).satisfiesExactly(
                 action -> {
                     assertThat(action.getAllValues(Baseline.PROJECT)).contains(builder.setCovered(8).build());
-                    Optional fileNode = action.getResult().find(Metric.FILE, ACU_COBOL_PARSER_SOURCE_FILE_PATH);
-                    assertThat(fileNode).isNotEmpty()
-                            .hasValueSatisfying(node -> assertThat(node.getPath()).isEqualTo(
-                                    ACU_COBOL_PARSER_SOURCE_FILE_PATH));
-                    assertThat(action.getTarget().getSourceCode(String.valueOf(ACU_COBOL_PARSER_SOURCE_FILE_PATH.hashCode()), "coverage-table"))
+                    var relativePath = getRelativePath(pathPrefix, ACU_COBOL_PARSER_SOURCE_FILE_PATH);
+                    Optional fileNode = action.getResult().find(Metric.FILE, relativePath);
+                    assertThat(fileNode).isNotEmpty().get()
+                            .isInstanceOfSatisfying(FileNode.class,
+                                    node -> assertThat(node.getRelativePath()).isEqualTo(relativePath));
+                    assertThat(action.getTarget().getSourceCode(String.valueOf(relativePath.hashCode()), "coverage-table"))
                             .contains(acuCobolParserSourceCodeSnippet);
                 },
                 action -> {
                     assertThat(action.getAllValues(Baseline.PROJECT)).contains(builder.setCovered(43).build());
-                    Optional fileNode = action.getResult().find(Metric.FILE, PATH_UTIL_SOURCE_FILE_PATH);
-                    assertThat(fileNode).isNotEmpty()
-                            .hasValueSatisfying(node -> assertThat(node.getPath()).isEqualTo(
-                                    PATH_UTIL_SOURCE_FILE_PATH));
-                    assertThat(action.getTarget().getSourceCode(String.valueOf(PATH_UTIL_SOURCE_FILE_PATH.hashCode()), "coverage-table"))
+                    var relativePath = getRelativePath(pathPrefix, PATH_UTIL_SOURCE_FILE_PATH);
+                    Optional fileNode = action.getResult().find(Metric.FILE, relativePath);
+                    assertThat(fileNode).isNotEmpty().get()
+                            .isInstanceOfSatisfying(FileNode.class,
+                                    node -> assertThat(node.getRelativePath()).isEqualTo(relativePath));
+                    assertThat(action.getTarget().getSourceCode(String.valueOf(relativePath.hashCode()), "coverage-table"))
                             .contains(pathUtilSourceCodeSnippet);
                 });
     }
 
+    private String getRelativePath(final String path, final String filePath) {
+        return UTIL.getRelativePath(Paths.get(path, filePath));
+    }
+
     String createDestinationPath(final String sourceDirectory, final String packagePath, final String fileName) {
         if (sourceDirectory.isEmpty()) {
             return packagePath + fileName;
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CodeDeltaCalculatorTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CodeDeltaCalculatorTest.java
index 7a92e596a..1c8724ede 100644
--- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CodeDeltaCalculatorTest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CodeDeltaCalculatorTest.java
@@ -118,7 +118,7 @@ void shouldNotMapScmChangesWithAmbiguousPaths() throws IllegalStateException {
 
         Node tree = mock(Node.class);
         FileNode file1 = mock(FileNode.class);
-        when(file1.getPath()).thenReturn(path);
+        when(file1.getRelativePath()).thenReturn(path);
         when(tree.getAllFileNodes()).thenReturn(List.of(file1));
         when(tree.getFiles()).thenReturn(Set.of(path));
 
@@ -150,8 +150,8 @@ void shouldNotCreateOldPathMappingWithMissingReferenceNodes() throws IllegalStat
         CodeDeltaCalculator codeDeltaCalculator = createCodeDeltaCalculator();
         FilteredLog log = createFilteredLog();
 
-        Node tree = new FileNode(REPORT_PATH_RENAME);
-        Node referenceTree = new FileNode(REPORT_PATH_MODIFY);
+        Node tree = new FileNode("Test_Renamed.java", REPORT_PATH_RENAME);
+        Node referenceTree = new FileNode("Test.java", REPORT_PATH_MODIFY);
         Map changes = new HashMap<>();
         changes.put(REPORT_PATH_RENAME, createFileChanges(SCM_PATH_RENAME, OLD_SCM_PATH_RENAME, FileEditType.RENAME));
 
@@ -257,16 +257,16 @@ private FileChanges createFileChanges(final String filePath, final String oldFil
      */
     private Node createStubbedCoverageTree() {
         FileNode addFile1 = mock(FileNode.class);
-        when(addFile1.getPath()).thenReturn(REPORT_PATH_ADD_1);
+        when(addFile1.getRelativePath()).thenReturn(REPORT_PATH_ADD_1);
         FileNode addFile2 = mock(FileNode.class);
-        when(addFile2.getPath()).thenReturn(REPORT_PATH_ADD_2);
+        when(addFile2.getRelativePath()).thenReturn(REPORT_PATH_ADD_2);
         FileNode modifyFile = mock(FileNode.class);
-        when(modifyFile.getPath()).thenReturn(REPORT_PATH_MODIFY);
+        when(modifyFile.getRelativePath()).thenReturn(REPORT_PATH_MODIFY);
         FileNode renameFile = mock(FileNode.class);
-        when(renameFile.getPath()).thenReturn(REPORT_PATH_RENAME);
+        when(renameFile.getRelativePath()).thenReturn(REPORT_PATH_RENAME);
         Node root = mock(Node.class);
         when(root.getAllFileNodes()).thenReturn(Arrays.asList(addFile1, addFile2, modifyFile, renameFile));
-        var files = root.getAllFileNodes().stream().map(FileNode::getPath).collect(Collectors.toSet());
+        var files = root.getAllFileNodes().stream().map(FileNode::getRelativePath).collect(Collectors.toSet());
         when(root.getFiles()).thenReturn(files);
 
         return root;
@@ -280,12 +280,12 @@ private Node createStubbedCoverageTree() {
      */
     private Node createStubbedReferenceCoverageTree() {
         FileNode modifyFile = mock(FileNode.class);
-        when(modifyFile.getPath()).thenReturn(REPORT_PATH_MODIFY);
+        when(modifyFile.getRelativePath()).thenReturn(REPORT_PATH_MODIFY);
         FileNode renameFile = mock(FileNode.class);
-        when(renameFile.getPath()).thenReturn(OLD_REPORT_PATH_RENAME);
+        when(renameFile.getRelativePath()).thenReturn(OLD_REPORT_PATH_RENAME);
         Node root = mock(Node.class);
         when(root.getAllFileNodes()).thenReturn(Arrays.asList(renameFile, modifyFile));
-        var files = root.getAllFileNodes().stream().map(FileNode::getPath).collect(Collectors.toSet());
+        var files = root.getAllFileNodes().stream().map(FileNode::getRelativePath).collect(Collectors.toSet());
         when(root.getFiles()).thenReturn(files);
 
         return root;
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoveragePluginITest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoveragePluginITest.java
index 1c2d3b276..bf3eb96c3 100644
--- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoveragePluginITest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoveragePluginITest.java
@@ -151,8 +151,8 @@ private static void verifyJaCoCoAction(final CoverageBuildAction coverageResult)
                         Metric.BRANCH,
                         Metric.INSTRUCTION,
                         Metric.COMPLEXITY,
-                        Metric.COMPLEXITY_DENSITY,
                         Metric.COMPLEXITY_MAXIMUM,
+                        Metric.COMPLEXITY_DENSITY,
                         Metric.LOC);
         assertThat(coverageResult.getMetricsForSummary())
                 .containsExactly(Metric.LINE, Metric.BRANCH, Metric.MUTATION, Metric.COMPLEXITY_DENSITY, Metric.LOC);
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModelTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModelTest.java
index 6c9cdfa2f..09713a91e 100644
--- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModelTest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageViewModelTest.java
@@ -78,7 +78,7 @@ void shouldProvideIndirectCoverageChanges() {
     private Node createIndirectCoverageChangesNode() {
         var root = new ModuleNode("root");
         for (int file = 0; file < 5; file++) {
-            var fileNode = new FileNode("File-" + file);
+            var fileNode = new FileNode("File-" + file, "path");
 
             for (int line = 0; line < 2; line++) {
                 fileNode.addCounters(10 + line, 1, 1);
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageXmlStreamTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageXmlStreamTest.java
index 23d4e14e5..804cdf547 100644
--- a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageXmlStreamTest.java
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/CoverageXmlStreamTest.java
@@ -112,8 +112,8 @@ void shouldStoreActionCompactly() throws IOException {
                         "BRANCH: 109/116",
                         "INSTRUCTION: 1260/1350",
                         "COMPLEXITY: 160",
-                        "COMPLEXITY_DENSITY: 160/323",
                         "COMPLEXITY_MAXIMUM: 6",
+                        "COMPLEXITY_DENSITY: 160/323",
                         "LOC: 323");
 
         assertThat(Input.from(saved)).nodesByXPath("//" + ACTION_QUALIFIED_NAME + "/projectValues/coverage")
@@ -130,11 +130,11 @@ void shouldStoreActionCompactly() throws IOException {
         var action = file.read();
         assertThat(action).isNotNull().isInstanceOfSatisfying(CoverageBuildAction.class, a ->
                 Assertions.assertThat(serializeValues(a))
-                        .containsExactly("MODULE: 1/1",
-                                "PACKAGE: 1/1", "FILE: 7/10", "CLASS: 15/18",
-                                "METHOD: 97/102", "LINE: 294/323", "BRANCH: 109/116",
-                                "INSTRUCTION: 1260/1350", "COMPLEXITY: 160",
-                                "COMPLEXITY_DENSITY: 160/323", "COMPLEXITY_MAXIMUM: 6", "LOC: 323"
+                        .containsExactly("MODULE: 1/1", "PACKAGE: 1/1", "FILE: 7/10", "CLASS: 15/18",
+                                "METHOD: 97/102",
+                                "LINE: 294/323", "BRANCH: 109/116", "INSTRUCTION: 1260/1350",
+                                "COMPLEXITY: 160", "COMPLEXITY_MAXIMUM: 6", "COMPLEXITY_DENSITY: 160/323",
+                                "LOC: 323"
                         ));
     }
 
diff --git a/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/PathResolverTest.java b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/PathResolverTest.java
new file mode 100644
index 000000000..1876e1d88
--- /dev/null
+++ b/plugin/src/test/java/io/jenkins/plugins/coverage/metrics/steps/PathResolverTest.java
@@ -0,0 +1,35 @@
+package io.jenkins.plugins.coverage.metrics.steps;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+
+import io.jenkins.plugins.coverage.metrics.steps.PathResolver.RemoteResultWrapper;
+
+import static org.assertj.core.api.Assertions.*;
+
+class PathResolverTest {
+    @Nested
+    class RemoteResultWrapperTest {
+        @Test
+        void shouldCreateWrapper() {
+            var result = "result";
+
+            var wrapper = new RemoteResultWrapper<>(result, "title");
+
+            assertThat(wrapper.getResult()).isEqualTo(result);
+
+            wrapper.logInfo("Hello %s", "World");
+            assertThat(wrapper.getInfoMessages()).containsExactly("Hello World");
+        }
+
+        @Test
+        void shouldAdhereToEquals() {
+            EqualsVerifier.simple().forClass(RemoteResultWrapper.class)
+                    .suppress(Warning.NULL_FIELDS)
+                    .verify();
+        }
+    }
+}
diff --git a/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result b/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result
index 896556689..f89d9824e 100644
--- a/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result
+++ b/plugin/src/test/resources/io/jenkins/plugins/coverage/metrics/steps/coverage-publisher-summary.checks-expected-result
@@ -1,5 +1,6 @@
-Modified lines summary:
-- 1 line has been modified
+#### Summary for modified lines
+
+- 3 lines have been modified
 - 1 line is not covered
 - 1 line is covered only partially