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 b915bdfec3..23a6ae54f4 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2014-2020 TNG Technology Consulting GmbH
+ * Copyright 2014-2021 TNG Technology Consulting GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,13 +15,15 @@
*/
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.google.common.base.Predicates;
import com.tngtech.archunit.PublicAPI;
+import static com.google.common.base.Predicates.not;
import static com.tngtech.archunit.PublicAPI.Usage.INHERITANCE;
+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 +49,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 +75,52 @@ 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 = Predicates.or(MAVEN_TEST_PATTERN, GRADLE_TEST_PATTERN, INTELLIJ_TEST_PATTERN);
+
+ 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 extends LocationPatternImportOption {
+ final class DoNotIncludeTests implements ImportOption {
+ private static final Predicate NO_TEST_LOCATION = not(TEST_LOCATION);
- public DoNotIncludeTests() {
- super(TESTS_LOCATIONS, true);
+ @Override
+ public boolean includes(Location location) {
+ return NO_TEST_LOCATION.apply(location);
}
}
-
+
/**
- * Import option to define rules only for Tests.
- * See {@link DoNotIncludeTests} for limitations if tests identification.
+ * Best effort {@link ImportOption} to check rules only on test classes.
+ * See {@link DoNotIncludeTests} for limitations of test class identification.
*/
- final class OnlyTests extends LocationPatternImportOption {
-
- public OnlyTests() {
- super(TESTS_LOCATIONS, false);
+ final class OnlyIncludeTests implements ImportOption {
+ @Override
+ public boolean includes(Location location) {
+ return TEST_LOCATION.apply(location);
}
}
@@ -105,33 +137,4 @@ public boolean includes(Location location) {
return !location.isArchive();
}
}
-
- /**
- * Import option for excluding/including locations matching specific regex patterns.
- */
- abstract class LocationPatternImportOption implements ImportOption {
- protected static final Pattern MAVEN_PATTERN = Pattern.compile(".*/target/test-classes/.*");
- protected static final Pattern GRADLE_PATTERN = Pattern.compile(".*/build/classes/([^/]+/)?test/.*");
- protected static final Pattern INTELLIJ_PATTERN = Pattern.compile(".*/out/test/classes/.*");
- protected static final Set TESTS_LOCATIONS =
- ImmutableSet.of(MAVEN_PATTERN, GRADLE_PATTERN, INTELLIJ_PATTERN);
-
- private final Set patterns;
- private final boolean exclude;
-
- public LocationPatternImportOption(Set excludedPatterns, boolean exclude) {
- this.patterns = excludedPatterns;
- this.exclude = exclude;
- }
-
- @Override
- public boolean includes(Location location) {
- for (Pattern pattern : patterns) {
- if (location.matches(pattern)) {
- return exclude ? false : true;
- }
- }
- return exclude ? true : false;
- }
- }
}
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