diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 000000000..7503452d5 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,12 @@ + + + + smart-testing-parent + org.arquillian.smart.testing + 0.0.4-SNAPSHOT + + 4.0.0 + + api + + diff --git a/api/src/main/java/org/arquillian/smart/testing/strategies/affected/ComponentUnderTest.java b/api/src/main/java/org/arquillian/smart/testing/strategies/affected/ComponentUnderTest.java new file mode 100644 index 000000000..a139f3ef7 --- /dev/null +++ b/api/src/main/java/org/arquillian/smart/testing/strategies/affected/ComponentUnderTest.java @@ -0,0 +1,42 @@ +package org.arquillian.smart.testing.strategies.affected; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to set which production classes are tested in current test. + * By default it appends all classes defined in all attributes. + * + * If none of the attributes are set, then all production classes with same package as test and its subpackages are added. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Repeatable(ComponentsUnderTest.class) +@Documented +public @interface ComponentUnderTest { + + /** + * Packages of classes that needs to be added as tested classes in current test. You can set the package name "org.superbiz" which means only classes defined in this package, + * or ending with start (*) operator "org.superbiz.*" which means all classes of current package and its subpackages. + * @return Packages containing Java classes. + */ + String[] packages() default {}; + + /** + * Packages of classes that needs to be added as tested classes in current test. It is used Class to get the package. + * Notice that in this case subpackages are not scanned. + * @return Packages containing Java classes. + */ + Class[] packagesOf() default {}; + + /** + * Classes to be added as tested classes in current test. + * @return Classes + */ + Class[] classes() default {}; + +} diff --git a/api/src/main/java/org/arquillian/smart/testing/strategies/affected/ComponentsUnderTest.java b/api/src/main/java/org/arquillian/smart/testing/strategies/affected/ComponentsUnderTest.java new file mode 100644 index 000000000..7ca39b471 --- /dev/null +++ b/api/src/main/java/org/arquillian/smart/testing/strategies/affected/ComponentsUnderTest.java @@ -0,0 +1,14 @@ +package org.arquillian.smart.testing.strategies.affected; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +public @interface ComponentsUnderTest { + ComponentUnderTest[] value(); +} diff --git a/docs/configuration.adoc b/docs/configuration.adoc index c14eff4be..294f682ed 100644 --- a/docs/configuration.adoc +++ b/docs/configuration.adoc @@ -142,6 +142,36 @@ IMPORTANT: This strategy is currently only applicable for _white box_ testing ap WARNING: At this moment, this strategy does not work with Java 9. +===== Explicitly Set + +By default affected strategy uses _imports_ of tests to build the graph of collaborators. +This approach is fine for unit tests (white box tests) but might not work in all cases of high level tests (black box test). + +There are some test technologies that allows you to deploy an application locally and then run tests against it. +For example Wildfly Swarm has `@DefaultDeployment` annotation or Spring (Boot) deploys all application automatically. + +This means that production classes are not directly imported into the test, so there is no way to get a relationship between test and production classes. +For this reason `affected` provides an annotation to set package(s) of production classes that are deployed by the test. + +The first thing you need to do is register following artifact into your build script: `org.arquillian.smart.testing:api:`. + +Then you can annotate your test with `org.arquillian.smart.testing.strategies.affected.ComponentUnderTest` annotation. + +For example: + +[source, java] +---- +include::../strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ZTest.java[tag=docs] +---- + +In previous example all classes belonging to packages and subpackages specified at `packages` attribute are considered as classes used by the test. + +You can also use `packageOf` attribute to set a reference class. +With this attribute all classes that are placed in the same package as the reference class are considered as classes used by the test. +With this approach your tests are resilient to package name changes. + +If none of the attributes are set, then all production classes with same package as test and its subpackages are added automatically as classes used by the test. + ==== Failed `Failed` strategy just gets all tests that failed from previous executions and mark them as *important* tests to run first (_ordering_) or not filtered (_selecting_). diff --git a/functional-tests/test-bed/src/test/java/org/arquillian/smart/testing/ftest/affected/LocalChangesAffectedAnnotationTestsSelectionExecutionFunctionalTest.java b/functional-tests/test-bed/src/test/java/org/arquillian/smart/testing/ftest/affected/LocalChangesAffectedAnnotationTestsSelectionExecutionFunctionalTest.java new file mode 100644 index 000000000..d336a4b26 --- /dev/null +++ b/functional-tests/test-bed/src/test/java/org/arquillian/smart/testing/ftest/affected/LocalChangesAffectedAnnotationTestsSelectionExecutionFunctionalTest.java @@ -0,0 +1,50 @@ +package org.arquillian.smart.testing.ftest.affected; + +import java.util.Collection; +import org.arquillian.smart.testing.ftest.testbed.project.Project; +import org.arquillian.smart.testing.ftest.testbed.project.TestResults; +import org.arquillian.smart.testing.ftest.testbed.testresults.TestResult; +import org.arquillian.smart.testing.mvn.ext.dependencies.ExtensionVersion; +import org.arquillian.smart.testing.rules.TestBed; +import org.arquillian.smart.testing.rules.git.GitClone; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; + +import static org.arquillian.smart.testing.ftest.testbed.TestRepository.testRepository; +import static org.arquillian.smart.testing.ftest.testbed.configuration.Mode.SELECTING; +import static org.arquillian.smart.testing.ftest.testbed.configuration.Strategy.AFFECTED; +import static org.assertj.core.api.Assertions.assertThat; + +public class LocalChangesAffectedAnnotationTestsSelectionExecutionFunctionalTest { + + @ClassRule + public static final GitClone GIT_CLONE = new GitClone(testRepository()); + + @Rule + public final TestBed testBed = new TestBed(GIT_CLONE); + + @Test + public void should_only_execute_tests_with_affected_changes_annotated() throws Exception { + // given + final Project project = testBed.getProject(); + + project.configureSmartTesting() + .executionOrder(AFFECTED) + .inMode(SELECTING) + .enable(); + + final Collection expectedTestResults = project + .applyAsLocalChanges("Uses annotation to detect affected classes"); + + // when + final TestResults actualTestResults = project.build("config/impl-base") + .options().withSystemProperties("smart.testing.version", ExtensionVersion.version().toString()) + .configure() + .run(); + + // then + assertThat(actualTestResults.accumulatedPerTestClass()).containsAll(expectedTestResults).hasSameSizeAs(expectedTestResults); + } + +} diff --git a/pom.xml b/pom.xml index da4235984..340b5dae9 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ 3.8.0 1.16.1 3.21.0-GA + 2.7.4 1.0.1 3.0.0-beta-2 1.19 @@ -70,6 +71,7 @@ core + api surefire-provider junit-test-result-parser strategies/affected @@ -127,6 +129,11 @@ snakeyaml ${version.snakeyaml} + + io.github.lukehutch + fast-classpath-scanner + ${version.fast-classpath-scanner} + diff --git a/strategies/affected/pom.xml b/strategies/affected/pom.xml index c95ff1521..8fa8f180e 100644 --- a/strategies/affected/pom.xml +++ b/strategies/affected/pom.xml @@ -16,6 +16,11 @@ core ${project.version} + + org.arquillian.smart.testing + api + ${project.version} + org.arquillian.smart.testing strategy-changed @@ -29,6 +34,10 @@ org.jgrapht jgrapht-core + + io.github.lukehutch + fast-classpath-scanner + junit junit diff --git a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraph.java b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraph.java index 82e6d6191..1ea401106 100644 --- a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraph.java +++ b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraph.java @@ -27,14 +27,19 @@ */ package org.arquillian.smart.testing.strategies.affected; +import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import org.arquillian.smart.testing.api.TestVerifier; +import org.arquillian.smart.testing.logger.Log; +import org.arquillian.smart.testing.logger.Logger; import org.arquillian.smart.testing.configuration.Configuration; import org.arquillian.smart.testing.strategies.affected.ast.JavaClass; import org.arquillian.smart.testing.strategies.affected.ast.JavaClassBuilder; @@ -47,6 +52,7 @@ public class ClassDependenciesGraph { + private static final Logger logger = Log.getLogger(); private static final Filter coreJava = new Filter(Collections.singletonList(""), Collections.singletonList("java.*")); private final JavaClassBuilder builder; @@ -77,14 +83,86 @@ void buildTestDependencyGraph(Collection testJavaFiles) { // Then find dependencies for (String changedTestClassNames : testClassesNames) { - JavaClass javaClass = builder.getClassDescription(changedTestClassNames); - if (javaClass != null) { - addToIndex(new JavaElement(javaClass), javaClass.getImports()); + JavaClass testJavaClass = builder.getClassDescription(changedTestClassNames); + if (testJavaClass != null) { + final String[] imports = testJavaClass.getImports(); + final List manualProductionClasses = calculateManualAddedDependencies(testJavaClass); + manualProductionClasses.addAll(Arrays.asList(imports)); + addToIndex(new JavaElement(testJavaClass), manualProductionClasses); } } } - private void addToIndex(JavaElement javaElement, String[] imports) { + private List calculateManualAddedDependencies(JavaClass testJavaClass) { + final List manualDependencyClasses = new ArrayList<>(); + final ComponentUnderTest[] allTestsAnnotation = getAllAnnotations(testJavaClass); + + for (ComponentUnderTest tests : allTestsAnnotation) { + List packages = getPackages(testJavaClass.packageName(), tests); + for (String pkg : packages) { + final String trimmedPackage = pkg.trim(); + manualDependencyClasses.addAll(scanClassesFromPackage(trimmedPackage)); + } + } + + return manualDependencyClasses; + + } + + private ComponentUnderTest[] getAllAnnotations(JavaClass testJavaClass) { + + final Optional testsListOptional = testJavaClass.getAnnotationByType(ComponentsUnderTest.class); + + ComponentUnderTest[] tests = testsListOptional + .map(ComponentsUnderTest::value) + .orElseGet(() -> testJavaClass.getAnnotationByType(ComponentUnderTest.class) + .map(annotation -> new ComponentUnderTest[] {annotation}) + .orElse(new ComponentUnderTest[0])); + + + return tests; + } + + private List scanClassesFromPackage(String trimmedPackage) { + final List manualDependencyClasses = new ArrayList<>(); + if (trimmedPackage.endsWith(".*")) { + String realPackage = trimmedPackage.substring(0, trimmedPackage.indexOf(".*")); + final List classesOfPackage = + new FastClasspathScanner(realPackage).scan() + .getNamesOfAllClasses(); + + manualDependencyClasses.addAll( + classesOfPackage); + } else { + final List classesOfPackage = + new FastClasspathScanner(trimmedPackage).disableRecursiveScanning().scan() + .getNamesOfAllClasses(); + manualDependencyClasses.addAll( + classesOfPackage); + } + + if (manualDependencyClasses.isEmpty()) { + logger.warn("You set %s package as reference classes to run tests, but no classes found. Maybe a package refactor?", trimmedPackage); + } + + return manualDependencyClasses; + } + + private List getPackages(String testPackage, ComponentUnderTest tests) { + List packages = new ArrayList<>(); + if (tests.classes().length == 0 && tests.packages().length == 0 && tests.packagesOf().length == 0) { + packages.add(testPackage + ".*"); + } else { + packages.addAll(Arrays.asList(tests.packages())); + + packages.addAll(Arrays.stream(tests.packagesOf()) + .map(clazz -> clazz.getPackage().getName()) + .collect(Collectors.toList())); + } + return packages; + } + + private void addToIndex(JavaElement javaElement, List imports) { addToGraph(javaElement); updateJavaElementWithImportReferences(javaElement, imports); } @@ -105,14 +183,14 @@ private void replaceVertex(JavaElement newClass) { } } - private void updateJavaElementWithImportReferences(JavaElement javaElementParentClass, String[] imports) { + private void updateJavaElementWithImportReferences(JavaElement javaElementParentClass, List imports) { for (String importz : imports) { if (addImport(javaElementParentClass, importz) && filter.shouldBeIncluded(importz) && this.enableTransitivity) { JavaClass javaClass = builder.getClassDescription(importz); if (javaClass != null) { - updateJavaElementWithImportReferences(javaElementParentClass, javaClass.getImports()); + updateJavaElementWithImportReferences(javaElementParentClass, Arrays.asList(javaClass.getImports())); } } } diff --git a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaAssistClass.java b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaAssistClass.java index 4fb8ff661..272ea1a6a 100644 --- a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaAssistClass.java +++ b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaAssistClass.java @@ -31,6 +31,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import javassist.CtClass; import javassist.CtField; @@ -53,10 +54,12 @@ public class JavaAssistClass extends AbstractJavaClass { private final String[] imports; private final String className; private File classFile; + private final CtClass classReference; JavaAssistClass(CtClass classReference) { imports = findImports(classReference); className = classReference.getName(); + this.classReference = classReference; } @Override @@ -163,6 +166,11 @@ public String getName() { return className; } + @Override + public String packageName() { + return classReference.getPackageName(); + } + @Override public String toString() { return getName(); @@ -176,4 +184,13 @@ public void setClassFile(File classFile) { public File getClassFile() { return classFile; } + + @Override + public Optional getAnnotationByType(Class type) { + try { + return Optional.ofNullable((T) this.classReference.getAnnotation(type)); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e); + } + } } diff --git a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaClass.java b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaClass.java index 22f459406..c8e417f28 100644 --- a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaClass.java +++ b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/JavaClass.java @@ -28,10 +28,12 @@ package org.arquillian.smart.testing.strategies.affected.ast; import java.io.File; +import java.util.Optional; public interface JavaClass { String getName(); + String packageName(); /** * Gets the collection on classes that this class depends on. i.e. the list * of this classes children. @@ -39,4 +41,7 @@ public interface JavaClass { String[] getImports(); File getClassFile(); + + Optional getAnnotationByType(Class type); + } diff --git a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/UnparsableClass.java b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/UnparsableClass.java index 6b38a7d35..40dde4697 100644 --- a/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/UnparsableClass.java +++ b/strategies/affected/src/main/java/org/arquillian/smart/testing/strategies/affected/ast/UnparsableClass.java @@ -28,6 +28,7 @@ package org.arquillian.smart.testing.strategies.affected.ast; import java.io.File; +import java.util.Optional; public class UnparsableClass implements JavaClass { private static final String[] NO_IMPORT = new String[0]; @@ -43,6 +44,11 @@ public File getClassFile() { return null; } + @Override + public Optional getAnnotationByType(Class type) { + return Optional.empty(); + } + @Override public String[] getImports() { return NO_IMPORT; @@ -53,6 +59,11 @@ public String getName() { return classname; } + @Override + public String packageName() { + return ""; + } + @Override public String toString() { return "UnparsableClass{" + "classname='" + classname + '\'' + '}'; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraphTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraphTest.java index 9b4da8424..a277787a2 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraphTest.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/ClassDependenciesGraphTest.java @@ -5,15 +5,21 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; +import org.arquillian.smart.testing.strategies.affected.fakeproject.main.A; import org.arquillian.smart.testing.configuration.Configuration; import org.arquillian.smart.testing.configuration.ConfigurationLoader; import org.arquillian.smart.testing.strategies.affected.fakeproject.main.D; import org.arquillian.smart.testing.strategies.affected.fakeproject.main.MyBusinessObject; import org.arquillian.smart.testing.strategies.affected.fakeproject.main.MyControllerObject; +import org.arquillian.smart.testing.strategies.affected.fakeproject.main.superbiz.Alone; +import org.arquillian.smart.testing.strategies.affected.fakeproject.main.superbiz.component.Unwanted; import org.arquillian.smart.testing.strategies.affected.fakeproject.test.ATest; import org.arquillian.smart.testing.strategies.affected.fakeproject.test.BTest; import org.arquillian.smart.testing.strategies.affected.fakeproject.test.CTest; import org.arquillian.smart.testing.strategies.affected.fakeproject.test.MyBusinessObjectTest; +import org.arquillian.smart.testing.strategies.affected.fakeproject.test.MySecondBusinessObjectTest; +import org.arquillian.smart.testing.strategies.affected.fakeproject.test.YTest; +import org.arquillian.smart.testing.strategies.affected.fakeproject.test.ZTest; import org.junit.Test; import static java.util.Collections.singletonList; @@ -31,12 +37,12 @@ public void should_detect_simple_test_to_execute() { final ClassDependenciesGraph classDependenciesGraph = new ClassDependenciesGraph(new EndingWithTestTestVerifier(), configuration); - final String testLocation = MyBusinessObjectTest.class.getResource("MyBusinessObjectTest.class").getPath(); + final String testLocation = getClassLocation(MyBusinessObjectTest.class); classDependenciesGraph.buildTestDependencyGraph(singletonList(new File(testLocation))); // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(MyBusinessObject.class.getResource("MyBusinessObject.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(MyBusinessObject.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -58,7 +64,7 @@ public void should_detect_multiple_tests_to_execute_against_same_main_class() { // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(MyBusinessObject.class.getResource("MyBusinessObject.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(MyBusinessObject.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -81,7 +87,7 @@ public void should_detect_test_with_multiple_main_classes() { // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(MyControllerObject.class.getResource("MyControllerObject.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(MyControllerObject.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -103,8 +109,8 @@ public void should_detect_multiple_tests_to_execute_against_same_main_class_avoi // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(MyBusinessObject.class.getResource("MyBusinessObject.class").getPath())); - mainObjectsChanged.add(new File(MyControllerObject.class.getResource("MyControllerObject.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(MyBusinessObject.class))); + mainObjectsChanged.add(new File(getClassLocation(MyControllerObject.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -128,7 +134,7 @@ public void should_detect_all_changes_transitive() { // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(D.class.getResource("D.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(D.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -138,6 +144,53 @@ public void should_detect_all_changes_transitive() { "org.arquillian.smart.testing.strategies.affected.fakeproject.test.ATest", "org.arquillian.smart.testing.strategies.affected.fakeproject.test.BTest"); } + @Test + public void should_detect_all_changes_adding_package_annotated_transitive() { + // given + final Configuration configuration = ConfigurationLoader.load(); + configuration.loadStrategyConfigurations(AFFECTED); + + final ClassDependenciesGraph + classDependenciesGraph = new ClassDependenciesGraph(new EndingWithTestTestVerifier(), configuration); + + final String testLocation = getClassLocation(ZTest.class); + classDependenciesGraph.buildTestDependencyGraph(Arrays.asList(new File(testLocation))); + + // when + Set mainObjectsChanged = new HashSet<>(); + mainObjectsChanged.add(new File(getClassLocation(Unwanted.class))); + + final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); + + // then + assertThat(testsDependingOn) + .containsExactlyInAnyOrder( + "org.arquillian.smart.testing.strategies.affected.fakeproject.test.ZTest"); + } + + @Test + public void should_detect_all_changes_adding_class_package_annotated_transitive() { + // given + final Configuration configuration = ConfigurationLoader.load(); + configuration.loadStrategyConfigurations(AFFECTED); + final ClassDependenciesGraph + classDependenciesGraph = new ClassDependenciesGraph(new EndingWithTestTestVerifier(), configuration); + + final String testLocation = getClassLocation(YTest.class); + classDependenciesGraph.buildTestDependencyGraph(Arrays.asList(new File(testLocation))); + + // when + Set mainObjectsChanged = new HashSet<>(); + mainObjectsChanged.add(new File(getClassLocation(Alone.class))); + + final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); + + // then + assertThat(testsDependingOn) + .containsExactlyInAnyOrder( + "org.arquillian.smart.testing.strategies.affected.fakeproject.test.YTest"); + } + @Test public void should_not_detect_all_changes_transitive_if_transitivity_is_disabled() { // given @@ -153,7 +206,7 @@ public void should_not_detect_all_changes_transitive_if_transitivity_is_disabled // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(D.class.getResource("D.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(D.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -178,7 +231,7 @@ public void should_exclude_imports_if_property_set() { // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(D.class.getResource("D.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(D.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -203,7 +256,7 @@ public void should_include_only_imports_if_property_set() { // when Set mainObjectsChanged = new HashSet<>(); - mainObjectsChanged.add(new File(D.class.getResource("A.class").getPath())); + mainObjectsChanged.add(new File(getClassLocation(A.class))); final Set testsDependingOn = classDependenciesGraph.findTestsDependingOn(mainObjectsChanged); @@ -214,16 +267,20 @@ public void should_include_only_imports_if_property_set() { } private void buildTestDependencyGraphWithTestLocation(ClassDependenciesGraph classDependenciesGraph) { - final String testLocation = ATest.class.getResource("ATest.class").getPath(); - final String testLocation2 = BTest.class.getResource("BTest.class").getPath(); - final String testLocation3 = CTest.class.getResource("CTest.class").getPath(); + final String testLocation = getClassLocation(ATest.class); + final String testLocation2 = getClassLocation(BTest.class); + final String testLocation3 = getClassLocation(CTest.class); classDependenciesGraph.buildTestDependencyGraph(Arrays.asList(new File(testLocation), new File(testLocation2), new File(testLocation3))); } private void buildTestDependencyGraphWithLocation(ClassDependenciesGraph classDependenciesGraph) { - final String testLocation = MyBusinessObjectTest.class.getResource("MyBusinessObjectTest.class").getPath(); - final String testLocation2 = MyBusinessObjectTest.class.getResource("MySecondBusinessObjectTest.class").getPath(); + final String testLocation = getClassLocation(MyBusinessObjectTest.class); + final String testLocation2 = getClassLocation(MySecondBusinessObjectTest.class); classDependenciesGraph.buildTestDependencyGraph(Arrays.asList(new File(testLocation), new File(testLocation2))); } + + private String getClassLocation(Class clazz) { + return clazz.getResource(clazz.getSimpleName() + ".class").getPath(); + } } diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/main/superbiz/Alone.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/main/superbiz/Alone.java new file mode 100644 index 000000000..9e6e8f9fd --- /dev/null +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/main/superbiz/Alone.java @@ -0,0 +1,4 @@ +package org.arquillian.smart.testing.strategies.affected.fakeproject.main.superbiz; + +public class Alone { +} diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/main/superbiz/component/Unwanted.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/main/superbiz/component/Unwanted.java new file mode 100644 index 000000000..8e335da9c --- /dev/null +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/main/superbiz/component/Unwanted.java @@ -0,0 +1,4 @@ +package org.arquillian.smart.testing.strategies.affected.fakeproject.main.superbiz.component; + +public class Unwanted { +} diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ATest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ATest.java index 2dfa26400..8e956dc07 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ATest.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ATest.java @@ -4,8 +4,7 @@ import org.junit.Ignore; import org.junit.Test; -// Test ignored because it is a test that is used to in tests and not to be run as real test by test runner -@Ignore +@Ignore("Test ignored because it is used internally") public class ATest { private A a; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/BTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/BTest.java index ef4f6d93b..d58798c8e 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/BTest.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/BTest.java @@ -4,8 +4,7 @@ import org.junit.Ignore; import org.junit.Test; -// Test ignored because it is a test that is used to in tests and not to be run as real test by test runner -@Ignore +@Ignore("Test ignored because it is used internally") public class BTest { private B b; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/CTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/CTest.java index fca32a88c..abbc225fb 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/CTest.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/CTest.java @@ -4,8 +4,7 @@ import org.junit.Ignore; import org.junit.Test; -// Test ignored because it is a test that is used to in tests and not to be run as real test by test runner -@Ignore +@Ignore("Test ignored because it is used internally") public class CTest { private C c; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTest.java index de86d2b48..e83bef77f 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTest.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTest.java @@ -4,8 +4,7 @@ import org.junit.Ignore; import org.junit.Test; -// Test ignored because it is a test that is used to in tests and not to be run as real test by test runner -@Ignore +@Ignore("Test ignored because it is used internally") public class MyBusinessObjectTest { private MyBusinessObject myBusinessObject; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTestCase.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTestCase.java index d7e4ba97e..24c3ade2c 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTestCase.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MyBusinessObjectTestCase.java @@ -4,8 +4,7 @@ import org.junit.Ignore; import org.junit.Test; -// Test ignored because it is a test that is used to in tests and not to be run as real test by test runner -@Ignore +@Ignore("Test ignored because it is used internally") public class MyBusinessObjectTestCase { private MyBusinessObject myBusinessObject; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MySecondBusinessObjectTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MySecondBusinessObjectTest.java index 087059f89..893c31e58 100644 --- a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MySecondBusinessObjectTest.java +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/MySecondBusinessObjectTest.java @@ -5,8 +5,7 @@ import org.junit.Ignore; import org.junit.Test; -// Test ignored because it is a test that is used to in tests and not to be run as real test by test runner -@Ignore +@Ignore("Test ignored because it is used internally") public class MySecondBusinessObjectTest { private MyBusinessObject myBusinessObject; diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/YTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/YTest.java new file mode 100644 index 000000000..a8512e2bf --- /dev/null +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/YTest.java @@ -0,0 +1,17 @@ +package org.arquillian.smart.testing.strategies.affected.fakeproject.test; + +import org.arquillian.smart.testing.strategies.affected.ComponentUnderTest; +import org.arquillian.smart.testing.strategies.affected.fakeproject.main.superbiz.Alone; +import org.junit.Ignore; +import org.junit.Test; + +@Ignore("Test ignored because it is used internally") +@ComponentUnderTest(packagesOf = Alone.class) +public class YTest { + + @Test + public void black_box() { + System.out.println("Black Box Testing"); + } + +} diff --git a/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ZTest.java b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ZTest.java new file mode 100644 index 000000000..fb505e816 --- /dev/null +++ b/strategies/affected/src/test/java/org/arquillian/smart/testing/strategies/affected/fakeproject/test/ZTest.java @@ -0,0 +1,17 @@ +package org.arquillian.smart.testing.strategies.affected.fakeproject.test; + +import org.arquillian.smart.testing.strategies.affected.ComponentUnderTest; +import org.junit.Ignore; +import org.junit.Test; + +@Ignore("Test ignored because it is used internally") +//tag::docs[] +@ComponentUnderTest(packages = "org.arquillian.smart.testing.strategies.affected.fakeproject.main.superbiz.*") +public class ZTest { +//end::docs[] + @Test + public void black_box() { + System.out.println("Black Box Testing"); + } + +}