diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index bb09719d9..319290ead 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -45,7 +45,10 @@ body: - allure-jsonunit - allure-junit-platform - allure-junit4 + - allure-jupiter + - allure-jupiter-assert - allure-junit5 + - allure-junit5-assert - allure-karate - allure-okhttp - allure-okhttp3 diff --git a/.github/labeler.yml b/.github/labeler.yml index a419c97f9..367271a00 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -48,8 +48,8 @@ - "allure-junit4-aspect/**" "theme:junit-platform": - - "allure-junit5/**" - - "allure-junit5-assert/**" + - "allure-jupiter/**" + - "allure-jupiter-assert/**" - "allure-junit-platform/**" "theme:karate": diff --git a/README.md b/README.md index e452787b3..5180b5077 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,12 @@ - 📚 Example project — https://github.com/allure-examples?q=topic%3Ajunit4 - ✅ Generate a project in 10 seconds via Allure Start - https://allurereport.org/start/ - -## JUnit 5 - -- 🚀 Documentation — https://allurereport.org/docs/junit5/ -- 📚 Example project — https://github.com/allure-examples?q=topic%3Ajunit5 -- ✅ Generate a project in 10 seconds via Allure Start - https://allurereport.org/start/ +## JUnit Jupiter (JUnit 5 and 6) + +- 🚀 Documentation — https://allurereport.org/docs/junit5/ +- 📚 Example project — https://github.com/allure-examples?q=topic%3Ajunit5 +- ✅ Generate a project in 10 seconds via Allure Start - https://allurereport.org/start/ +- 🧩 Use `io.qameta.allure:allure-jupiter` for new setups. `allure-junit5` remains available as a deprecated compatibility alias during migration. ## Cucumber JVM diff --git a/allure-bom/build.gradle.kts b/allure-bom/build.gradle.kts index 9593300aa..0d83d95e9 100644 --- a/allure-bom/build.gradle.kts +++ b/allure-bom/build.gradle.kts @@ -8,6 +8,8 @@ dependencies { constraints { rootProject.subprojects.sorted() .forEach { api("${it.group}:${it.name}:${it.version}") } + api("io.qameta.allure:allure-junit5:${project.version}") + api("io.qameta.allure:allure-junit5-assert:${project.version}") } } diff --git a/allure-junit5/src/main/services/org.junit.jupiter.api.extension.Extension b/allure-junit5/src/main/services/org.junit.jupiter.api.extension.Extension deleted file mode 100644 index 4a1ec18c0..000000000 --- a/allure-junit5/src/main/services/org.junit.jupiter.api.extension.Extension +++ /dev/null @@ -1 +0,0 @@ -io.qameta.allure.junit5.AllureJunit5 diff --git a/allure-junit5/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/allure-junit5/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension deleted file mode 100644 index 4a1ec18c0..000000000 --- a/allure-junit5/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension +++ /dev/null @@ -1 +0,0 @@ -io.qameta.allure.junit5.AllureJunit5 diff --git a/allure-junit5-assert/README.MD b/allure-jupiter-assert/README.MD similarity index 78% rename from allure-junit5-assert/README.MD rename to allure-jupiter-assert/README.MD index 5124d63c9..1705bcae0 100644 --- a/allure-junit5-assert/README.MD +++ b/allure-jupiter-assert/README.MD @@ -1,4 +1,6 @@ -Adding JUnit5-assert may lead to java.lang.OutOfMemoryError: Java heap space +Adding Jupiter assert may lead to java.lang.OutOfMemoryError: Java heap space + +The primary artifact is now `allure-jupiter-assert`. `allure-junit5-assert` remains available as a deprecated compatibility alias during the transition. Having a huge class path may lead to OOM, because AspectJ processes all the classes. [Link to documentation](https://www.eclipse.org/aspectj/doc/released/devguide/ltw.html) diff --git a/allure-junit5-assert/build.gradle.kts b/allure-jupiter-assert/build.gradle.kts similarity index 64% rename from allure-junit5-assert/build.gradle.kts rename to allure-jupiter-assert/build.gradle.kts index dd5410151..230fb5038 100644 --- a/allure-junit5-assert/build.gradle.kts +++ b/allure-jupiter-assert/build.gradle.kts @@ -1,7 +1,7 @@ -description = "Allure Junit5 Assertions Integration" +description = "Allure Jupiter Assertions Integration" dependencies { - api(project(":allure-junit5")) + api(project(":allure-jupiter")) compileOnly("org.aspectj:aspectjrt") compileOnly("org.junit.jupiter:junit-jupiter-api") testAnnotationProcessor(project(":allure-descriptions-javadoc")) @@ -15,7 +15,7 @@ dependencies { tasks.jar { manifest { attributes(mapOf( - "Automatic-Module-Name" to "io.qameta.allure.junit5-assert" + "Automatic-Module-Name" to "io.qameta.allure.jupiterassert" )) } } @@ -24,3 +24,10 @@ tasks.test { useJUnitPlatform() } +publishing { + publications { + create("legacyJunit5Assert") { + artifactId = "allure-junit5-assert" + } + } +} diff --git a/allure-jupiter-assert/src/main/java/io/qameta/allure/junit5assert/AllureJunit5Assert.java b/allure-jupiter-assert/src/main/java/io/qameta/allure/junit5assert/AllureJunit5Assert.java new file mode 100644 index 000000000..f7f04b0fa --- /dev/null +++ b/allure-jupiter-assert/src/main/java/io/qameta/allure/junit5assert/AllureJunit5Assert.java @@ -0,0 +1,26 @@ +/* + * Copyright 2016-2026 Qameta Software Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.qameta.allure.junit5assert; + +import io.qameta.allure.jupiterassert.AllureJupiterAssert; + +/** + * @author legionivo (Andrey Konovka). + * @deprecated use {@link AllureJupiterAssert}. + */ +@Deprecated +public class AllureJunit5Assert extends AllureJupiterAssert { +} diff --git a/allure-junit5-assert/src/main/java/io/qameta/allure/junit5assert/AllureJunit5Assert.java b/allure-jupiter-assert/src/main/java/io/qameta/allure/jupiterassert/AllureJupiterAssert.java similarity index 87% rename from allure-junit5-assert/src/main/java/io/qameta/allure/junit5assert/AllureJunit5Assert.java rename to allure-jupiter-assert/src/main/java/io/qameta/allure/jupiterassert/AllureJupiterAssert.java index e7fad0087..a259fdbb1 100644 --- a/allure-junit5-assert/src/main/java/io/qameta/allure/junit5assert/AllureJunit5Assert.java +++ b/allure-jupiter-assert/src/main/java/io/qameta/allure/jupiterassert/AllureJupiterAssert.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.qameta.allure.junit5assert; +package io.qameta.allure.jupiterassert; import io.qameta.allure.Allure; import io.qameta.allure.AllureLifecycle; @@ -41,13 +41,12 @@ */ @SuppressWarnings("all") @Aspect -public class AllureJunit5Assert { +public class AllureJupiterAssert { - private static final Logger LOGGER = LoggerFactory.getLogger(AllureJunit5Assert.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AllureJupiterAssert.class); private StepResult stepResult; - - private static InheritableThreadLocal lifecycle = new InheritableThreadLocal() { + private static final InheritableThreadLocal LIFECYCLE = new InheritableThreadLocal() { @Override protected AllureLifecycle initialValue() { return Allure.getLifecycle(); @@ -69,11 +68,10 @@ public void stepStart(final JoinPoint joinPoint) { if (joinPoint.getArgs().length > 1) { final String uuid = UUID.randomUUID().toString(); final String assertName = joinPoint.getSignature().getName(); - String name; + final String name; if (joinPoint.getSignature().getName().equalsIgnoreCase("assertAll")) { - name = String.format("assert All in " + " \'%s\'", joinPoint.getArgs()[0].toString()); + name = String.format("assert All in " + " '%s'", joinPoint.getArgs()[0].toString()); } else { - final String actual = joinPoint.getArgs().length > 0 ? ObjectUtils.toString(joinPoint.getArgs()[1]) : ""; @@ -83,12 +81,13 @@ public void stepStart(final JoinPoint joinPoint) { final List assertArray = Arrays.asList(assertName.split("(?=[A-Z])")); if (assertArray.size() >= 3) { - name = String.format(assertArray.get(0) + " " + assertArray.get(1) + " \'%s\'", expected) + name = String.format(assertArray.get(0) + " " + assertArray.get(1) + " '%s'", expected) + " " + String.format(assertArray.stream() .skip(2) - .collect(Collectors.joining(" ")) + " \'%s\'", actual); + .collect(Collectors.joining(" ")) + " '%s'", actual); } else { - name = String.format(assertArray.get(0) + " \'%s\'", expected) + " " + String.format(assertArray.get(1) + " \'%s\'", actual); + name = String.format(assertArray.get(0) + " '%s'", expected) + + " " + String.format(assertArray.get(1) + " '%s'", actual); } } final StepResult result = new StepResult() @@ -101,7 +100,7 @@ public void stepStart(final JoinPoint joinPoint) { : ""; final String uuid = UUID.randomUUID().toString(); final String assertName = joinPoint.getSignature().getName(); - final String name = String.format(assertName + " \'%s\'", actual); + final String name = String.format(assertName + " '%s'", actual); final StepResult result = new StepResult() .setName(name) @@ -129,11 +128,10 @@ public void stepStop() { * @param allure allure lifecycle to set. */ public static void setLifecycle(final AllureLifecycle allure) { - lifecycle.set(allure); + LIFECYCLE.set(allure); } public static AllureLifecycle getLifecycle() { - return lifecycle.get(); + return LIFECYCLE.get(); } - } diff --git a/allure-junit5-assert/src/main/resources/META-INF/aop-ajc.xml b/allure-jupiter-assert/src/main/resources/META-INF/aop-ajc.xml similarity index 56% rename from allure-junit5-assert/src/main/resources/META-INF/aop-ajc.xml rename to allure-jupiter-assert/src/main/resources/META-INF/aop-ajc.xml index 1ce84d6db..f4a039615 100644 --- a/allure-junit5-assert/src/main/resources/META-INF/aop-ajc.xml +++ b/allure-jupiter-assert/src/main/resources/META-INF/aop-ajc.xml @@ -1,6 +1,6 @@ - + diff --git a/allure-junit5-assert/src/test/java/io/qameta/allure/junit5assert/AllureJunit5AssertTest.java b/allure-jupiter-assert/src/test/java/io/qameta/allure/junit5assert/AllureJunit5AssertTest.java similarity index 100% rename from allure-junit5-assert/src/test/java/io/qameta/allure/junit5assert/AllureJunit5AssertTest.java rename to allure-jupiter-assert/src/test/java/io/qameta/allure/junit5assert/AllureJunit5AssertTest.java diff --git a/allure-jupiter-assert/src/test/java/io/qameta/allure/jupiterassert/AllureJupiterAssertTest.java b/allure-jupiter-assert/src/test/java/io/qameta/allure/jupiterassert/AllureJupiterAssertTest.java new file mode 100644 index 000000000..1da892a97 --- /dev/null +++ b/allure-jupiter-assert/src/test/java/io/qameta/allure/jupiterassert/AllureJupiterAssertTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2016-2026 Qameta Software Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.qameta.allure.jupiterassert; + +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import io.qameta.allure.test.AllureResults; +import org.junit.jupiter.api.Test; + +import static io.qameta.allure.test.RunUtils.runWithinTestContext; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AllureJupiterAssertTest { + + @Test + void shouldHandleAssertEquals() { + final AllureResults results = runWithinTestContext( + () -> assertEquals("expectedString", "actualString"), + AllureJupiterAssert::setLifecycle + ); + + assertThat(results.getTestResults()) + .flatExtracting(TestResult::getSteps) + .extracting(StepResult::getName) + .containsExactly("assert 'expectedString' Equals 'actualString'"); + } +} diff --git a/allure-junit5-assert/src/test/resources/allure.properties b/allure-jupiter-assert/src/test/resources/allure.properties similarity index 100% rename from allure-junit5-assert/src/test/resources/allure.properties rename to allure-jupiter-assert/src/test/resources/allure.properties diff --git a/allure-junit5/build.gradle.kts b/allure-jupiter/build.gradle.kts similarity index 84% rename from allure-junit5/build.gradle.kts rename to allure-jupiter/build.gradle.kts index 372885809..dd6033879 100644 --- a/allure-junit5/build.gradle.kts +++ b/allure-jupiter/build.gradle.kts @@ -1,4 +1,4 @@ -description = "Allure JUnit 5 Integration" +description = "Allure Jupiter Integration" dependencies { api(project(":allure-junit-platform")) @@ -19,7 +19,7 @@ dependencies { tasks.jar { manifest { attributes(mapOf( - "Automatic-Module-Name" to "io.qameta.allure.junit5" + "Automatic-Module-Name" to "io.qameta.allure.jupiter" )) } from("src/main/services") { @@ -43,6 +43,9 @@ publishing { named("maven") { artifact(spiOffJar) } + create("legacyJunit5") { + artifactId = "allure-junit5" + artifact(spiOffJar) + } } } - diff --git a/allure-jupiter/src/main/java/io/qameta/allure/junit5/AllureJunit5.java b/allure-jupiter/src/main/java/io/qameta/allure/junit5/AllureJunit5.java new file mode 100644 index 000000000..2231d34e0 --- /dev/null +++ b/allure-jupiter/src/main/java/io/qameta/allure/junit5/AllureJunit5.java @@ -0,0 +1,26 @@ +/* + * Copyright 2016-2026 Qameta Software Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.qameta.allure.junit5; + +import io.qameta.allure.jupiter.AllureJupiter; + +/** + * @author charlie (Dmitry Baev). + * @deprecated use {@link AllureJupiter}. + */ +@Deprecated +public class AllureJunit5 extends AllureJupiter { +} diff --git a/allure-junit5/src/main/java/io/qameta/allure/junit5/AllureJunit5.java b/allure-jupiter/src/main/java/io/qameta/allure/jupiter/AllureJupiter.java similarity index 88% rename from allure-junit5/src/main/java/io/qameta/allure/junit5/AllureJunit5.java rename to allure-jupiter/src/main/java/io/qameta/allure/jupiter/AllureJupiter.java index 3d1019a2b..1641ed1f7 100644 --- a/allure-junit5/src/main/java/io/qameta/allure/junit5/AllureJunit5.java +++ b/allure-jupiter/src/main/java/io/qameta/allure/jupiter/AllureJupiter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.qameta.allure.junit5; +package io.qameta.allure.jupiter; import io.qameta.allure.Param; import io.qameta.allure.model.Status; @@ -27,8 +27,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.HashMap; -import java.util.Map; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -50,12 +50,18 @@ * @author charlie (Dmitry Baev). */ @SuppressWarnings("MultipleStringLiterals") -public class AllureJunit5 implements InvocationInterceptor { +public class AllureJupiter implements InvocationInterceptor { + + private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create(AllureJupiter.class); @Override public void interceptTestTemplateMethod(final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + if (!shouldHandle(extensionContext, "template", invocationContext.getExecutable())) { + invocation.proceed(); + return; + } sendParameterEvent(invocationContext, extensionContext); invocation.proceed(); } @@ -134,6 +140,10 @@ protected void processFixture(final String type, final Invocation invocation, final ReflectiveInvocationContext invocationContext, final ExtensionContext extensionContext) throws Throwable { + if (!shouldHandle(extensionContext, type, invocationContext.getExecutable())) { + invocation.proceed(); + return; + } final String uuid = UUID.randomUUID().toString(); try { extensionContext.publishReportEntry(wrap(buildStartEvent( @@ -206,4 +216,19 @@ public Map wrap(final Map data) { ); return res; } + + private boolean shouldHandle(final ExtensionContext extensionContext, + final String eventType, + final Method method) { + final Object marker = new Object(); + final String key = String.join(":", + extensionContext.getUniqueId(), + eventType, + method.toGenericString() + ); + final Object storedMarker = extensionContext.getRoot() + .getStore(NAMESPACE) + .getOrComputeIfAbsent(key, ignored -> marker); + return marker.equals(storedMarker); + } } diff --git a/allure-jupiter/src/main/services/org.junit.jupiter.api.extension.Extension b/allure-jupiter/src/main/services/org.junit.jupiter.api.extension.Extension new file mode 100644 index 000000000..17a075141 --- /dev/null +++ b/allure-jupiter/src/main/services/org.junit.jupiter.api.extension.Extension @@ -0,0 +1 @@ +io.qameta.allure.jupiter.AllureJupiter diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/AllureJunit5Junit6CompatibilityTest.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/AllureJunit5Junit6CompatibilityTest.java similarity index 87% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/AllureJunit5Junit6CompatibilityTest.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/AllureJunit5Junit6CompatibilityTest.java index a9d85cc24..c1d5171c5 100644 --- a/allure-junit5/src/test/java/io/qameta/allure/junit5/AllureJunit5Junit6CompatibilityTest.java +++ b/allure-jupiter/src/test/java/io/qameta/allure/junit5/AllureJunit5Junit6CompatibilityTest.java @@ -90,12 +90,17 @@ void shouldCaptureParametersWithParamAnnotationOnJunit6() { .toList(); assertThat(allParams) - .isNotEmpty() + .filteredOn(parameter -> "id".equals(parameter.getName())) .extracting(Parameter::getName, Parameter::getValue) - .contains( + .containsExactlyInAnyOrder( tuple("id", "a"), tuple("id", "b") ); + + assertThat(allParams) + .filteredOn(parameter -> "id".equals(parameter.getName())) + .extracting(Parameter::getName, Parameter::getValue) + .doesNotHaveDuplicates(); } @Test @@ -111,30 +116,34 @@ void shouldCaptureFixturesAndStepsOnJunit6() { assertThat(results.getTestResultContainers()) .flatExtracting(TestResultContainer::getBefores) - .extracting(FixtureResult::getStatus) - .contains(Status.PASSED); + .extracting(FixtureResult::getName, FixtureResult::getStatus) + .containsExactly( + tuple("setUp", Status.PASSED) + ); assertThat(results.getTestResultContainers()) .flatExtracting(TestResultContainer::getAfters) - .extracting(FixtureResult::getStatus) - .contains(Status.PASSED); + .extracting(FixtureResult::getName, FixtureResult::getStatus) + .containsExactly( + tuple("tearDown", Status.PASSED) + ); assertThat(results.getTestResultContainers()) .flatExtracting(TestResultContainer::getBefores) .flatExtracting(FixtureResult::getSteps) .extracting(StepResult::getName) - .contains("before step"); + .containsExactly("before step"); assertThat(results.getTestResults()) .flatExtracting(TestResult::getSteps) .extracting(StepResult::getName) - .contains("test step"); + .containsExactly("test step"); assertThat(results.getTestResultContainers()) .flatExtracting(TestResultContainer::getAfters) .flatExtracting(FixtureResult::getSteps) .extracting(StepResult::getName) - .contains("after step"); + .containsExactly("after step"); } @io.qameta.allure.Step("Run classes {classes}") diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/AllureJunit5Test.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/AllureJunit5Test.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/AllureJunit5Test.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/AllureJunit5Test.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/AfterEachFixtureBrokenSupport.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/AfterEachFixtureBrokenSupport.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/AfterEachFixtureBrokenSupport.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/AfterEachFixtureBrokenSupport.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/AllFixtureSupport.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/AllFixtureSupport.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/AllFixtureSupport.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/AllFixtureSupport.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/BeforeAllFixtureFailureSupport.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/BeforeAllFixtureFailureSupport.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/BeforeAllFixtureFailureSupport.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/BeforeAllFixtureFailureSupport.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/BeforeEachFixtureBrokenSupport.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/BeforeEachFixtureBrokenSupport.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/BeforeEachFixtureBrokenSupport.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/BeforeEachFixtureBrokenSupport.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/EachFixtureSupport.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/EachFixtureSupport.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/EachFixtureSupport.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/EachFixtureSupport.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedBlankParameterValueTests.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedBlankParameterValueTests.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedBlankParameterValueTests.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedBlankParameterValueTests.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedPrimitivesTests.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedPrimitivesTests.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedPrimitivesTests.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedPrimitivesTests.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedTests.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedTests.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedTests.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedTests.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedWithInjectablesTests.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedWithInjectablesTests.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/ParameterisedWithInjectablesTests.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/ParameterisedWithInjectablesTests.java diff --git a/allure-junit5/src/test/java/io/qameta/allure/junit5/features/SkipOtherInjectables.java b/allure-jupiter/src/test/java/io/qameta/allure/junit5/features/SkipOtherInjectables.java similarity index 100% rename from allure-junit5/src/test/java/io/qameta/allure/junit5/features/SkipOtherInjectables.java rename to allure-jupiter/src/test/java/io/qameta/allure/junit5/features/SkipOtherInjectables.java diff --git a/allure-jupiter/src/test/java/io/qameta/allure/jupiter/AllureJupiterJunit6CompatibilityTest.java b/allure-jupiter/src/test/java/io/qameta/allure/jupiter/AllureJupiterJunit6CompatibilityTest.java new file mode 100644 index 000000000..f40fe2bd8 --- /dev/null +++ b/allure-jupiter/src/test/java/io/qameta/allure/jupiter/AllureJupiterJunit6CompatibilityTest.java @@ -0,0 +1,165 @@ +/* + * Copyright 2016-2026 Qameta Software Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.qameta.allure.jupiter; + +import io.qameta.allure.Allure; +import io.qameta.allure.Param; +import io.qameta.allure.junitplatform.AllureJunitPlatform; +import io.qameta.allure.model.FixtureResult; +import io.qameta.allure.model.Parameter; +import io.qameta.allure.model.Status; +import io.qameta.allure.model.StepResult; +import io.qameta.allure.model.TestResult; +import io.qameta.allure.model.TestResultContainer; +import io.qameta.allure.test.AllureResults; +import io.qameta.allure.test.RunUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.platform.engine.discovery.ClassSelector; +import org.junit.platform.engine.discovery.DiscoverySelectors; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.core.LauncherConfig; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; +import org.junit.platform.launcher.core.LauncherFactory; + +import java.util.List; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; + +@Tag("junit6-compat") +@SuppressWarnings("unused") +class AllureJupiterJunit6CompatibilityTest { + + @ExtendWith(AllureJupiter.class) + static class CompatParametersTest { + + @org.junit.jupiter.params.ParameterizedTest + @org.junit.jupiter.params.provider.ValueSource(strings = {"a", "b"}) + void paramTest(@Param("id") final String value) { + } + } + + @Nested + @ExtendWith(AllureJupiter.class) + class CompatFixtures { + + @BeforeEach + void setUp() { + Allure.step("before step"); + } + + @Test + void testBody() { + Allure.step("test step"); + } + + @AfterEach + void tearDown() { + Allure.step("after step"); + } + } + + @Test + void shouldCaptureParametersWithParamAnnotationOnJunit6() { + final AllureResults results = runWithLauncher(CompatParametersTest.class); + + assertThat(results.getTestResults()).isNotEmpty(); + + final List allParams = results.getTestResults().stream() + .flatMap(tr -> tr.getParameters().stream()) + .toList(); + + assertThat(allParams) + .filteredOn(parameter -> "id".equals(parameter.getName())) + .extracting(Parameter::getName, Parameter::getValue) + .containsExactlyInAnyOrder( + tuple("id", "a"), + tuple("id", "b") + ); + } + + @Test + void shouldCaptureFixturesAndStepsOnJunit6() { + final AllureResults results = runWithLauncher(CompatFixtures.class); + + assertThat(results.getTestResults()).hasSize(1); + final TestResult testResult = results.getTestResults().get(0); + + assertThat(results.getTestResultContainers()) + .flatExtracting(TestResultContainer::getChildren) + .contains(testResult.getUuid()); + + assertThat(results.getTestResultContainers()) + .flatExtracting(TestResultContainer::getBefores) + .extracting(FixtureResult::getName, FixtureResult::getStatus) + .containsExactly( + tuple("setUp", Status.PASSED) + ); + + assertThat(results.getTestResultContainers()) + .flatExtracting(TestResultContainer::getAfters) + .extracting(FixtureResult::getName, FixtureResult::getStatus) + .containsExactly( + tuple("tearDown", Status.PASSED) + ); + + assertThat(results.getTestResultContainers()) + .flatExtracting(TestResultContainer::getBefores) + .flatExtracting(FixtureResult::getSteps) + .extracting(StepResult::getName) + .containsExactly("before step"); + + assertThat(results.getTestResults()) + .flatExtracting(TestResult::getSteps) + .extracting(StepResult::getName) + .containsExactly("test step"); + + assertThat(results.getTestResultContainers()) + .flatExtracting(TestResultContainer::getAfters) + .flatExtracting(FixtureResult::getSteps) + .extracting(StepResult::getName) + .containsExactly("after step"); + } + + @io.qameta.allure.Step("Run classes {classes}") + private AllureResults runWithLauncher(final Class... classes) { + return RunUtils.runTests(lifecycle -> { + final ClassSelector[] selectors = Stream.of(classes) + .map(DiscoverySelectors::selectClass) + .toArray(ClassSelector[]::new); + + final LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() + .configurationParameter("junit.jupiter.extensions.autodetection.enabled", "true") + .selectors(selectors) + .build(); + + final LauncherConfig config = LauncherConfig.builder() + .enableTestExecutionListenerAutoRegistration(false) + .addTestExecutionListeners(new AllureJunitPlatform(lifecycle)) + .build(); + + final Launcher launcher = LauncherFactory.create(config); + launcher.execute(request); + }); + } +} diff --git a/allure-jupiter/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/allure-jupiter/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension new file mode 100644 index 000000000..17a075141 --- /dev/null +++ b/allure-jupiter/src/test/resources/META-INF/services/org.junit.jupiter.api.extension.Extension @@ -0,0 +1 @@ +io.qameta.allure.jupiter.AllureJupiter diff --git a/allure-junit5/src/test/resources/allure.properties b/allure-jupiter/src/test/resources/allure.properties similarity index 100% rename from allure-junit5/src/test/resources/allure.properties rename to allure-jupiter/src/test/resources/allure.properties diff --git a/allure-scalatest/build.gradle.kts b/allure-scalatest/build.gradle.kts index a5ecc550d..f16998fea 100644 --- a/allure-scalatest/build.gradle.kts +++ b/allure-scalatest/build.gradle.kts @@ -74,13 +74,6 @@ publishing { } } -signing { - sign( - publishing.publications["crossBuildScala_212"], - publishing.publications["crossBuildScala_213"] - ) -} - dependencies { api(project(":allure-java-commons")) compileOnly("org.scalatest:scalatest_$scala213:3.2.19") diff --git a/build.gradle.kts b/build.gradle.kts index b3a82e141..ac086dec1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ val qualityConfigsDir by extra("$gradleScriptDir/quality-configs") val spotlessDtr by extra("$qualityConfigsDir/spotless") val libs = subprojects.filterNot { it.name in "allure-bom" } +val standardJavaLibs = libs.filterNot { it.name == "allure-scalatest" } tasks.withType(Wrapper::class) { gradleVersion = "8.5" @@ -60,6 +61,12 @@ configure(subprojects) { publishing { publications { withType().configureEach { + suppressAllPomMetadataWarnings() + versionMapping { + allVariants { + fromResolutionResult() + } + } pom { name.set(project.name) description.set("Module ${project.name} of Allure Framework.") @@ -103,19 +110,12 @@ configure(subprojects) { } } } - create("maven") { - suppressAllPomMetadataWarnings() - versionMapping { - allVariants { - fromResolutionResult() - } - } - } + create("maven") } } signing { - sign(publishing.publications["maven"]) + sign(publishing.publications) } tasks.withType().configureEach { @@ -375,17 +375,74 @@ configure(libs) { } } - publishing.publications.named("maven") { - pom { - from(components["java"]) - } - } - val allDepsInsight by tasks.creating(DependencyInsightReportTask::class) { showingAllVariants.set(true) } } +configure(standardJavaLibs) { + publishing.publications.withType().configureEach { + from(components["java"]) + } +} + +val verifyJupiterCompatibilityBridge by tasks.registering { + dependsOn( + ":allure-bom:generatePomFileForMavenPublication" + ) + + doLast { + fun publicationArtifactIds(projectPath: String): Set = + project(projectPath) + .extensions + .getByType(org.gradle.api.publish.PublishingExtension::class.java) + .publications + .withType(MavenPublication::class.java) + .mapTo(linkedSetOf()) { it.artifactId } + + val jupiterArtifactIds = publicationArtifactIds(":allure-jupiter") + check("allure-jupiter" in jupiterArtifactIds) { + "Expected :allure-jupiter to publish the primary allure-jupiter coordinate." + } + check("allure-junit5" in jupiterArtifactIds) { + "Expected :allure-jupiter to publish the legacy allure-junit5 alias." + } + + val jupiterAssertArtifactIds = publicationArtifactIds(":allure-jupiter-assert") + check("allure-jupiter-assert" in jupiterAssertArtifactIds) { + "Expected :allure-jupiter-assert to publish the primary allure-jupiter-assert coordinate." + } + check("allure-junit5-assert" in jupiterAssertArtifactIds) { + "Expected :allure-jupiter-assert to publish the legacy allure-junit5-assert alias." + } + + val bomPom = project(":allure-bom") + .layout + .buildDirectory + .file("publications/maven/pom-default.xml") + .get() + .asFile + .readText() + + check("allure-jupiter" in bomPom) { + "Expected allure-bom to manage allure-jupiter." + } + check("allure-junit5" in bomPom) { + "Expected allure-bom to manage the legacy allure-junit5 alias." + } + check("allure-jupiter-assert" in bomPom) { + "Expected allure-bom to manage allure-jupiter-assert." + } + check("allure-junit5-assert" in bomPom) { + "Expected allure-bom to manage the legacy allure-junit5-assert alias." + } + } +} + +tasks.check { + dependsOn(verifyJupiterCompatibilityBridge) +} + allure { version.set("2.19.0") } diff --git a/settings.gradle.kts b/settings.gradle.kts index bf49b841b..ad6f5e51d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,8 +24,8 @@ include("allure-jsonunit") include("allure-junit-platform") include("allure-junit4") include("allure-junit4-aspect") -include("allure-junit5") -include("allure-junit5-assert") +include("allure-jupiter") +include("allure-jupiter-assert") include("allure-karate") include("allure-model") include("allure-okhttp")