Skip to content

Commit a3758a9

Browse files
committed
Make @tag and @tags inherited
Prior to this commit, class-level declarations of @tag and @tags were not inherited. This commit addresses this issue by annotating @tag and @tags with @inherited. Fixes: #1158
1 parent 65f17cd commit a3758a9

File tree

4 files changed

+21
-18
lines changed

4 files changed

+21
-18
lines changed

documentation/src/docs/asciidoc/release-notes-5.1.0-M1.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ on GitHub.
5050

5151
===== Bug Fixes
5252

53-
*
53+
* The `@Tag` and `@Tags` annotations are now inherited within test class hierarchies.
5454

5555
===== Deprecations and Breaking Changes
5656

junit-jupiter-api/src/main/java/org/junit/jupiter/api/Tag.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import java.lang.annotation.Documented;
1616
import java.lang.annotation.ElementType;
17+
import java.lang.annotation.Inherited;
1718
import java.lang.annotation.Repeatable;
1819
import java.lang.annotation.Retention;
1920
import java.lang.annotation.RetentionPolicy;
@@ -56,6 +57,7 @@
5657
@Target({ ElementType.TYPE, ElementType.METHOD })
5758
@Retention(RetentionPolicy.RUNTIME)
5859
@Documented
60+
@Inherited
5961
@Repeatable(Tags.class)
6062
@API(status = STABLE, since = "5.0")
6163
public @interface Tag {

junit-jupiter-api/src/main/java/org/junit/jupiter/api/Tags.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import java.lang.annotation.Documented;
1616
import java.lang.annotation.ElementType;
17+
import java.lang.annotation.Inherited;
1718
import java.lang.annotation.Retention;
1819
import java.lang.annotation.RetentionPolicy;
1920
import java.lang.annotation.Target;
@@ -34,6 +35,7 @@
3435
@Target({ ElementType.TYPE, ElementType.METHOD })
3536
@Retention(RetentionPolicy.RUNTIME)
3637
@Documented
38+
@Inherited
3739
@API(status = STABLE, since = "5.0")
3840
public @interface Tags {
3941

junit-jupiter-engine/src/test/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptorTests.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
package org.junit.jupiter.engine.descriptor;
1212

13+
import static java.util.stream.Collectors.toList;
1314
import static org.assertj.core.api.Assertions.assertThat;
1415
import static org.junit.jupiter.api.Assertions.assertEquals;
15-
import static org.junit.jupiter.api.Assertions.assertTrue;
1616

1717
import java.lang.annotation.ElementType;
1818
import java.lang.annotation.Retention;
@@ -21,7 +21,6 @@
2121
import java.lang.reflect.Method;
2222
import java.math.BigDecimal;
2323
import java.util.List;
24-
import java.util.stream.Collectors;
2524

2625
import org.junit.jupiter.api.AfterAll;
2726
import org.junit.jupiter.api.AfterEach;
@@ -48,15 +47,16 @@ class JupiterTestDescriptorTests {
4847
private static final UniqueId uniqueId = UniqueId.root("enigma", "foo");
4948

5049
@Test
51-
void constructFromClass() throws Exception {
50+
void constructFromClass() {
5251
ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCase.class);
5352

5453
assertEquals(TestCase.class, descriptor.getTestClass());
55-
assertThat(descriptor.getTags()).containsExactly(TestTag.create("classTag1"), TestTag.create("classTag2"));
54+
assertThat(descriptor.getTags()).containsExactly(TestTag.create("inherited-class-level-tag"),
55+
TestTag.create("classTag1"), TestTag.create("classTag2"));
5656
}
5757

5858
@Test
59-
void constructFromClassWithInvalidBeforeAllDeclaration() throws Exception {
59+
void constructFromClassWithInvalidBeforeAllDeclaration() {
6060
// Note: if we can instantiate the descriptor, then the invalid configuration
6161
// will not be reported during the test engine discovery phase.
6262
ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidBeforeAllMethod.class);
@@ -65,7 +65,7 @@ void constructFromClassWithInvalidBeforeAllDeclaration() throws Exception {
6565
}
6666

6767
@Test
68-
void constructFromClassWithInvalidAfterAllDeclaration() throws Exception {
68+
void constructFromClassWithInvalidAfterAllDeclaration() {
6969
// Note: if we can instantiate the descriptor, then the invalid configuration
7070
// will not be reported during the test engine discovery phase.
7171
ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidAfterAllMethod.class);
@@ -74,7 +74,7 @@ void constructFromClassWithInvalidAfterAllDeclaration() throws Exception {
7474
}
7575

7676
@Test
77-
void constructFromClassWithInvalidBeforeEachDeclaration() throws Exception {
77+
void constructFromClassWithInvalidBeforeEachDeclaration() {
7878
// Note: if we can instantiate the descriptor, then the invalid configuration
7979
// will not be reported during the test engine discovery phase.
8080
ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidBeforeEachMethod.class);
@@ -83,7 +83,7 @@ void constructFromClassWithInvalidBeforeEachDeclaration() throws Exception {
8383
}
8484

8585
@Test
86-
void constructFromClassWithInvalidAfterEachDeclaration() throws Exception {
86+
void constructFromClassWithInvalidAfterEachDeclaration() {
8787
// Note: if we can instantiate the descriptor, then the invalid configuration
8888
// will not be reported during the test engine discovery phase.
8989
ClassTestDescriptor descriptor = new ClassTestDescriptor(uniqueId, TestCaseWithInvalidAfterEachMethod.class);
@@ -112,14 +112,9 @@ void constructFromMethodWithAnnotations() throws Exception {
112112
assertEquals(testMethod, methodDescriptor.getTestMethod());
113113
assertEquals("custom test name", methodDescriptor.getDisplayName(), "display name:");
114114

115-
List<String> tags = methodDescriptor.getTags().stream().map(TestTag::getName).collect(Collectors.toList());
116-
assertEquals(4, methodDescriptor.getTags().size());
117-
assertTrue(tags.contains("methodTag1"));
118-
assertTrue(tags.contains("methodTag2"));
119-
120-
// Methods "inherit" tags from their test class
121-
assertTrue(tags.contains("classTag1"));
122-
assertTrue(tags.contains("classTag2"));
115+
List<String> tags = methodDescriptor.getTags().stream().map(TestTag::getName).collect(toList());
116+
assertThat(tags).containsExactlyInAnyOrder("inherited-class-level-tag", "classTag1", "classTag2", "methodTag1",
117+
"methodTag2");
123118
}
124119

125120
@Test
@@ -204,11 +199,15 @@ void defaultDisplayNamesForTestClasses() {
204199
@interface CustomTestAnnotation {
205200
}
206201

202+
@Tag("inherited-class-level-tag")
203+
private static abstract class AbstractTestCase {
204+
}
205+
207206
@Tag("classTag1")
208207
@Tag("classTag2")
209208
@DisplayName("custom class name")
210209
@SuppressWarnings("unused")
211-
private static class TestCase {
210+
private static class TestCase extends AbstractTestCase {
212211

213212
void test() {
214213
}

0 commit comments

Comments
 (0)