diff --git a/modules/core/src/main/java/org/approvej/approve/StackTraceTestFinderUtil.java b/modules/core/src/main/java/org/approvej/approve/StackTraceTestFinderUtil.java index 8018603..6e1f0b4 100644 --- a/modules/core/src/main/java/org/approvej/approve/StackTraceTestFinderUtil.java +++ b/modules/core/src/main/java/org/approvej/approve/StackTraceTestFinderUtil.java @@ -6,6 +6,7 @@ import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.Optional; import java.util.stream.Stream; import org.jspecify.annotations.NullMarked; @@ -67,7 +68,7 @@ public static Path findTestSourcePath(Method testMethod) { .replace("-classes", ""); String packagePath = declaringClass.getPackageName().replace(".", "/"); String pathRegex = - "(?!build|target).*%s.*/%s/%s\\.(java|kt|groovy|scala)$" + "(?!(?:build|target|bin|out)/).*%s.*/%s/%s\\.(java|kt|groovy|scala)$" .formatted(sourceSetName, packagePath, declaringClass.getSimpleName()); try (Stream pathStream = Files.find( @@ -75,10 +76,21 @@ public static Path findTestSourcePath(Method testMethod) { packageDepth + 10, (path, attributes) -> attributes.isRegularFile() && path.normalize().toString().matches(pathRegex))) { - return pathStream - .findFirst() - .map(Path::normalize) - .orElseThrow(() -> new FileApproverError("Could not locate test source file")); + List matches = pathStream.map(Path::normalize).toList(); + return switch (matches.size()) { + case 0 -> throw new FileApproverError("Could not locate test source file"); + case 1 -> matches.getFirst(); + default -> { + List srcMatches = + matches.stream().filter(path -> path.toString().contains("src")).toList(); + if (srcMatches.size() == 1) { + yield srcMatches.getFirst(); + } + throw new FileApproverError( + "Found multiple test source files (%d contain 'src'): %s" + .formatted(srcMatches.size(), matches)); + } + }; } catch (IOException e) { throw new FileApproverError("Could not traverse code directory", e); } diff --git a/modules/core/src/test/java/org/approvej/approve/StackTraceTestFinderUtilTest.java b/modules/core/src/test/java/org/approvej/approve/StackTraceTestFinderUtilTest.java index 1e9dd5e..d14bd0f 100644 --- a/modules/core/src/test/java/org/approvej/approve/StackTraceTestFinderUtilTest.java +++ b/modules/core/src/test/java/org/approvej/approve/StackTraceTestFinderUtilTest.java @@ -3,6 +3,7 @@ import static java.nio.file.Files.copy; import static java.nio.file.Files.createDirectories; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.io.IOException; import java.lang.reflect.Method; @@ -61,11 +62,17 @@ void findTestSourcePath() { assertThat(testSourcePath).isEqualTo(thisTestSourcePath.normalize()); } - @Test - void findTestSourcePath_file_in_build() throws IOException { - Path wrongTestSourcePath = - Path.of( - "build/spotless-clean/spotlessJava/java/test/org/approvej/approve/StackTraceTestFinderUtilTest.java"); + @ParameterizedTest + @ValueSource( + strings = { + "build/spotless-clean/spotlessJava/java/test/org/approvej/approve/StackTraceTestFinderUtilTest.java", + "target/spotless-clean/spotlessJava/java/test/org/approvej/approve/StackTraceTestFinderUtilTest.java", + "bin/test/org/approvej/approve/StackTraceTestFinderUtilTest.java", + "out/test/org/approvej/approve/StackTraceTestFinderUtilTest.java", + "other/test/java/org/approvej/approve/StackTraceTestFinderUtilTest.java", + }) + void findTestSourcePath_duplicate_file(String wrongPath) throws IOException { + Path wrongTestSourcePath = Path.of(wrongPath); wrongTestSourcePathsToCleanup.add(wrongTestSourcePath); createDirectories(wrongTestSourcePath.getParent()); copy(thisTestSourcePath, wrongTestSourcePath); @@ -78,18 +85,27 @@ void findTestSourcePath_file_in_build() throws IOException { } @Test - void findTestSourcePath_file_in_target() throws IOException { + void findTestSourcePath_no_source_file() throws NoSuchMethodException { + Method method = + org.assertj.core.api.Assertions.class.getDeclaredMethod("assertThat", boolean.class); + + assertThatThrownBy(() -> StackTraceTestFinderUtil.findTestSourcePath(method)) + .isInstanceOf(FileApproverError.class) + .hasMessage("Could not locate test source file"); + } + + @Test + void findTestSourcePath_ambiguous() throws IOException { Path wrongTestSourcePath = - Path.of( - "target/spotless-clean/spotlessJava/java/test/org/approvej/approve/StackTraceTestFinderUtilTest.java"); + Path.of("other/src/test/java/org/approvej/approve/StackTraceTestFinderUtilTest.java"); wrongTestSourcePathsToCleanup.add(wrongTestSourcePath); createDirectories(wrongTestSourcePath.getParent()); copy(thisTestSourcePath, wrongTestSourcePath); - Path testSourcePath = - StackTraceTestFinderUtil.findTestSourcePath( - StackTraceTestFinderUtil.currentTestMethod().method()); + Method method = StackTraceTestFinderUtil.currentTestMethod().method(); - assertThat(testSourcePath).isEqualTo(thisTestSourcePath.normalize()); + assertThatThrownBy(() -> StackTraceTestFinderUtil.findTestSourcePath(method)) + .isInstanceOf(FileApproverError.class) + .hasMessageStartingWith("Found multiple test source files ("); } }