diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ImportOption.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ImportOption.java
index 5e24a4d54c..75fd781299 100644
--- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ImportOption.java
+++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ImportOption.java
@@ -15,13 +15,16 @@
*/
package com.tngtech.archunit.core.importer;
-import java.util.Set;
import java.util.regex.Pattern;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.base.Predicate;
import com.tngtech.archunit.PublicAPI;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.base.Predicates.or;
import static com.tngtech.archunit.PublicAPI.Usage.INHERITANCE;
+import static com.tngtech.archunit.core.importer.ImportOption.Predefined.NO_TEST_LOCATION;
+import static com.tngtech.archunit.core.importer.ImportOption.Predefined.TEST_LOCATION;
/**
* Will be evaluated for every class location, to determine if the class should be imported.
@@ -47,6 +50,14 @@ public boolean includes(Location location) {
return doNotIncludeTests.includes(location);
}
},
+ ONLY_INCLUDE_TESTS {
+ private final OnlyIncludeTests onlyIncludeTests = new OnlyIncludeTests();
+
+ @Override
+ public boolean includes(Location location) {
+ return onlyIncludeTests.includes(location);
+ }
+ },
DO_NOT_INCLUDE_JARS {
private final DoNotIncludeJars doNotIncludeJars = new DoNotIncludeJars();
@@ -65,30 +76,51 @@ public boolean includes(Location location) {
public boolean includes(Location location) {
return doNotIncludeArchives.includes(location);
}
+ };
+
+ static final PatternPredicate MAVEN_TEST_PATTERN = new PatternPredicate(".*/target/test-classes/.*");
+ static final PatternPredicate GRADLE_TEST_PATTERN = new PatternPredicate(".*/build/classes/([^/]+/)?test/.*");
+ static final PatternPredicate INTELLIJ_TEST_PATTERN = new PatternPredicate(".*/out/test/classes/.*");
+ static final Predicate TEST_LOCATION = or(MAVEN_TEST_PATTERN, GRADLE_TEST_PATTERN, INTELLIJ_TEST_PATTERN);
+ static final Predicate NO_TEST_LOCATION = not(TEST_LOCATION);
+
+ private static class PatternPredicate implements Predicate {
+ private final Pattern pattern;
+
+ PatternPredicate(String pattern) {
+ this.pattern = Pattern.compile(pattern);
+ }
+
+ @Override
+ @SuppressWarnings("ConstantConditions") // ArchUnit never uses null as a valid parameter
+ public boolean apply(Location input) {
+ return input.matches(pattern);
+ }
}
}
/**
+ * Best effort {@link ImportOption} to check rules only on main classes.
* NOTE: This excludes all class files residing in some directory
* ../target/test-classes/.., ../build/classes/test/.. or ../build/classes/someLang/test/.. (Maven/Gradle standard).
* Thus it is just a best guess, how tests can be identified,
* in other environments, it might be necessary, to implement the correct {@link ImportOption} yourself.
*/
final class DoNotIncludeTests implements ImportOption {
- private static final Pattern MAVEN_PATTERN = Pattern.compile(".*/target/test-classes/.*");
- private static final Pattern GRADLE_PATTERN = Pattern.compile(".*/build/classes/([^/]+/)?test/.*");
- private static final Pattern INTELLIJ_PATTERN = Pattern.compile(".*/out/test/classes/.*");
-
- private static final Set EXCLUDED_PATTERN = ImmutableSet.of(MAVEN_PATTERN, GRADLE_PATTERN, INTELLIJ_PATTERN);
+ @Override
+ public boolean includes(Location location) {
+ return NO_TEST_LOCATION.apply(location);
+ }
+ }
+ /**
+ * Best effort {@link ImportOption} to check rules only on test classes.
+ * See {@link DoNotIncludeTests} for limitations of test class identification.
+ */
+ final class OnlyIncludeTests implements ImportOption {
@Override
public boolean includes(Location location) {
- for (Pattern pattern : EXCLUDED_PATTERN) {
- if (location.matches(pattern)) {
- return false;
- }
- }
- return true;
+ return TEST_LOCATION.apply(location);
}
}
diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportOptionsTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportOptionsTest.java
index fd5ed6ddbd..a6b0cca2a6 100644
--- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportOptionsTest.java
+++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportOptionsTest.java
@@ -3,10 +3,14 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import com.google.common.collect.ImmutableList;
import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeArchives;
import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeJars;
import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests;
+import com.tngtech.archunit.core.importer.ImportOption.OnlyIncludeTests;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
@@ -15,14 +19,17 @@
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
+import static com.google.common.collect.ImmutableList.copyOf;
+import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.getLast;
import static com.tngtech.archunit.core.importer.ImportOption.Predefined.DO_NOT_INCLUDE_ARCHIVES;
import static com.tngtech.archunit.core.importer.ImportOption.Predefined.DO_NOT_INCLUDE_JARS;
import static com.tngtech.archunit.core.importer.ImportOption.Predefined.DO_NOT_INCLUDE_TESTS;
+import static com.tngtech.archunit.core.importer.ImportOption.Predefined.ONLY_INCLUDE_TESTS;
import static com.tngtech.java.junit.dataprovider.DataProviders.$;
-import static com.tngtech.java.junit.dataprovider.DataProviders.$$;
import static com.tngtech.java.junit.dataprovider.DataProviders.crossProduct;
import static com.tngtech.java.junit.dataprovider.DataProviders.testForEach;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(DataProviderRunner.class)
@@ -46,33 +53,62 @@ public void excludes_test_class(ImportOption doNotIncludeTests) {
}
@DataProvider
- public static Object[][] folders() {
- return crossProduct(do_not_include_tests(), $$(
+ public static Object[][] only_include_tests() {
+ return testForEach(new OnlyIncludeTests(), ONLY_INCLUDE_TESTS);
+ }
+
+ @Test
+ @UseDataProvider("only_include_tests")
+ public void excludes_main_class(ImportOption onlyIncludeTests) {
+ assertThat(onlyIncludeTests.includes(locationOf(OnlyIncludeTests.class)))
+ .as("includes production location").isFalse();
+
+ assertThat(onlyIncludeTests.includes(locationOf(getClass())))
+ .as("includes test location").isTrue();
+ }
+
+ private static List getFolderPatterns() {
+ return ImmutableList.of(
// Gradle
- $(new String[]{"build", "classes", "test"}, false),
- $(new String[]{"build", "classes", "java", "test"}, false),
- $(new String[]{"build", "classes", "otherlang", "test"}, false),
- $(new String[]{"build", "test-classes"}, true),
- $(new String[]{"build", "classes", "main"}, true),
- $(new String[]{"build", "classes", "java", "main"}, true),
- $(new String[]{"build", "classes", "java", "main", "my", "test"}, true),
+ new FolderPattern("build", "classes", "test").expectTestFolder(),
+ new FolderPattern("build", "classes", "java", "test").expectTestFolder(),
+ new FolderPattern("build", "classes", "otherlang", "test").expectTestFolder(),
+ new FolderPattern("build", "test-classes").expectMainFolder(),
+ new FolderPattern("build", "classes", "main").expectMainFolder(),
+ new FolderPattern("build", "classes", "java", "main").expectMainFolder(),
+ new FolderPattern("build", "classes", "java", "main", "my", "test").expectMainFolder(),
// Maven
- $(new String[]{"target", "classes", "test"}, true),
- $(new String[]{"target", "test-classes"}, false),
- $(new String[]{"target", "classes"}, true),
+ new FolderPattern("target", "classes", "test").expectMainFolder(),
+ new FolderPattern("target", "test-classes").expectTestFolder(),
+ new FolderPattern("target", "classes").expectMainFolder(),
// IntelliJ
- $(new String[]{"out", "production", "classes"}, true),
- $(new String[]{"out", "test", "classes"}, false),
- $(new String[]{"out", "test", "classes", "my", "test"}, false),
- $(new String[]{"out", "some", "classes"}, true)
- ));
+ new FolderPattern("out", "production", "classes").expectMainFolder(),
+ new FolderPattern("out", "test", "classes").expectTestFolder(),
+ new FolderPattern("out", "test", "classes", "my", "test").expectTestFolder(),
+ new FolderPattern("out", "some", "classes").expectMainFolder()
+ );
+ }
+
+ @DataProvider
+ public static Object[][] test_location_predicates_and_expected_folder_patterns() {
+ List