Skip to content

Commit abdb58b

Browse files
authored
report metadata from inherited junit jupiter test methods (fixes #1032, via #1317)
1 parent e7f02d1 commit abdb58b

7 files changed

Lines changed: 243 additions & 6 deletions

File tree

allure-junit-platform/src/main/java/io/qameta/allure/junitplatform/AllureJunitPlatformUtils.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package io.qameta.allure.junitplatform;
1717

18+
import org.junit.platform.commons.JUnitException;
1819
import org.junit.platform.engine.TestSource;
1920
import org.junit.platform.engine.support.descriptor.ClassSource;
2021
import org.junit.platform.engine.support.descriptor.ClasspathResourceSource;
@@ -24,7 +25,6 @@
2425

2526
import java.lang.reflect.Method;
2627
import java.util.Optional;
27-
import java.util.stream.Stream;
2828
/* package-private */ final class AllureJunitPlatformUtils {
2929

3030
private static final Logger LOGGER = LoggerFactory.getLogger(AllureJunitPlatformUtils.class);
@@ -81,11 +81,10 @@ static Optional<Method> getTestMethod(final TestSource source) {
8181

8282
static Optional<Method> getTestMethod(final MethodSource source) {
8383
try {
84-
final Class<?> aClass = Class.forName(source.getClassName());
85-
return Stream.of(aClass.getDeclaredMethods())
86-
.filter(method -> MethodSource.from(method).equals(source))
87-
.findAny();
88-
} catch (ClassNotFoundException e) {
84+
// resolves the method in the whole class hierarchy, including
85+
// test methods inherited from super classes
86+
return Optional.ofNullable(source.getJavaMethod());
87+
} catch (JUnitException e) {
8988
LOGGER.trace("Could not get test method from method source {}", source, e);
9089
}
9190
return Optional.empty();

allure-junit-platform/src/test/java/io/qameta/allure/junitplatform/AllureJunitPlatformTest.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,11 @@
5151
import io.qameta.allure.junitplatform.features.TestWithClassLinks;
5252
import io.qameta.allure.junitplatform.features.TestWithDescription;
5353
import io.qameta.allure.junitplatform.features.TestWithDisplayName;
54+
import io.qameta.allure.junitplatform.features.TestWithInheritedMetadata;
55+
import io.qameta.allure.junitplatform.features.TestWithInterfaceDefaultMetadata;
5456
import io.qameta.allure.junitplatform.features.TestWithMethodLabels;
5557
import io.qameta.allure.junitplatform.features.TestWithMethodLinks;
58+
import io.qameta.allure.junitplatform.features.TestWithOverriddenMetadata;
5659
import io.qameta.allure.junitplatform.features.TestWithPublishedFile;
5760
import io.qameta.allure.junitplatform.features.TestWithSteps;
5861
import io.qameta.allure.junitplatform.features.TestWithSystemErr;
@@ -94,6 +97,7 @@
9497
import static io.qameta.allure.test.AllurePredicates.hasLabel;
9598
import static io.qameta.allure.test.AllurePredicates.hasStatus;
9699
import static io.qameta.allure.util.ResultsUtils.ALLURE_ID_LABEL_NAME;
100+
import static io.qameta.allure.util.ResultsUtils.EPIC_LABEL_NAME;
97101
import static io.qameta.allure.util.ResultsUtils.FEATURE_LABEL_NAME;
98102
import static io.qameta.allure.util.ResultsUtils.HOST_LABEL_NAME;
99103
import static io.qameta.allure.util.ResultsUtils.OWNER_LABEL_NAME;
@@ -448,6 +452,89 @@ void shouldProcessMethodLabels() {
448452
);
449453
}
450454

455+
@Test
456+
@AllureFeatures.MarkerAnnotations
457+
@Issue("1032")
458+
void shouldProcessAnnotationsOnInheritedTestMethods() {
459+
final AllureResults results = runClasses(TestWithInheritedMetadata.class);
460+
final List<TestResult> testResults = results.getTestResults();
461+
assertThat(testResults)
462+
.hasSize(1);
463+
464+
final TestResult testResult = testResults.get(0);
465+
assertThat(testResult.getDescription())
466+
.isEqualTo("Inherited test description");
467+
468+
assertThat(testResult.getLabels())
469+
.extracting(Label::getName, Label::getValue)
470+
.contains(
471+
tuple(EPIC_LABEL_NAME, "inherited-epic"),
472+
tuple(FEATURE_LABEL_NAME, "inherited-feature"),
473+
tuple(STORY_LABEL_NAME, "inherited-story"),
474+
tuple(OWNER_LABEL_NAME, "inherited-owner"),
475+
tuple(SEVERITY_LABEL_NAME, "critical")
476+
);
477+
478+
assertThat(testResult.getLinks())
479+
.extracting(Link::getName, Link::getUrl)
480+
.contains(tuple("INHERITED-LINK", "https://example.org/inherited"));
481+
}
482+
483+
@Test
484+
@AllureFeatures.MarkerAnnotations
485+
@Issue("1032")
486+
void shouldProcessAnnotationsOnInterfaceDefaultTestMethods() {
487+
final AllureResults results = runClasses(TestWithInterfaceDefaultMetadata.class);
488+
final List<TestResult> testResults = results.getTestResults();
489+
assertThat(testResults)
490+
.hasSize(1);
491+
492+
final TestResult testResult = testResults.get(0);
493+
assertThat(testResult.getDescription())
494+
.isEqualTo("Interface default test description");
495+
496+
assertThat(testResult.getLabels())
497+
.extracting(Label::getName, Label::getValue)
498+
.contains(
499+
tuple(STORY_LABEL_NAME, "interface-story"),
500+
tuple(OWNER_LABEL_NAME, "interface-owner"),
501+
tuple(SEVERITY_LABEL_NAME, "minor")
502+
);
503+
504+
assertThat(testResult.getLinks())
505+
.extracting(Link::getName, Link::getUrl)
506+
.contains(tuple("INTERFACE-LINK", "https://example.org/interface"));
507+
}
508+
509+
@Test
510+
@AllureFeatures.MarkerAnnotations
511+
@Issue("1032")
512+
void shouldUseOverriddenTestMethodAnnotations() {
513+
final AllureResults results = runClasses(TestWithOverriddenMetadata.class);
514+
final List<TestResult> testResults = results.getTestResults();
515+
assertThat(testResults)
516+
.hasSize(1);
517+
518+
// the overriding method fully replaces the inherited one, so only
519+
// the annotations declared on the override are reported
520+
final TestResult testResult = testResults.get(0);
521+
assertThat(testResult.getDescription())
522+
.isEqualTo("Overridden test description");
523+
524+
assertThat(testResult.getLabels())
525+
.extracting(Label::getName, Label::getValue)
526+
.contains(tuple(STORY_LABEL_NAME, "overridden-story"))
527+
.doesNotContain(
528+
tuple(STORY_LABEL_NAME, "interface-story"),
529+
tuple(OWNER_LABEL_NAME, "interface-owner"),
530+
tuple(SEVERITY_LABEL_NAME, "minor")
531+
);
532+
533+
assertThat(testResult.getLinks())
534+
.extracting(Link::getName)
535+
.doesNotContain("INTERFACE-LINK");
536+
}
537+
451538
@Test
452539
@AllureFeatures.MarkerAnnotations
453540
void shouldProcessClassLabels() {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2016-2026 Qameta Software Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.junitplatform.features;
17+
18+
import io.qameta.allure.Description;
19+
import io.qameta.allure.Epic;
20+
import io.qameta.allure.Feature;
21+
import io.qameta.allure.Link;
22+
import io.qameta.allure.Owner;
23+
import io.qameta.allure.Severity;
24+
import io.qameta.allure.SeverityLevel;
25+
import io.qameta.allure.Story;
26+
import org.junit.jupiter.api.Test;
27+
28+
public abstract class AbstractTestWithMetadata {
29+
30+
@Test
31+
@Description("Inherited test description")
32+
@Epic("inherited-epic")
33+
@Feature("inherited-feature")
34+
@Story("inherited-story")
35+
@Owner("inherited-owner")
36+
@Severity(SeverityLevel.CRITICAL)
37+
@Link(
38+
name = "INHERITED-LINK",
39+
url = "https://example.org/inherited"
40+
)
41+
void inheritedTest() {
42+
}
43+
44+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2016-2026 Qameta Software Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.junitplatform.features;
17+
18+
import io.qameta.allure.Description;
19+
import io.qameta.allure.Link;
20+
import io.qameta.allure.Owner;
21+
import io.qameta.allure.Severity;
22+
import io.qameta.allure.SeverityLevel;
23+
import io.qameta.allure.Story;
24+
import org.junit.jupiter.api.Test;
25+
26+
public interface InterfaceWithMetadata {
27+
28+
@Test
29+
@Description("Interface default test description")
30+
@Story("interface-story")
31+
@Owner("interface-owner")
32+
@Severity(SeverityLevel.MINOR)
33+
@Link(
34+
name = "INTERFACE-LINK",
35+
url = "https://example.org/interface"
36+
)
37+
default void interfaceDefaultTest() {
38+
}
39+
40+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2016-2026 Qameta Software Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.junitplatform.features;
17+
public class TestWithInheritedMetadata extends AbstractTestWithMetadata {
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright 2016-2026 Qameta Software Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.junitplatform.features;
17+
public class TestWithInterfaceDefaultMetadata implements InterfaceWithMetadata {
18+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2016-2026 Qameta Software Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.qameta.allure.junitplatform.features;
17+
18+
import io.qameta.allure.Description;
19+
import io.qameta.allure.Story;
20+
import org.junit.jupiter.api.Test;
21+
22+
public class TestWithOverriddenMetadata implements InterfaceWithMetadata {
23+
24+
@Test
25+
@Override
26+
@Description("Overridden test description")
27+
@Story("overridden-story")
28+
public void interfaceDefaultTest() {
29+
}
30+
31+
}

0 commit comments

Comments
 (0)