diff --git a/runner/android_junit_runner/CHANGELOG.md b/runner/android_junit_runner/CHANGELOG.md index 0e374a29f..2a4d16c10 100644 --- a/runner/android_junit_runner/CHANGELOG.md +++ b/runner/android_junit_runner/CHANGELOG.md @@ -6,6 +6,8 @@ **Bug Fixes** +* Inspect class-level annotations in `TestRequestBuilder.CustomFilters` so `@CustomFilter` annotations applied at the test class level are evaluated. (b/573501234) + **New Features** **Breaking Changes** diff --git a/runner/android_junit_runner/java/androidx/test/internal/runner/TestRequestBuilder.java b/runner/android_junit_runner/java/androidx/test/internal/runner/TestRequestBuilder.java index 1a9d7e308..01f4efd29 100644 --- a/runner/android_junit_runner/java/androidx/test/internal/runner/TestRequestBuilder.java +++ b/runner/android_junit_runner/java/androidx/test/internal/runner/TestRequestBuilder.java @@ -213,7 +213,15 @@ static Suite createSuite(List runners) { private static class CustomFilters extends AbstractFilter { @Override protected boolean evaluateTest(Description description) { - Collection allAnnotations = description.getAnnotations(); + List allAnnotations = new ArrayList<>(description.getAnnotations()); + Class testClass = description.getTestClass(); + if (testClass != null) { + for (Annotation classAnnotation : testClass.getAnnotations()) { + if (description.getAnnotation(classAnnotation.annotationType()) == null) { + allAnnotations.add(classAnnotation); + } + } + } for (Annotation a : allAnnotations) { CustomFilter filter = a.annotationType().getAnnotation(CustomFilter.class); diff --git a/runner/android_junit_runner/javatests/androidx/test/internal/runner/TestRequestBuilderTest.java b/runner/android_junit_runner/javatests/androidx/test/internal/runner/TestRequestBuilderTest.java index 20bd1c222..beb880b4d 100644 --- a/runner/android_junit_runner/javatests/androidx/test/internal/runner/TestRequestBuilderTest.java +++ b/runner/android_junit_runner/javatests/androidx/test/internal/runner/TestRequestBuilderTest.java @@ -209,12 +209,36 @@ public void testRun() {} public void testNotRun() {} } + @SampleCustomAnnotation(runTest = true) + public static class SampleCustomFilterClassIncludedTestClass { + @Test + public void testRunFromClassAnnotation() {} + + @Test + @SampleCustomAnnotation(runTest = false) + public void testNotRunOverridingClassAnnotation() {} + } + + @SampleCustomAnnotation(runTest = false) + public static class SampleCustomFilterClassExcludedTestClass { + @Test + public void testNotRunFromClassAnnotation() {} + + @Test + @SampleCustomAnnotation(runTest = true) + public void testRunOverridingClassAnnotation() {} + } + public static class SampleCustomFilter extends AbstractFilter { public SampleCustomFilter() {} @Override protected boolean evaluateTest(Description description) { - return description.getAnnotation(SampleCustomAnnotation.class).runTest(); + SampleCustomAnnotation annotation = description.getAnnotation(SampleCustomAnnotation.class); + if (annotation == null && description.getTestClass() != null) { + annotation = description.getTestClass().getAnnotation(SampleCustomAnnotation.class); + } + return annotation == null || annotation.runTest(); } @Override @@ -485,6 +509,7 @@ public void run() { fail("Broken"); } } + @Mock private ClassPathScanner mockClassPathScanner; private TestRequestBuilder builder; @@ -922,6 +947,23 @@ public void testCustomFilterAnnotation() { Assert.assertEquals(1, result.getRunCount()); } + /** Test that {@link CustomFilter} on a class-level annotation filters tests as appropriate */ + @Test + public void testCustomFilterAnnotation_classLevel() { + Request request = + builder + .addTestClass(SampleCustomFilterClassIncludedTestClass.class.getName()) + .addTestClass(SampleCustomFilterClassExcludedTestClass.class.getName()) + .build(); + List results = runRequest(request); + assertThat(results) + .containsExactly( + SampleCustomFilterClassIncludedTestClass.class.getName() + + "#testRunFromClassAnnotation", + SampleCustomFilterClassExcludedTestClass.class.getName() + + "#testRunOverridingClassAnnotation"); + } + /** Test that {@link CustomFilter} throws when the filter class cannot be instantiated */ @Test public void testMalformedCustomFilterAnnotation() {