From bbf78cc481345ed0807033d93ac43d1e3f9a9f8e Mon Sep 17 00:00:00 2001 From: krzysztof-owczarek Date: Wed, 23 Oct 2024 21:42:29 +0200 Subject: [PATCH 1/2] fix resideInSamePackage rule fails for multiple implementations, but not all with tests Signed-off-by: krzysztof-owczarek --- .../archunit/library/GeneralCodingRules.java | 15 ++++++++++++++- .../archunit/library/GeneralCodingRulesTest.java | 11 +++++++++++ ...entationsWithOnlyOneTestAndInRightPackage.java | 4 ++++ ...ionHaveTestAndItIsMatchingImplPackageTest.java | 4 ++++ ...entationsWithOnlyOneTestAndInRightPackage.java | 4 ++++ 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java diff --git a/archunit/src/main/java/com/tngtech/archunit/library/GeneralCodingRules.java b/archunit/src/main/java/com/tngtech/archunit/library/GeneralCodingRules.java index ee6cbb6813..f78b0e9c47 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/GeneralCodingRules.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/GeneralCodingRules.java @@ -452,12 +452,16 @@ public static ArchRule testClassesShouldResideInTheSamePackageAsImplementation(S private static ArchCondition resideInTheSamePackageAsTheirTestClasses(String testClassSuffix) { return new ArchCondition("reside in the same package as their test classes") { Map> testClassesBySimpleClassName = new HashMap<>(); + Map> classesByPackageName = new HashMap<>(); @Override public void init(Collection allClasses) { testClassesBySimpleClassName = allClasses.stream() .filter(clazz -> clazz.getName().endsWith(testClassSuffix)) .collect(groupingBy(JavaClass::getSimpleName)); + + classesByPackageName = allClasses.stream() + .collect(groupingBy(JavaClass::getPackageName)); } @Override @@ -468,7 +472,8 @@ public void check(JavaClass implementationClass, ConditionEvents events) { List 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 -> { @@ -478,6 +483,14 @@ public void check(JavaClass implementationClass, ConditionEvents events) { }); } } + + private boolean allPossibleTestClassesHaveImplementationInRightPackage(List possibleTestClasses) { + return possibleTestClasses.stream() + .allMatch(testClazz -> classesByPackageName.getOrDefault(testClazz.getPackageName(), emptyList()) + .stream() + .filter(clazz -> !testClazz.getSimpleName().equals(clazz.getSimpleName())) + .anyMatch(clazz -> testClazz.getSimpleName().startsWith(clazz.getSimpleName()))); + } }; } diff --git a/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java b/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java index 22ef0e6bf0..09c1493843 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java @@ -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.MultipleImplementationsWithOnlyOneTestAndInRightPackage; 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; @@ -83,6 +84,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( + MultipleImplementationsWithOnlyOneTestAndInRightPackage.class, + com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2.MultipleImplementationsWithOnlyOneTestAndInRightPackage.class + )) + .hasNoViolation(); + } + @Test public void ASSERTIONS_SHOULD_HAVE_DETAIL_MESSAGE_should_fail_on_assert_without_detail_message() { @SuppressWarnings("unused") diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java new file mode 100644 index 0000000000..b588c8b81a --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java @@ -0,0 +1,4 @@ +package com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1; + +public class MultipleImplementationsWithOnlyOneTestAndInRightPackage { +} diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java new file mode 100644 index 0000000000..ebd29a2a6f --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java @@ -0,0 +1,4 @@ +package com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1; + +public class OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest { +} diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java new file mode 100644 index 0000000000..6456b7d36d --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java @@ -0,0 +1,4 @@ +package com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2; + +public class MultipleImplementationsWithOnlyOneTestAndInRightPackage { +} From b87bd2f70701d886dbf2e0af625a230b2a7967a3 Mon Sep 17 00:00:00 2001 From: krzysztof-owczarek Date: Fri, 25 Oct 2024 10:43:19 +0200 Subject: [PATCH 2/2] CR: Fix class names Signed-off-by: krzysztof-owczarek --- .../tngtech/archunit/library/GeneralCodingRulesTest.java | 6 +++--- ...kage.java => SimpleNameThatOccursInSeveralPackages.java} | 2 +- ....java => SimpleNameThatOccursInSeveralPackagesTest.java} | 2 +- ...kage.java => SimpleNameThatOccursInSeveralPackages.java} | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/{MultipleImplementationsWithOnlyOneTestAndInRightPackage.java => SimpleNameThatOccursInSeveralPackages.java} (58%) rename archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/{OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java => SimpleNameThatOccursInSeveralPackagesTest.java} (57%) rename archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/{MultipleImplementationsWithOnlyOneTestAndInRightPackage.java => SimpleNameThatOccursInSeveralPackages.java} (58%) diff --git a/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java b/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java index 09c1493843..a091ad0847 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/GeneralCodingRulesTest.java @@ -5,7 +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.MultipleImplementationsWithOnlyOneTestAndInRightPackage; +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; @@ -88,8 +88,8 @@ public void should_not_pass_when_none_of_multiple_matching_test_classes_resides_ 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( - MultipleImplementationsWithOnlyOneTestAndInRightPackage.class, - com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2.MultipleImplementationsWithOnlyOneTestAndInRightPackage.class + SimpleNameThatOccursInSeveralPackages.class, + com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2.SimpleNameThatOccursInSeveralPackages.class )) .hasNoViolation(); } diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/SimpleNameThatOccursInSeveralPackages.java similarity index 58% rename from archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java rename to archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/SimpleNameThatOccursInSeveralPackages.java index b588c8b81a..6fa3e2b04e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/SimpleNameThatOccursInSeveralPackages.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1; -public class MultipleImplementationsWithOnlyOneTestAndInRightPackage { +public class SimpleNameThatOccursInSeveralPackages { } diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/SimpleNameThatOccursInSeveralPackagesTest.java similarity index 57% rename from archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java rename to archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/SimpleNameThatOccursInSeveralPackagesTest.java index ebd29a2a6f..58097a5b5c 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/correct/twoimplementationsonetestdir1/SimpleNameThatOccursInSeveralPackagesTest.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.library.testclasses.packages.correct.twoimplementationsonetestdir1; -public class OnlyOneImplementationHaveTestAndItIsMatchingImplPackageTest { +class SimpleNameThatOccursInSeveralPackagesTest { } diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/SimpleNameThatOccursInSeveralPackages.java similarity index 58% rename from archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java rename to archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/SimpleNameThatOccursInSeveralPackages.java index 6456b7d36d..c1c69d3bdb 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/MultipleImplementationsWithOnlyOneTestAndInRightPackage.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/packages/incorrect/twoimplementationsonetestdir2/SimpleNameThatOccursInSeveralPackages.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.library.testclasses.packages.incorrect.twoimplementationsonetestdir2; -public class MultipleImplementationsWithOnlyOneTestAndInRightPackage { +public class SimpleNameThatOccursInSeveralPackages { }