Skip to content

Commit

Permalink
fix resideInSamePackage rule fails for multiple implementations, but …
Browse files Browse the repository at this point in the history
…not all with tests

Signed-off-by: krzysztof-owczarek <[email protected]>
  • Loading branch information
krzysztof-owczarek authored and hankem committed Feb 10, 2025
1 parent 13a2bc9 commit 2e7af6a
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -452,12 +452,16 @@ public static ArchRule testClassesShouldResideInTheSamePackageAsImplementation(S
private static ArchCondition<JavaClass> resideInTheSamePackageAsTheirTestClasses(String testClassSuffix) {
return new ArchCondition<JavaClass>("reside in the same package as their test classes") {
Map<String, List<JavaClass>> testClassesBySimpleClassName = new HashMap<>();
Map<String, List<JavaClass>> classesByPackageName = new HashMap<>();

@Override
public void init(Collection<JavaClass> allClasses) {
testClassesBySimpleClassName = allClasses.stream()
.filter(clazz -> clazz.getName().endsWith(testClassSuffix))
.collect(groupingBy(JavaClass::getSimpleName));

classesByPackageName = allClasses.stream()
.collect(groupingBy(JavaClass::getPackageName));
}

@Override
Expand All @@ -468,7 +472,8 @@ public void check(JavaClass implementationClass, ConditionEvents events) {
List<JavaClass> possibleTestClasses = testClassesBySimpleClassName.getOrDefault(possibleTestClassName, emptyList());

boolean isTestClassInWrongPackage = !possibleTestClasses.isEmpty()
&& possibleTestClasses.stream().noneMatch(clazz -> clazz.getPackageName().equals(implementationClassPackageName));
&& possibleTestClasses.stream().noneMatch(clazz -> clazz.getPackageName().equals(implementationClassPackageName))
&& !allPossibleTestClassesHaveImplementationInRightPackage(possibleTestClasses);

if (isTestClassInWrongPackage) {
possibleTestClasses.forEach(wrongTestClass -> {
Expand All @@ -478,6 +483,13 @@ public void check(JavaClass implementationClass, ConditionEvents events) {
});
}
}

private boolean allPossibleTestClassesHaveImplementationInRightPackage(List<JavaClass> possibleTestClasses) {
return possibleTestClasses.stream()
.allMatch(testClazz -> classesByPackageName.getOrDefault(testClazz.getPackageName(), emptyList())
.stream()
.anyMatch(clazz -> testClazz.getSimpleName().equals(clazz.getSimpleName() + testClassSuffix)));
}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.tngtech.archunit.library.testclasses.packages.correct.defaultsuffix.ImplementationClassWithCorrectPackage;
import com.tngtech.archunit.library.testclasses.packages.correct.notest.ImplementationClassWithoutTestClass;
import com.tngtech.archunit.library.testclasses.packages.correct.onedirmatching.ImplementationClassWithOneTestPackageMatchingOutOfTwo;
import com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1.SimpleNameThatOccursInSeveralPackages;
import com.tngtech.archunit.library.testclasses.packages.incorrect.nodirmatching.ImplementationClassWithMultipleTestsNotMatchingImplementationClassPackage;
import com.tngtech.archunit.library.testclasses.packages.incorrect.wrongsubdir.customsuffix.ImplementationClassWithWrongTestClassPackageCustomSuffix;
import com.tngtech.archunit.library.testclasses.packages.incorrect.wrongsubdir.customsuffix.subdir.ImplementationClassWithWrongTestClassPackageCustomSuffixTestingScenario;
Expand Down Expand Up @@ -89,6 +90,16 @@ public void should_not_pass_when_none_of_multiple_matching_test_classes_resides_
);
}

@Test
public void should_pass_when_only_one_of_two_implementations_have_test_class_and_it_is_in_implementation_package() {
assertThatRule(testClassesShouldResideInTheSamePackageAsImplementation())
.checking(new ClassFileImporter().importPackagesOf(
SimpleNameThatOccursInSeveralPackages.class,
com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2.SimpleNameThatOccursInSeveralPackages.class
))
.hasNoViolation();
}

@Test
public void ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE_should_fail_on_assert_without_detail_message() {
@SuppressWarnings("unused")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1;

public class SimpleNameThatOccursInSeveralPackages {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1;

class SimpleNameThatOccursInSeveralPackagesTest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2;

public class SimpleNameThatOccursInSeveralPackages {
}

0 comments on commit 2e7af6a

Please sign in to comment.