From c7dcc563456d3c0a706f37b9cdd776a2caf5764f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Apr 2026 19:32:44 +0000 Subject: [PATCH 1/2] fix(deps): update spring core to v7 Signed-off-by: Renovate Bot --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 80cf8726d2a..d885cccd32b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ junit4-version = "4.13.2" mockito-version = "5.23.0" paranamer-version = "2.8.3" slf4j-version = "2.0.18" -spring-version = "6.2.19" +spring-version = "7.0.6" androidx-test-version = "1.7.0" vanniktech-version = "0.36.0" From 97a547b8117f15e3e8a4caae3786695604669537 Mon Sep 17 00:00:00 2001 From: l-1squared Date: Fri, 10 Apr 2026 14:59:35 +0200 Subject: [PATCH 2/2] chore(Spring 7): Separate Spring7/JUnit6 from Spring6/JUnit5 Signed-off-by: l-1squared <30831153+l-1squared@users.noreply.github.com> --- .../workflows/jgiven_branch_and_pr_build.yml | 44 ++++- CHANGELOG.md | 14 ++ build.gradle | 5 - gradle/libs.versions.toml | 32 +++- jgiven-future-java-tests/build.gradle.kts | 4 +- .../sealed/SealedClassesHandlingTest.java | 11 +- jgiven-gradle-plugin/build.gradle.kts | 2 +- jgiven-junit5/build.gradle.kts | 23 ++- .../jgiven/junit5/DualScenarioTest.java | 28 +--- .../jgiven/junit5/JGivenExtension.java | 151 +---------------- .../tngtech/jgiven/junit5/ScenarioTest.java | 29 +--- .../jgiven/junit5/SimpleScenarioTest.java | 21 +-- .../JUnit5DefaultTagConfigurationTest.java | 2 +- jgiven-junit6/build.gradle.kts | 86 ++++++++++ .../junit6}/ArgumentReflectionUtil.java | 8 +- .../jgiven/junit6/DualScenarioTest.java | 29 ++++ .../jgiven/junit6/JGivenExtension.java | 154 ++++++++++++++++++ .../tngtech/jgiven/junit6/ScenarioTest.java | 30 ++++ .../jgiven/junit6/SimpleScenarioTest.java | 26 +++ .../src/main/templates/ScenarioTest.template | 4 +- .../templates/SimpleScenarioTest.template | 4 +- .../jgiven/junit6/test/AllDisabledTest.java | 17 ++ .../jgiven/junit6/test/AssumptionsTest.java | 54 ++++++ .../jgiven/junit6/test/DisabledTest.java | 39 +++++ .../jgiven/junit6/test/DynamicTestTest.java | 27 +++ .../jgiven/junit6/test/GeneralStage.java | 21 +++ .../jgiven/junit6/test/GivenStage.java | 14 ++ .../junit6/test/JUnit6ExtensionTest.java | 33 ++++ .../junit6/test/JUnit6NoScenarioTest.java | 42 +++++ .../junit6/test/JUnit6ScenarioTest.java | 16 ++ .../junit6/test/JUnit6SimpleScenarioTest.java | 15 ++ .../jgiven/junit6/test/NestedTest.java | 96 +++++++++++ .../junit6/test/ParameterizedTestTest.java | 70 ++++++++ .../junit6/test/PendingOnClassTest.java | 28 ++++ .../jgiven/junit6/test/PendingTest.java | 73 +++++++++ .../tngtech/jgiven/junit6/test/TagTest.java | 37 +++++ .../tngtech/jgiven/junit6/test/ThenStage.java | 17 ++ .../tngtech/jgiven/junit6/test/WhenStage.java | 28 ++++ .../JUnit6InheritedParallelizationTest.java | 36 ++++ .../JUnit6InjectedParallelizationTest.java | 48 ++++++ .../junit6/test/concurrency/Stages.java | 54 ++++++ .../CustomJUnit6TagConfiguration.java | 15 ++ .../JUnit6DefaultTagConfigurationTest.java | 21 +++ ...6ExtensionWithJGivenConfigurationTest.java | 25 +++ .../configuration/TagConfigurationStage.java | 55 +++++++ .../test/resources/junit-platform.properties | 6 + jgiven-maven-plugin/build.gradle.kts | 2 +- jgiven-spring-junit5/build.gradle.kts | 10 +- .../spring/junit5/DualSpringScenarioTest.java | 4 + .../junit5/SimpleSpringScenarioTest.java | 4 + .../spring/junit5/SpringScenarioTest.java | 4 + .../src/test/resources/jgiven-spring.xml | 2 +- jgiven-spring-junit6/build.gradle.kts | 37 +++++ .../spring/junit6/DualSpringScenarioTest.java | 34 ++++ .../junit6/SimpleSpringScenarioTest.java | 33 ++++ .../spring/junit6/SpringScenarioTest.java | 35 ++++ .../junit6/config/TestSpringConfig.java | 12 ++ .../junit6/test/AdditionalStageTest.java | 76 +++++++++ .../SimpleSpringRuleScenarioTestTest.java | 18 ++ .../junit6/test/SimpleTestSpringSteps.java | 46 ++++++ ...pringRuleFreshInstanceForEachTestTest.java | 31 ++++ .../test/SpringRuleScenarioTestTest.java | 17 ++ .../SpringScenarioWithParameterizedTest.java | 19 +++ .../spring/junit6/test/TestBean.java | 15 ++ .../junit6/test/proxy/GivenTestStage.java | 24 +++ .../GivenTestStageWithTransactional.java | 26 +++ .../junit6/test/proxy/HelloWorldService.java | 14 ++ .../junit6/test/proxy/MessageToTheWorld.java | 17 ++ .../junit6/test/proxy/ProxyTestConfig.java | 29 ++++ .../junit6/test/proxy/SpringProxyTest.java | 23 +++ .../test/proxy/SpringTransactionalTest.java | 18 ++ .../test/proxy/ThenNewInstanceStage.java | 16 ++ .../junit6/test/proxy/ThenTestStage.java | 18 ++ .../junit6/test/proxy/WhenTestStage.java | 25 +++ .../src/test/resources/jgiven-spring.xml | 13 ++ jgiven-tests/build.gradle.kts | 4 +- .../JGivenReportExtractingExtension.java | 5 +- ...Tests.java => JUnit6AfterMethodTests.java} | 9 +- .../jgiven/tests/TestScenarioRepository.java | 4 +- ...ava => JUnit6AssumptionTestScenarios.java} | 2 +- .../com/tngtech/jgiven/AssumptionsTest.java | 4 +- .../com/tngtech/jgiven/GivenScenarioTest.java | 4 +- .../JUnit6Executor.java} | 4 +- .../JUnit6ExecutorTest.java} | 6 +- .../Junit6TestExecutionResult.java} | 6 +- .../TestExecutionResultProvider.java | 11 +- .../jgiven/testframework/TestExecutor.java | 4 +- settings.gradle | 2 + 88 files changed, 1995 insertions(+), 286 deletions(-) create mode 100644 jgiven-junit6/build.gradle.kts rename {jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5 => jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6}/ArgumentReflectionUtil.java (94%) create mode 100644 jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/DualScenarioTest.java create mode 100644 jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/JGivenExtension.java create mode 100644 jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ScenarioTest.java create mode 100644 jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/SimpleScenarioTest.java rename {jgiven-junit5 => jgiven-junit6}/src/main/templates/ScenarioTest.template (85%) rename {jgiven-junit5 => jgiven-junit6}/src/main/templates/SimpleScenarioTest.template (85%) create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AllDisabledTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AssumptionsTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DisabledTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DynamicTestTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GeneralStage.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GivenStage.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ExtensionTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6NoScenarioTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ScenarioTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6SimpleScenarioTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/NestedTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ParameterizedTestTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingOnClassTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/TagTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ThenStage.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/WhenStage.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InheritedParallelizationTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InjectedParallelizationTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/Stages.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/CustomJUnit6TagConfiguration.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6DefaultTagConfigurationTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6ExtensionWithJGivenConfigurationTest.java create mode 100644 jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/TagConfigurationStage.java create mode 100644 jgiven-junit6/src/test/resources/junit-platform.properties create mode 100644 jgiven-spring-junit6/build.gradle.kts create mode 100644 jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/DualSpringScenarioTest.java create mode 100644 jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SimpleSpringScenarioTest.java create mode 100644 jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SpringScenarioTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/config/TestSpringConfig.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/AdditionalStageTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleSpringRuleScenarioTestTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleTestSpringSteps.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleFreshInstanceForEachTestTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleScenarioTestTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringScenarioWithParameterizedTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/TestBean.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStage.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStageWithTransactional.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/HelloWorldService.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/MessageToTheWorld.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ProxyTestConfig.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringProxyTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringTransactionalTest.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenNewInstanceStage.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenTestStage.java create mode 100644 jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/WhenTestStage.java create mode 100644 jgiven-spring-junit6/src/test/resources/jgiven-spring.xml rename jgiven-tests/src/main/java/com/tngtech/jgiven/tests/{JUnit5AfterMethodTests.java => JUnit6AfterMethodTests.java} (85%) rename jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/{JUnit5AssumptionTestScenarios.java => JUnit6AssumptionTestScenarios.java} (95%) rename jgiven-tests/src/test/java/com/tngtech/jgiven/{junit5/JUnit5Executor.java => junit6/JUnit6Executor.java} (94%) rename jgiven-tests/src/test/java/com/tngtech/jgiven/{junit5/JUnit5ExecutorTest.java => junit6/JUnit6ExecutorTest.java} (95%) rename jgiven-tests/src/test/java/com/tngtech/jgiven/{junit5/Junit5TestExecutionResult.java => junit6/Junit6TestExecutionResult.java} (94%) rename jgiven-tests/src/test/java/com/tngtech/jgiven/{junit5 => junit6}/TestExecutionResultProvider.java (96%) diff --git a/.github/workflows/jgiven_branch_and_pr_build.yml b/.github/workflows/jgiven_branch_and_pr_build.yml index fe907e051ad..21ac51c9350 100644 --- a/.github/workflows/jgiven_branch_and_pr_build.yml +++ b/.github/workflows/jgiven_branch_and_pr_build.yml @@ -2,15 +2,15 @@ name: Java CI with Gradle on: [push, pull_request] jobs: - build: - name: Build JGiven on Java ${{ matrix.java }} with JUnit ${{ matrix.junit }} + junit5: + name: Build JGiven on Java ${{ matrix.java }} with JUnit 5 runs-on: ubuntu-latest env: ANDROID: true strategy: matrix: java: [ '17', '21'] - junit: [ '5.14.3', '6.0.0' ] + junit5: [ '5.11.4', '5.12.2', '5.13.4' ] steps: - name: Ensure chrome is installed run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && sudo apt install ./google-chrome-stable_current_amd64.deb && rm *.deb @@ -22,17 +22,47 @@ jobs: distribution: 'adopt' - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build with Gradle and JUnit ${{ matrix.junit }} - run: "./gradlew -i -s check -PjunitVersion=${{ matrix.junit }}" + - name: Build with Gradle and JUnit 5 ${{ matrix.junit5 }} + run: "./gradlew -i -s check -Pjunit5Version=${{ matrix.junit5 }}" - name: Run Jacoco - if: ${{matrix.java == '17' && github.ref == 'refs/heads/master' && github.head_ref == null}} + if: ${{matrix.java == '17' && matrix.junit5 == '5.13.4' && github.ref == 'refs/heads/master' && github.head_ref == null}} run: ./gradlew overallJacocoReport coveralls - name: Upload test results html files continue-on-error: true if: ${{failure()}} uses: actions/upload-artifact@v7.0.1 with: - name: test-report_${{matrix.java}}_${{matrix.junit}} + name: test-report_junit5-${{matrix.junit5}}_java${{matrix.java}} + path: /home/runner/work/JGiven/JGiven/*/build/reports/tests + if-no-files-found: ignore + junit6: + name: Build JGiven on Java ${{ matrix.java }} with JUnit 6 + runs-on: ubuntu-latest + env: + ANDROID: true + strategy: + matrix: + java: [ '17', '21' ] + junit6: [ '6.0.0', '6.0.3' ] + steps: + - name: Ensure chrome is installed + run: wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && sudo apt install ./google-chrome-stable_current_amd64.deb && rm *.deb + - uses: actions/checkout@v6.0.2 + - name: Set up JDK ${{matrix.java}} + uses: actions/setup-java@v5.2.0 + with: + java-version: ${{matrix.java}} + distribution: 'adopt' + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle and JUnit 6 ${{ matrix.junit6 }} + run: "./gradlew -i -s check -Pjunit6Version=${{ matrix.junit6 }}" + - name: Upload test results html files + continue-on-error: true + if: ${{failure()}} + uses: actions/upload-artifact@v7.0.1 + with: + name: test-report_junit6-${{matrix.junit6}}_java${{matrix.java}} path: /home/runner/work/JGiven/JGiven/*/build/reports/tests if-no-files-found: ignore junit4: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a2a0adb168..cef9716399d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ * Removed deprecated JGiven-Spock module. Please use the JGiven-Spock2 module instead. +## Deprecated modules + +* Deprecated `jgiven-junit5` module in favor of `jgiven-junit6`. The `jgiven-junit6` module provides full JUnit 5 support and is also compatible with JUnit 6, enabling forward compatibility. Existing JUnit 5 tests using `jgiven-junit5` will continue to work, but new projects should use `jgiven-junit6`. + * Use `com.tngtech.jgiven.junit6.ScenarioTest`, `com.tngtech.jgiven.junit6.SimpleScenarioTest`, and `com.tngtech.jgiven.junit6.DualScenarioTest` instead of the junit5 variants. + +* Deprecated `jgiven-spring-junit5` module for Spring 7.x compatibility. A new `jgiven-spring-junit6` module has been introduced that supports Spring 7.x. + * The `jgiven-spring-junit5` module will continue to support Spring 6.x but is deprecated for users wanting to upgrade to Spring 7.x or later. + * Use `com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest`, `com.tngtech.jgiven.integration.spring.junit6.SimpleSpringScenarioTest`, and `com.tngtech.jgiven.integration.spring.junit6.DualSpringScenarioTest` instead of the junit5 variants. + +## New features + +* Added `jgiven-junit6` module with support for both JUnit 5 and JUnit 6. This module provides API compatibility with JUnit 5 and enables migration to JUnit 6 when ready. +* Added `jgiven-spring-junit6` module with support for Spring 7.x while maintaining backward compatibility with JUnit 5. + # Release v2.0.3 ## Fixed issues diff --git a/build.gradle b/build.gradle index 44512f45b62..568c314bbee 100644 --- a/build.gradle +++ b/build.gradle @@ -75,11 +75,6 @@ configure(subprojects.findAll { !it.name.contains("android") }) { testImplementation libs.slf4j.java.util.logging testImplementation libs.assertj testImplementation libs.quickcheck - - if (rootProject.hasProperty('junitVersion')) { - // Use dynamic JUnit version for testing - testImplementation platform("org.junit:junit-bom:${rootProject.junitVersion}") - } } if (timingEnabled) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d885cccd32b..e5010952b2a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,10 +5,13 @@ gson-version = "2.14.0" guava-version = "33.6.0-jre" jakarta-version = "3.0.0" junit4-version = "4.13.2" +junit5-version = "5.13.4" +junit6-version = "6.1.0" mockito-version = "5.23.0" paranamer-version = "2.8.3" slf4j-version = "2.0.18" -spring-version = "7.0.6" +spring6-version = "6.2.18" +spring7-version = "7.0.6" androidx-test-version = "1.7.0" vanniktech-version = "0.36.0" @@ -28,7 +31,8 @@ gson = { module = "com.google.code.gson:gson", version.ref = "gson-version" } guava = { module = "com.google.guava:guava", version.ref = "guava-version" } hypersql-database = { module = "org.hsqldb:hsqldb", version = "2.7.4" } jakarta-annotation = { module = "jakarta.annotation:jakarta.annotation-api", version.ref = "jakarta-version" } -junit-bom = { module = "org.junit:junit-bom", version = "6.1.0" } +junit6-bom = { module = "org.junit:junit-bom", version.ref = "junit6-version" } +junit5-bom = { module = "org.junit:junit-bom", version.ref = "junit5-version" } junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" } junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher" } junit4 = { module = "junit:junit", version.ref = "junit4-version" } @@ -40,17 +44,29 @@ publish = { module = "com.vanniktech.maven.publish:com.vanniktech.maven.publish. quickcheck = { module = "net.java.quickcheck:quickcheck", version = "0.6" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-version" } slf4j-java-util-logging = { module = "org.slf4j:slf4j-jdk14", version.ref = "slf4j-version" } -spring-context = { module = "org.springframework:spring-context", version.ref = "spring-version" } -spring-test = { module = "org.springframework:spring-test", version.ref = "spring-version" } -spring-tx = { module = "org.springframework:spring-tx", version.ref = "spring-version" } -spring-jdbc = { module = "org.springframework:spring-jdbc", version.ref = "spring-version" } +spring6-context = { module = "org.springframework:spring-context", version.ref = "spring6-version" } +spring6-test = { module = "org.springframework:spring-test", version.ref = "spring6-version" } +spring6-tx = { module = "org.springframework:spring-tx", version.ref = "spring6-version" } +spring6-jdbc = { module = "org.springframework:spring-jdbc", version.ref = "spring6-version" } +# NOTE: Unprefixed `spring-*` libraries below resolve to Spring 7. +# Use the `spring6-*` aliases above when a module must stay on Spring 6 (e.g. jgiven-spring, +# jgiven-spring-junit4, jgiven-spring-junit5). +spring-context = { module = "org.springframework:spring-context", version.ref = "spring7-version" } +spring-test = { module = "org.springframework:spring-test", version.ref = "spring7-version" } +spring-tx = { module = "org.springframework:spring-tx", version.ref = "spring7-version" } +spring-jdbc = { module = "org.springframework:spring-jdbc", version.ref = "spring7-version" } testng = { module = "org.testng:testng", version="7.12.0" } [bundles] junit4 = [ "junit4", "junit4-dataprovider", "junit4-params" ] -spring-test = [ "spring-context", "spring-test", "spring-tx", "spring-jdbc" ] -spring-compile = [ "spring-context", "spring-test" ] +# Spring 6 test bundle (used by jgiven-spring, jgiven-spring-junit4, jgiven-spring-junit5). +spring6-test = ["spring6-context", "spring6-test", "spring6-tx", "spring6-jdbc"] +# Spring 7 test bundle (used by jgiven-spring-junit6). +spring-test = ["spring-context", "spring-test", "spring-tx", "spring-jdbc"] +# `spring-compile` is intentionally Spring 6: published modules compile against Spring 6 +# APIs to remain ABI-compatible with Spring 6 consumers; Spring 7 is forward-compatible. +spring-compile = ["spring6-context", "spring6-test"] aspectj-spring-test = [ "aspectj-jrt", "aspectj-jweaver" ] [plugins] diff --git a/jgiven-future-java-tests/build.gradle.kts b/jgiven-future-java-tests/build.gradle.kts index 32aef2f6ebb..4401a03115f 100644 --- a/jgiven-future-java-tests/build.gradle.kts +++ b/jgiven-future-java-tests/build.gradle.kts @@ -12,10 +12,10 @@ java { dependencies { testImplementation(project(":jgiven-core")) - testImplementation(project(":jgiven-junit5")) + testImplementation(project(":jgiven-junit6")) testImplementation(project(":jgiven-html5-report")) - implementation(platform(libs.junit.bom)) + implementation(platform(libs.junit6.bom)) testImplementation("org.junit.jupiter:junit-jupiter-engine") testImplementation("org.junit.jupiter:junit-jupiter-params") diff --git a/jgiven-future-java-tests/src/test/java/com/tngtech/jgiven/tests/sealed/SealedClassesHandlingTest.java b/jgiven-future-java-tests/src/test/java/com/tngtech/jgiven/tests/sealed/SealedClassesHandlingTest.java index 0d263456c8d..531573f02ff 100644 --- a/jgiven-future-java-tests/src/test/java/com/tngtech/jgiven/tests/sealed/SealedClassesHandlingTest.java +++ b/jgiven-future-java-tests/src/test/java/com/tngtech/jgiven/tests/sealed/SealedClassesHandlingTest.java @@ -1,13 +1,14 @@ package com.tngtech.jgiven.tests.sealed; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - import com.tngtech.jgiven.Stage; -import com.tngtech.jgiven.junit5.SimpleScenarioTest; -import java.util.Collections; +import com.tngtech.jgiven.junit6.SimpleScenarioTest; import org.junit.jupiter.api.Test; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + class SealedClassesHandlingTest { @Test diff --git a/jgiven-gradle-plugin/build.gradle.kts b/jgiven-gradle-plugin/build.gradle.kts index 77c79eb0e54..d57656cda0d 100644 --- a/jgiven-gradle-plugin/build.gradle.kts +++ b/jgiven-gradle-plugin/build.gradle.kts @@ -12,7 +12,7 @@ dependencies { implementation(project(":jgiven-core")) implementation(project(":jgiven-asciidoc-report")) implementation(project(":jgiven-html5-report")) - implementation(platform(libs.junit.bom)) + implementation(platform(libs.junit6.bom)) implementation(libs.jakarta.annotation) implementation(libs.guava) implementation(libs.gson) diff --git a/jgiven-junit5/build.gradle.kts b/jgiven-junit5/build.gradle.kts index 1b4d13cf662..cd5f5a13923 100644 --- a/jgiven-junit5/build.gradle.kts +++ b/jgiven-junit5/build.gradle.kts @@ -7,7 +7,7 @@ plugins { id("jgiven-java") } -description = "Module for writing JGiven tests with JUnit 5" +description = "Module for writing JGiven tests with JUnit 5 (Deprecated: Use jgiven-junit6 for JUnit 5 and 6 support)" tasks.withType { options.compilerArgs.add("-parameters") @@ -20,12 +20,12 @@ tasks.named("test") { } dependencies { - api(project(":jgiven-core")) + api(project(":jgiven-junit6")) - if (rootProject.hasProperty("junitVersion")) { - implementation(platform("org.junit:junit-bom:${rootProject.property("junitVersion")}")) + if (rootProject.hasProperty("junit5Version")) { + implementation(platform("org.junit:junit-bom:${rootProject.property("junit5Version")}")) } else { - implementation(platform(libs.junit.bom)) + implementation(platform(libs.junit5.bom)) } compileOnly("org.junit.jupiter:junit-jupiter-params") compileOnly("org.junit.jupiter:junit-jupiter-api") @@ -38,6 +38,10 @@ dependencies { val generatedSourceDir = "generatedSrc/java" +tasks.named("clean") { + delete(generatedSourceDir) +} + sourceSets { main { java { @@ -47,7 +51,11 @@ sourceSets { } file("../jgiven-core/src/main/translations").listFiles()?.forEach { translationFile -> - val pkg = translationFile.name.split(".")[0] + if (!translationFile.isFile()) { + return@forEach + } + + val pkg = translationFile.nameWithoutExtension val props = Properties() translationFile.inputStream().use { stream -> props.load(stream) } @@ -56,10 +64,11 @@ file("../jgiven-core/src/main/translations").listFiles()?.forEach { translationF val taskName = "${pkg}Translation" val copyTask = tasks.register(taskName) { - from("src/main/templates") + from("../jgiven-junit6/src/main/templates") into("$generatedSourceDir/com/tngtech/jgiven/junit5/lang/$pkg") rename("SimpleScenarioTest.template", "${props.getProperty("simple_scenario_test_class")}.java") rename("ScenarioTest.template", "${props.getProperty("scenario_test_class")}.java") + props["module"] = "junit5" @Suppress("UNCHECKED_CAST") // Properties has string keys! expand(props.toMap() as Map) filteringCharset = "UTF-8" diff --git a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/DualScenarioTest.java b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/DualScenarioTest.java index 44523ef93c3..c2b7e02a890 100644 --- a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/DualScenarioTest.java +++ b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/DualScenarioTest.java @@ -1,29 +1,11 @@ package com.tngtech.jgiven.junit5; -import com.tngtech.jgiven.base.DualScenarioTestBase; -import com.tngtech.jgiven.impl.Scenario; -import org.junit.jupiter.api.extension.ExtendWith; - - /** - * Convenience test base class for writing JGiven scenarios with JUnit 5. - * If you only have one stage class you can also use the {@link SimpleScenarioTest} class. - * If you don't want to inherit from any class you can just use the {@link JGivenExtension} - * directly. - * - * @param the combined GIVEN and WHEN stage - * @param the THEN stage - * - * @see JGivenExtension - * @see SimpleScenarioTest + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.junit6.DualScenarioTest} instead. + * The junit6 module supports both JUnit 5 and JUnit 6. */ -@ExtendWith( JGivenExtension.class ) -public class DualScenarioTest extends DualScenarioTestBase { +@Deprecated(since = "3.0.0", forRemoval = false) +public class DualScenarioTest extends com.tngtech.jgiven.junit6.DualScenarioTest { +} - private Scenario scenario = createScenario(); - @Override - public Scenario getScenario() { - return scenario; - } -} diff --git a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/JGivenExtension.java b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/JGivenExtension.java index 6b150387132..b71d49d80aa 100644 --- a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/JGivenExtension.java +++ b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/JGivenExtension.java @@ -1,151 +1,10 @@ package com.tngtech.jgiven.junit5; -import com.tngtech.jgiven.base.ScenarioTestBase; -import com.tngtech.jgiven.config.AbstractJGivenConfiguration; -import com.tngtech.jgiven.config.ConfigurationUtil; -import com.tngtech.jgiven.exception.JGivenWrongUsageException; -import com.tngtech.jgiven.impl.ScenarioBase; -import com.tngtech.jgiven.impl.ScenarioHolder; -import com.tngtech.jgiven.report.impl.CommonReportHelper; -import com.tngtech.jgiven.report.model.ReportModel; -import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.extension.*; -import org.junit.jupiter.api.extension.ExtensionContext.Namespace; - -import java.util.EnumSet; -import java.util.Optional; - -import static com.tngtech.jgiven.impl.util.ThrowableUtil.isAssumptionException; -import static com.tngtech.jgiven.report.model.ExecutionStatus.*; - /** - * This extension enables JGiven for JUnit 5 Tests. - *

- * Just annotate your test class with {@code @ExtendWith( JGivenExtension.class )} - *

- * You can then inject stage classes by using the {@see ScenarioStage} annotation - *

- * As an alternative you can also inherit from one of the following predefined base classes: - *

    - *
  • {@link ScenarioTest}
  • - *
  • {@link SimpleScenarioTest}
  • - *
- * - * @see ScenarioTest - * @see SimpleScenarioTest + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.junit6.JGivenExtension} instead. + * The junit6 module supports both JUnit 5 and JUnit 6. */ -public class JGivenExtension implements - TestInstancePostProcessor, - BeforeAllCallback, - AfterAllCallback, - BeforeEachCallback, - AfterTestExecutionCallback { - - private static final Namespace NAMESPACE = Namespace.create("com.tngtech.jgiven"); - - private static final String REPORT_MODEL = "report-model"; - - @Override - public void beforeAll(ExtensionContext context) { - validatePerMethodLifecycle(context); - - ReportModel reportModel = new ReportModel(); - reportModel.setTestClass(context.getTestClass().orElseThrow()); - if (!context.getDisplayName().equals(context.getTestClass().orElseThrow().getSimpleName())) { - reportModel.setName(context.getDisplayName()); - } - context.getStore(NAMESPACE).put(REPORT_MODEL, reportModel); - - AbstractJGivenConfiguration configuration = ConfigurationUtil.getConfiguration(context.getTestClass().get()); - if (configuration.getTagConfiguration(Tag.class) == null) { - configuration.configureTag(Tag.class) - .description("JUnit 5 Tag") - .color("orange"); - } - } - - @Override - public void afterAll(ExtensionContext context) { - ScenarioHolder.get().removeScenarioOfCurrentThread(); - new CommonReportHelper().finishReport((ReportModel) context.getStore(NAMESPACE).get(REPORT_MODEL)); - } - - @Override - public void beforeEach(ExtensionContext context) { - getScenario().startScenario(context.getTestClass().orElseThrow(), context.getTestMethod().orElseThrow(), - ArgumentReflectionUtil.getNamedArgs(context)); - } - - @Override - public void afterTestExecution(ExtensionContext context) throws Exception { - ScenarioBase scenario = getScenario(); - try { - reportPotentialExecutionException(scenario, context); - scenario.finished(); - - // ignore test when scenario is not implemented - Assumptions.assumeTrue( - EnumSet.of(SUCCESS, FAILED, ABORTED).contains(scenario.getScenarioModel().getExecutionStatus())); - - } catch (Exception e) { - throw e; - } catch (Throwable e) { - throw new RuntimeException(e); - } finally { - ScenarioHolder.get().removeScenarioOfCurrentThread(); - } - } - - private void reportPotentialExecutionException(ScenarioBase scenario, ExtensionContext context) { - Optional exception = context.getExecutionException(); - if (exception.isEmpty()) { - return; - } - if (isAssumptionException(exception.get())) { - scenario.getExecutor().aborted(exception.get()); - } else if (!isAssumptionException(exception.get())) { - scenario.getExecutor().failed(exception.get()); - } - } - - @Override - public void postProcessTestInstance(Object testInstance, ExtensionContext context) { - ScenarioBase currentScenario = ScenarioHolder.get().getScenarioOfCurrentThread(); - - ScenarioBase scenario; - if (testInstance instanceof ScenarioTestBase) { - scenario = ((ScenarioTestBase) testInstance).getScenario(); - } else { - scenario = currentScenario == null ? new ScenarioBase() : currentScenario; - } - - if (scenario != currentScenario) { - ReportModel reportModel = (ReportModel) context.getStore(NAMESPACE).get(REPORT_MODEL); - scenario.setModel(reportModel); - ScenarioHolder.get().setScenarioOfCurrentThread(scenario); - } - - scenario.getExecutor().injectStages(testInstance); - scenario.getExecutor().readScenarioState(testInstance); - } - - private void validatePerMethodLifecycle(ExtensionContext context) { - if (isPerClassLifecycle(context)) { - throw new JGivenWrongUsageException( - "JGiven does not support keeping a test instance over multiple scenarios. Please use Lifecycle '" - + TestInstance.Lifecycle.PER_METHOD + "'."); - } - } - - private boolean isPerClassLifecycle(ExtensionContext context) { - return context.getTestInstanceLifecycle() - .filter(lifecycle -> TestInstance.Lifecycle.PER_CLASS == lifecycle) - .isPresent(); - } - - private ScenarioBase getScenario() { - return ScenarioHolder.get().getScenarioOfCurrentThread(); - } +@Deprecated(since = "3.0.0", forRemoval = false) +public class JGivenExtension extends com.tngtech.jgiven.junit6.JGivenExtension { } + diff --git a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ScenarioTest.java b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ScenarioTest.java index 10e497ea843..107f59f0456 100644 --- a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ScenarioTest.java +++ b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ScenarioTest.java @@ -1,30 +1,11 @@ package com.tngtech.jgiven.junit5; -import com.tngtech.jgiven.base.ScenarioTestBase; -import com.tngtech.jgiven.impl.Scenario; -import org.junit.jupiter.api.extension.ExtendWith; - - /** - * Convenience test base class for writing JGiven scenarios with JUnit 5. - * If you only have one stage class you can also use the {@link SimpleScenarioTest} class. - * If you don't want to inherit from any class you can just use the {@link JGivenExtension} - * directly. - * - * @param the GIVEN stage - * @param the WHEN stage - * @param the THEN stage - * - * @see JGivenExtension - * @see SimpleScenarioTest + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.junit6.ScenarioTest} instead. + * The junit6 module supports both JUnit 5 and JUnit 6. */ -@ExtendWith( JGivenExtension.class ) -public class ScenarioTest extends ScenarioTestBase { +@Deprecated(since = "3.0.0", forRemoval = false) +public class ScenarioTest extends com.tngtech.jgiven.junit6.ScenarioTest { +} - private Scenario scenario = createScenario(); - @Override - public Scenario getScenario() { - return scenario; - } -} diff --git a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/SimpleScenarioTest.java b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/SimpleScenarioTest.java index fa7efbe6de0..5bf596ab7c4 100644 --- a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/SimpleScenarioTest.java +++ b/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/SimpleScenarioTest.java @@ -1,18 +1,11 @@ package com.tngtech.jgiven.junit5; -import com.tngtech.jgiven.base.SimpleScenarioTestBase; -import org.junit.jupiter.api.extension.ExtendWith; - -import com.tngtech.jgiven.impl.Scenario; - - -@ExtendWith( JGivenExtension.class ) -public class SimpleScenarioTest extends SimpleScenarioTestBase { +/** + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.junit6.SimpleScenarioTest} instead. + * The junit6 module supports both JUnit 5 and JUnit 6. + */ +@Deprecated(since = "3.0.0", forRemoval = false) +public class SimpleScenarioTest extends com.tngtech.jgiven.junit6.SimpleScenarioTest { +} - private Scenario scenario = createScenario(); - @Override - public Scenario getScenario() { - return scenario; - } -} diff --git a/jgiven-junit5/src/test/java/com/tngtech/jgiven/junit5/test/configuration/JUnit5DefaultTagConfigurationTest.java b/jgiven-junit5/src/test/java/com/tngtech/jgiven/junit5/test/configuration/JUnit5DefaultTagConfigurationTest.java index 21ad362d101..1554eef3afc 100644 --- a/jgiven-junit5/src/test/java/com/tngtech/jgiven/junit5/test/configuration/JUnit5DefaultTagConfigurationTest.java +++ b/jgiven-junit5/src/test/java/com/tngtech/jgiven/junit5/test/configuration/JUnit5DefaultTagConfigurationTest.java @@ -16,6 +16,6 @@ void JUnit5_tags_are_converted_to_JGiven_tags_using_default_configuration() { when().the_configuration_is_queried(); then().the_tag_configuration_has_the_color("orange") .and().the_tag_configuration_has_the_name("") - .and().the_tag_configuration_has_the_description("JUnit 5 Tag"); + .and().the_tag_configuration_has_the_description("JUnit 5/6 Tag"); } } diff --git a/jgiven-junit6/build.gradle.kts b/jgiven-junit6/build.gradle.kts new file mode 100644 index 00000000000..638ce09ffdf --- /dev/null +++ b/jgiven-junit6/build.gradle.kts @@ -0,0 +1,86 @@ +import java.util.* + +plugins { + id("jgiven-publishing") + id("java-library") + id("jgiven-checkstyle") + id("jgiven-java") +} + +description = "Module for writing JGiven tests with JUnit 5 and JUnit 6" + +tasks.withType { + options.compilerArgs.add("-parameters") + options.encoding = "UTF-8" +} + +tasks.named("test") { + useJUnitPlatform() + finalizedBy("jgivenHtml5Report") +} + +dependencies { + api(project(":jgiven-core")) + + if (rootProject.hasProperty("junit6Version")) { + implementation(platform("org.junit:junit-bom:${rootProject.property("junit6Version")}")) + } else { + implementation(platform(libs.junit6.bom)) + } + compileOnly("org.junit.jupiter:junit-jupiter-params") + compileOnly("org.junit.jupiter:junit-jupiter-api") + + testImplementation(project(":jgiven-html5-report")) + testImplementation("org.junit.jupiter:junit-jupiter-engine") + testImplementation("org.junit.jupiter:junit-jupiter-params") + testRuntimeOnly(libs.junit.platform.launcher) +} + +val generatedSourceDir = "generatedSrc/java" + +tasks.named("clean") { + delete(generatedSourceDir) +} + +sourceSets { + main { + java { + setSrcDirs(listOf("src/main/java", generatedSourceDir)) + } + } +} + +file("../jgiven-core/src/main/translations").listFiles()?.forEach { translationFile -> + if (!translationFile.isFile()) { + return@forEach + } + + val pkg = translationFile.nameWithoutExtension + + val props = Properties() + translationFile.inputStream().use { stream -> props.load(stream) } + props["pkg"] = pkg + + val taskName = "${pkg}Translation" + + val copyTask = tasks.register(taskName) { + from("src/main/templates") + into("$generatedSourceDir/com/tngtech/jgiven/junit6/lang/$pkg") + rename("SimpleScenarioTest.template", "${props.getProperty("simple_scenario_test_class")}.java") + rename("ScenarioTest.template", "${props.getProperty("scenario_test_class")}.java") + props["module"] = "junit6" + @Suppress("UNCHECKED_CAST") // Properties has string keys! + expand(props.toMap() as Map) + filteringCharset = "UTF-8" + } + + tasks.named("compileJava") { + dependsOn(copyTask) + } + + project.afterEvaluate { + tasks.named("sourcesJar") { + dependsOn(copyTask) + } + } +} diff --git a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ArgumentReflectionUtil.java b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ArgumentReflectionUtil.java similarity index 94% rename from jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ArgumentReflectionUtil.java rename to jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ArgumentReflectionUtil.java index 5034781f7f7..dc72679ee9a 100644 --- a/jgiven-junit5/src/main/java/com/tngtech/jgiven/junit5/ArgumentReflectionUtil.java +++ b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ArgumentReflectionUtil.java @@ -1,4 +1,4 @@ -package com.tngtech.jgiven.junit5; +package com.tngtech.jgiven.junit6; import com.tngtech.jgiven.impl.util.ParameterNameUtil; import com.tngtech.jgiven.impl.util.ReflectionUtil; @@ -53,7 +53,11 @@ static List getNamedArgs(ExtensionContext context) { //ExperimentalAPI that only exists since JUnit 5.13 @SuppressWarnings("OptionalGetWithoutIsPresent") //Presence checked in calling method private static List findByPublicApi(ExtensionContext context) { - var args = Arrays.asList(ParameterInfo.get(context).getArguments().toArray()); + var contextParameterInfo = ParameterInfo.get(context); + if (contextParameterInfo == null) { + return List.of(); + } + var args = contextParameterInfo.getArguments().toList(); return ParameterNameUtil.mapArgumentsWithParameterNames(context.getTestMethod().get(), args); } diff --git a/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/DualScenarioTest.java b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/DualScenarioTest.java new file mode 100644 index 00000000000..6545822e89d --- /dev/null +++ b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/DualScenarioTest.java @@ -0,0 +1,29 @@ +package com.tngtech.jgiven.junit6; + +import com.tngtech.jgiven.base.DualScenarioTestBase; +import com.tngtech.jgiven.impl.Scenario; +import org.junit.jupiter.api.extension.ExtendWith; + + +/** + * Convenience test base class for writing JGiven scenarios with JUnit 5 and JUnit 6. + * If you only have one stage class you can also use the {@link SimpleScenarioTest} class. + * If you don't want to inherit from any class you can just use the {@link JGivenExtension} + * directly. + * + * @param the combined GIVEN and WHEN stage + * @param the THEN stage + * + * @see JGivenExtension + * @see SimpleScenarioTest + */ +@ExtendWith( JGivenExtension.class ) +public class DualScenarioTest extends DualScenarioTestBase { + + private Scenario scenario = createScenario(); + + @Override + public Scenario getScenario() { + return scenario; + } +} diff --git a/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/JGivenExtension.java b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/JGivenExtension.java new file mode 100644 index 00000000000..8b14e0e6155 --- /dev/null +++ b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/JGivenExtension.java @@ -0,0 +1,154 @@ +package com.tngtech.jgiven.junit6; + +import com.tngtech.jgiven.base.ScenarioTestBase; +import com.tngtech.jgiven.config.AbstractJGivenConfiguration; +import com.tngtech.jgiven.config.ConfigurationUtil; +import com.tngtech.jgiven.exception.JGivenWrongUsageException; +import com.tngtech.jgiven.impl.ScenarioBase; +import com.tngtech.jgiven.impl.ScenarioHolder; +import com.tngtech.jgiven.report.impl.CommonReportHelper; +import com.tngtech.jgiven.report.model.ReportModel; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.*; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; + +import java.util.EnumSet; +import java.util.Optional; + +import static com.tngtech.jgiven.impl.util.ThrowableUtil.isAssumptionException; +import static com.tngtech.jgiven.report.model.ExecutionStatus.*; + +/** + * This extension enables JGiven for JUnit 5 and JUnit 6 Tests. + *

+ * Just annotate your test class with {@code @ExtendWith( JGivenExtension.class )} + *

+ * You can then inject stage classes by using the {@link com.tngtech.jgiven.annotation.ScenarioStage} annotation + *

+ * As an alternative you can also inherit from one of the following predefined base classes: + *

    + *
  • {@link ScenarioTest}
  • + *
  • {@link SimpleScenarioTest}
  • + *
+ * + * @see ScenarioTest + * @see SimpleScenarioTest + */ +public class JGivenExtension implements + TestInstancePostProcessor, + BeforeAllCallback, + AfterAllCallback, + BeforeEachCallback, + AfterTestExecutionCallback { + + private static final Namespace NAMESPACE = Namespace.create("com.tngtech.jgiven"); + + private static final String REPORT_MODEL = "report-model"; + + @Override + public void beforeAll(ExtensionContext context) { + validatePerMethodLifecycle(context); + + ReportModel reportModel = new ReportModel(); + reportModel.setTestClass(context.getTestClass().orElseThrow()); + if (!context.getDisplayName().equals(context.getTestClass().orElseThrow().getSimpleName())) { + reportModel.setName(context.getDisplayName()); + } + context.getStore(NAMESPACE).put(REPORT_MODEL, reportModel); + + AbstractJGivenConfiguration configuration = ConfigurationUtil.getConfiguration(context.getTestClass().orElseThrow()); + if (configuration.getTagConfiguration(Tag.class) == null) { + configuration.configureTag(Tag.class) + .description("JUnit 5/6 Tag") + .color("orange"); + } + } + + @Override + public void afterAll(ExtensionContext context) { + ScenarioHolder.get().removeScenarioOfCurrentThread(); + new CommonReportHelper().finishReport((ReportModel) context.getStore(NAMESPACE).get(REPORT_MODEL)); + } + + @Override + public void beforeEach(ExtensionContext context) { + getScenario().startScenario(context.getTestClass().orElseThrow(), context.getTestMethod().orElseThrow(), + ArgumentReflectionUtil.getNamedArgs(context)); + } + + @Override + public void afterTestExecution(ExtensionContext context) throws Exception { + ScenarioBase scenario = getScenario(); + if (scenario == null) { + return; + } + try { + reportPotentialExecutionException(scenario, context); + scenario.finished(); + + // ignore test when scenario is not implemented + Assumptions.assumeTrue( + EnumSet.of(SUCCESS, FAILED, ABORTED).contains(scenario.getScenarioModel().getExecutionStatus())); + + } catch (Exception e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(e); + } finally { + ScenarioHolder.get().removeScenarioOfCurrentThread(); + } + } + + private void reportPotentialExecutionException(ScenarioBase scenario, ExtensionContext context) { + Optional exception = context.getExecutionException(); + if (exception.isEmpty()) { + return; + } + if (isAssumptionException(exception.get())) { + scenario.getExecutor().aborted(exception.get()); + } else { + scenario.getExecutor().failed(exception.get()); + } + } + + @Override + public void postProcessTestInstance(Object testInstance, ExtensionContext context) { + ScenarioBase currentScenario = ScenarioHolder.get().getScenarioOfCurrentThread(); + + ScenarioBase scenario; + if (testInstance instanceof ScenarioTestBase) { + scenario = ((ScenarioTestBase) testInstance).getScenario(); + } else { + scenario = currentScenario == null ? new ScenarioBase() : currentScenario; + } + + if (scenario != currentScenario) { + ReportModel reportModel = (ReportModel) context.getStore(NAMESPACE).get(REPORT_MODEL); + scenario.setModel(reportModel); + ScenarioHolder.get().setScenarioOfCurrentThread(scenario); + } + + scenario.getExecutor().injectStages(testInstance); + scenario.getExecutor().readScenarioState(testInstance); + } + + private void validatePerMethodLifecycle(ExtensionContext context) { + if (isPerClassLifecycle(context)) { + throw new JGivenWrongUsageException( + "JGiven does not support keeping a test instance over multiple scenarios. Please use Lifecycle '" + + TestInstance.Lifecycle.PER_METHOD + "'."); + } + } + + private boolean isPerClassLifecycle(ExtensionContext context) { + return context.getTestInstanceLifecycle() + .filter(lifecycle -> TestInstance.Lifecycle.PER_CLASS == lifecycle) + .isPresent(); + } + + private ScenarioBase getScenario() { + return ScenarioHolder.get().getScenarioOfCurrentThread(); + } +} diff --git a/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ScenarioTest.java b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ScenarioTest.java new file mode 100644 index 00000000000..f74fe80880c --- /dev/null +++ b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/ScenarioTest.java @@ -0,0 +1,30 @@ +package com.tngtech.jgiven.junit6; + +import com.tngtech.jgiven.base.ScenarioTestBase; +import com.tngtech.jgiven.impl.Scenario; +import org.junit.jupiter.api.extension.ExtendWith; + + +/** + * Convenience test base class for writing JGiven scenarios with JUnit 5 and JUnit 6. + * If you only have one stage class you can also use the {@link SimpleScenarioTest} class. + * If you don't want to inherit from any class you can just use the {@link JGivenExtension} + * directly. + * + * @param the GIVEN stage + * @param the WHEN stage + * @param the THEN stage + * + * @see JGivenExtension + * @see SimpleScenarioTest + */ +@ExtendWith( JGivenExtension.class ) +public class ScenarioTest extends ScenarioTestBase { + + private Scenario scenario = createScenario(); + + @Override + public Scenario getScenario() { + return scenario; + } +} diff --git a/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/SimpleScenarioTest.java b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/SimpleScenarioTest.java new file mode 100644 index 00000000000..5778f4f21ba --- /dev/null +++ b/jgiven-junit6/src/main/java/com/tngtech/jgiven/junit6/SimpleScenarioTest.java @@ -0,0 +1,26 @@ +package com.tngtech.jgiven.junit6; + +import com.tngtech.jgiven.base.SimpleScenarioTestBase; +import org.junit.jupiter.api.extension.ExtendWith; + +import com.tngtech.jgiven.impl.Scenario; + + +/** + * Convenience test base class for writing JGiven scenarios with JUnit 5 and JUnit 6 using a single stage class. + * + * @param the stage class + * + * @see JGivenExtension + * @see ScenarioTest + */ +@ExtendWith( JGivenExtension.class ) +public class SimpleScenarioTest extends SimpleScenarioTestBase { + + private Scenario scenario = createScenario(); + + @Override + public Scenario getScenario() { + return scenario; + } +} diff --git a/jgiven-junit5/src/main/templates/ScenarioTest.template b/jgiven-junit6/src/main/templates/ScenarioTest.template similarity index 85% rename from jgiven-junit5/src/main/templates/ScenarioTest.template rename to jgiven-junit6/src/main/templates/ScenarioTest.template index 35edc20c822..2aa14387672 100644 --- a/jgiven-junit5/src/main/templates/ScenarioTest.template +++ b/jgiven-junit6/src/main/templates/ScenarioTest.template @@ -1,9 +1,9 @@ -package com.tngtech.jgiven.junit5.lang.${pkg}; +package com.tngtech.jgiven.${module}.lang.${pkg}; import com.tngtech.jgiven.impl.Scenario; import org.junit.jupiter.api.extension.ExtendWith; import com.tngtech.jgiven.lang.${pkg}.${scenario_test_base_class}; -import com.tngtech.jgiven.junit5.JGivenExtension; +import com.tngtech.jgiven.${module}.JGivenExtension; /** * ${scenario_test_javadoc} diff --git a/jgiven-junit5/src/main/templates/SimpleScenarioTest.template b/jgiven-junit6/src/main/templates/SimpleScenarioTest.template similarity index 85% rename from jgiven-junit5/src/main/templates/SimpleScenarioTest.template rename to jgiven-junit6/src/main/templates/SimpleScenarioTest.template index 40325fa672f..825b8a60c8c 100644 --- a/jgiven-junit5/src/main/templates/SimpleScenarioTest.template +++ b/jgiven-junit6/src/main/templates/SimpleScenarioTest.template @@ -1,8 +1,8 @@ -package com.tngtech.jgiven.junit5.lang.${pkg}; +package com.tngtech.jgiven.${module}.lang.${pkg}; import com.tngtech.jgiven.lang.${pkg}.${simple_scenario_test_base_class}; import org.junit.jupiter.api.extension.ExtendWith; -import com.tngtech.jgiven.junit5.JGivenExtension; +import com.tngtech.jgiven.${module}.JGivenExtension; import com.tngtech.jgiven.impl.Scenario; /** diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AllDisabledTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AllDisabledTest.java new file mode 100644 index 00000000000..2574564a127 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AllDisabledTest.java @@ -0,0 +1,17 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.junit6.ScenarioTest; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * A test class with only disabled test methods to reproduce #338 + */ +public class AllDisabledTest extends ScenarioTest { + + @Test + @Disabled + void aTestThatIsDisabled() { + given().some_state(); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AssumptionsTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AssumptionsTest.java new file mode 100644 index 00000000000..e77b7beaf92 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/AssumptionsTest.java @@ -0,0 +1,54 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import com.tngtech.jgiven.report.model.ScenarioCaseModel; +import com.tngtech.jgiven.report.model.StepStatus; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assumptions.assumeThat; + +class AssumptionsTest extends SimpleScenarioTest { + + + @Test + void should_pass_on_assertJ_assumptions() throws Throwable { + when().I_assume_something_using_assertJ(); + getScenario().finished(); + + assertThat(getScenario().getExecutor().hasAborted()).isTrue(); + assertThat(getScenario().getExecutor().getAbortedException()).isInstanceOf(org.junit.AssumptionViolatedException.class); + ScenarioCaseModel aCase = getScenario().getModel().getLastScenarioModel().getCase(0); + assertThat(aCase.getStep(0).getStatus()).isEqualTo(StepStatus.ABORTED); + } + + @Test + void should_pass_on_junit6_assumptions() throws Throwable { + when().I_assume_something_using_junit6(); + getScenario().finished(); + + assertThat(getScenario().getExecutor().hasAborted()).isTrue(); + assertThat(getScenario().getExecutor().getAbortedException()).isInstanceOf(org.opentest4j.TestAbortedException.class); + ScenarioCaseModel aCase = getScenario().getModel().getLastScenarioModel().getCase(0); + assertThat(aCase.getStep(0).getStatus()).isEqualTo(StepStatus.ABORTED); + } + + static class TestStage { + void I_assume_something_using_assertJ() { + assertJAssumptionFailure(); + } + + void I_assume_something_using_junit6() { + junitAssumptionFailure(); + } + } + + private static void assertJAssumptionFailure(){ + assumeThat( true ).isFalse(); + } + + private static void junitAssumptionFailure(){ + Assumptions.abort(); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DisabledTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DisabledTest.java new file mode 100644 index 00000000000..b86867b386e --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DisabledTest.java @@ -0,0 +1,39 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.Stage; +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +public class DisabledTest extends SimpleScenarioTest { + @Test + @Disabled + void test1() { + given().something(); + } + + @Test + void test2() { + // given() returns null when following test1 + given().something(); + } + + @Test + @Disabled + void test3() { + given().something(); + } + + @Test + void test4() { + // given() returns null when following test1 + given().something(); + } + + + public static class ExtensibleReproStage> extends Stage { + public SELF something() { + return self(); + } + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DynamicTestTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DynamicTestTest.java new file mode 100644 index 00000000000..e8ca780f557 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/DynamicTestTest.java @@ -0,0 +1,27 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +@ExtendWith(JGivenExtension.class) +@DisplayName("Dynamic Tests") +public class DynamicTestTest { + + @TestFactory + Collection dynamicTestsFromCollection() { + return Arrays.asList( + dynamicTest("1st dynamic test", () -> assertTrue(true)), + dynamicTest("2nd dynamic test", () -> assertEquals(4, 2 * 2)) + ); + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GeneralStage.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GeneralStage.java new file mode 100644 index 00000000000..dfa62223cfb --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GeneralStage.java @@ -0,0 +1,21 @@ +package com.tngtech.jgiven.junit6.test; + +import org.junit.jupiter.api.Assertions; + +public class GeneralStage { + + private String someState; + + public void some_state() { + someState = "SomeState"; + + } + + public void some_action() { + Assertions.assertNotNull(someState); + } + + public void some_outcome() { + Assertions.assertNotNull(someState); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GivenStage.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GivenStage.java new file mode 100644 index 00000000000..1b8aa637be2 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/GivenStage.java @@ -0,0 +1,14 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.ProvidedScenarioState; + +public class GivenStage { + + @ProvidedScenarioState + String someState; + + public void some_state() { + someState = "Some State"; + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ExtensionTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ExtensionTest.java new file mode 100644 index 00000000000..f6b1cc7c663 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ExtensionTest.java @@ -0,0 +1,33 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.Pending; +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(JGivenExtension.class) +class JUnit6ExtensionTest { + + @ScenarioStage + GivenStage givenStage; + + @ScenarioStage + WhenStage whenStage; + + @ScenarioStage + ThenStage thenStage; + + @Test + public void JGiven_works_with_JUnit6() { + givenStage.some_state(); + whenStage.some_action(); + thenStage.some_outcome(); + } + + @Test + @Pending + public void Pending_works() { + whenStage.some_failing_step(); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6NoScenarioTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6NoScenarioTest.java new file mode 100644 index 00000000000..3ddf634228b --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6NoScenarioTest.java @@ -0,0 +1,42 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.Stage; +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.impl.ScenarioHolder; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(JGivenExtension.class) +class JUnit6NoScenarioTest { + + @ScenarioStage + TestStage testStage; + + @Test + void running_jgiven_without_scenario(){ + testStage.given().a_class_with_only_an_extension(); + testStage.when().i_run_the_test(); + testStage.then().i_get_a_report(); + + } + + + @SuppressWarnings("UnusedReturnValue") + static class TestStage extends Stage{ + TestStage a_class_with_only_an_extension(){ + return self(); + } + TestStage i_run_the_test(){ + return self(); + } + + TestStage i_get_a_report(){ + var myScenario = ScenarioHolder.get().getScenarioOfCurrentThread(); + assertThat(myScenario.getModel().getClassName()).isEqualTo(JUnit6NoScenarioTest.class.getName()); + return self(); + } + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ScenarioTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ScenarioTest.java new file mode 100644 index 00000000000..149d61f579e --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6ScenarioTest.java @@ -0,0 +1,16 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.junit6.ScenarioTest; +import org.junit.jupiter.api.Test; + +public class JUnit6ScenarioTest extends ScenarioTest { + + @Test + public void JGiven_works_with_JUnit6_ScenarioTest() { + given().some_state(); + when().some_action(); + then().some_outcome(); + } + + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6SimpleScenarioTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6SimpleScenarioTest.java new file mode 100644 index 00000000000..da682870250 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/JUnit6SimpleScenarioTest.java @@ -0,0 +1,15 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import org.junit.jupiter.api.Test; + +public class JUnit6SimpleScenarioTest extends SimpleScenarioTest { + + @Test + public void JGiven_works_with_JUnit6() { + given().some_state(); + when().some_action(); + then().some_outcome(); + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/NestedTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/NestedTest.java new file mode 100644 index 00000000000..c026c44e005 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/NestedTest.java @@ -0,0 +1,96 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.BeforeStage; +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.annotation.ScenarioState; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith( { JGivenExtension.class } ) +@DisplayName( "@Nested") +public class NestedTest { + + @ScenarioStage + GeneralStage outerStage; + + @ScenarioState + String outerState = "Outer State"; + + @Nested + @DisplayName("1st level nesting") + class NestedTestClass { + + @ScenarioStage + NestedStage stage; + + @ScenarioState + String nestedState = "Nested State"; + + @BeforeEach + public void background() { + stage.some_background(); + } + + @Test + public void nested_classes() { + assertThat( outerStage ).as( "outerStage" ).isNotNull(); + assertThat( stage ).as( "stage" ).isNotNull(); + + outerStage.some_state(); + stage.some_action(); + stage.some_outcome(); + } + + @Test + public void another_test() { + + } + + @Nested + @DisplayName("2nd level nesting") + class NestedDeeper { + @Test + public void deeply_nested_classes() { + assertThat( outerStage ).as( "outerStage" ).isNotNull(); + assertThat( stage ).as( "stage" ).isNotNull(); + + outerStage.some_state(); + stage.some_action(); + stage.some_outcome(); + } + + } + } + + static class NestedStage { + @ExpectedScenarioState + String outerState; + + @ExpectedScenarioState + String nestedState; + + @BeforeStage + void setup() { + assertThat( outerState ).as( "outerState" ).isNotNull(); + assertThat( nestedState ).as( "nestedState" ).isNotNull(); + } + + public void some_action() { + + } + + public void some_outcome() {} + + public void some_background() { + + } + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ParameterizedTestTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ParameterizedTestTest.java new file mode 100644 index 00000000000..d79f63ea2bb --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ParameterizedTestTest.java @@ -0,0 +1,70 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.CaseAs; +import com.tngtech.jgiven.junit6.JGivenExtension; +import com.tngtech.jgiven.junit6.ScenarioTest; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(JGivenExtension.class) +public class ParameterizedTestTest extends ScenarioTest { + + @ParameterizedTest(name = "{index} [{arguments}] param name") + @ValueSource(strings = {"Hello", "World"}) + @NullSource + @CaseAs("Case $1") + public void parameterized_scenario(String param) { + given().some_state(); + when().some_action_with_a_parameter(param); + then().some_outcome(); + + assertThat(getScenario().getScenarioCaseModel().getDescription()).isIn("Case Hello", "Case World", "Case null"); + } + + @ParameterizedTest + @MethodSource("parametersWithNullInSubsequentTestCases") + void parameterized_scenario_with_null_arguments_in_subsequent_test_cases(String param1, String param2) { + given().some_state(); + when().some_action_with_a_parameter(param1); + when().some_action_with_a_parameter(param2); + then().some_outcome(); + + assertThat(getScenario().getScenarioCaseModel().getExplicitArguments()).containsExactly(String.valueOf(param1), String.valueOf(param2)); + } + + + @ParameterizedTest + @MethodSource("parametersWithNullInFirstTestCase") + void parameterized_scenario_with_null_arguments_in_first_iteration(String param1, String param2) { + given().some_state(); + when().some_action_with_a_parameter(param1); + when().some_action_with_a_parameter(param2); + then().some_outcome(); + + assertThat(getScenario().getScenarioCaseModel().getExplicitArguments()).containsExactly(String.valueOf(param1), String.valueOf(param2)); + } + + static Stream parametersWithNullInSubsequentTestCases() { + return Stream.of( + Arguments.of("Hello", "World"), + Arguments.of(null, "World"), + Arguments.of("Hello", null), + Arguments.of(null, null) + ); + } + + static Stream parametersWithNullInFirstTestCase() { + return Stream.of( + Arguments.of(null, "World"), + Arguments.of("Hello", "World") + ); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingOnClassTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingOnClassTest.java new file mode 100644 index 00000000000..52eb08ba032 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingOnClassTest.java @@ -0,0 +1,28 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.annotation.Pending; +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@Pending +public class PendingOnClassTest extends SimpleScenarioTest { + + @Test + public void required_does_not_fail_for_pending_scenarios() { + when().some_action(); + } + + public static class PendingTestSteps { + @ExpectedScenarioState + String someState; + + public PendingTestSteps some_action() { + assertThat(someState).isNotNull(); + return this; + } + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingTest.java new file mode 100644 index 00000000000..0493cfae3d0 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/PendingTest.java @@ -0,0 +1,73 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.annotation.Pending; +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import com.tngtech.jgiven.report.model.ExecutionStatus; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PendingTest extends SimpleScenarioTest { + + @ScenarioStage + PendingTest.PendingTestStepsWithRequiredField pendingTestStepsWithRequiredField; + + @Test + @Pending + public void required_does_not_fail_for_pending_scenarios() { + pendingTestStepsWithRequiredField.some_action(); + + assertThat( getScenario().getScenarioCaseModel().getExecutionStatus() ).isEqualTo(ExecutionStatus.SCENARIO_PENDING); + } + + @Test + @Pending(executeSteps = true) + public void failing_steps_are_reported_as_pending_if_execute_steps_is_true() { + when().some_failing_action(); + + assertThat( getScenario().getScenarioCaseModel().getExecutionStatus() ).isEqualTo(ExecutionStatus.SCENARIO_PENDING); + } + + @Test + public void failing_steps_are_reported_as_pending_if_execute_steps_is_true_on_step_method() { + when().some_failing_action_with_pending_annotation(); + + assertThat( getScenario().getScenarioCaseModel().getExecutionStatus() ).isEqualTo(ExecutionStatus.SCENARIO_PENDING); + } + + @Test + @Pending(failIfPass = true) + public void failing_tests_with_failIfPass_are_reported_as_pending() { + when().some_failing_action(); + + assertThat( getScenario().getScenarioCaseModel().getExecutionStatus() ).isEqualTo(ExecutionStatus.SCENARIO_PENDING); + } + + public static class PendingTestStepsWithRequiredField { + @ExpectedScenarioState(required = true) + String someState; + + public PendingTestStepsWithRequiredField some_action() { + return this; + } + } + + public static class PendingTestSteps { + @ExpectedScenarioState + String someState; + + public PendingTestSteps some_failing_action() { + assertThat(someState).isNotNull(); + return this; + } + + @Pending(executeSteps = true) + public PendingTestSteps some_failing_action_with_pending_annotation() { + assertThat(someState).isNotNull(); + return this; + } + + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/TagTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/TagTest.java new file mode 100644 index 00000000000..4fd676f7cd4 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/TagTest.java @@ -0,0 +1,37 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.Pending; +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@Tag("class-tag") +@ExtendWith( JGivenExtension.class ) +public class TagTest { + + @ScenarioStage + GivenStage givenStage; + + @ScenarioStage + WhenStage whenStage; + + @ScenarioStage + ThenStage thenStage; + + @Test + @Tag("method-tag") + public void scenario_with_a_JUnit6_tag() { + givenStage.some_state(); + whenStage.some_action(); + thenStage.some_outcome(); + } + + @Test + @Pending + public void Pending_works() { + whenStage.some_failing_step(); + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ThenStage.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ThenStage.java new file mode 100644 index 00000000000..56149713ea1 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/ThenStage.java @@ -0,0 +1,17 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import org.junit.jupiter.api.Assertions; + +public class ThenStage { + @ExpectedScenarioState + String someState; + + @ExpectedScenarioState + String someResult; + + void some_outcome() { + Assertions.assertNotNull(someState); + Assertions.assertNotNull(someResult); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/WhenStage.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/WhenStage.java new file mode 100644 index 00000000000..7b8c2e1b579 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/WhenStage.java @@ -0,0 +1,28 @@ +package com.tngtech.jgiven.junit6.test; + +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.annotation.ProvidedScenarioState; +import org.junit.jupiter.api.Assertions; + +public class WhenStage { + + @ExpectedScenarioState + String someState; + + @ProvidedScenarioState + String someResult; + + void some_action() { + Assertions.assertNotNull(someState); + someResult = "Some Result"; + } + + void some_action_with_a_parameter(String s) { + someResult = String.valueOf(s); + } + + public WhenStage some_failing_step() { + Assertions.assertTrue(false, "Intentionally failing"); + return this; + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InheritedParallelizationTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InheritedParallelizationTest.java new file mode 100644 index 00000000000..1e28c44c157 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InheritedParallelizationTest.java @@ -0,0 +1,36 @@ +package com.tngtech.jgiven.junit6.test.concurrency; + +import com.tngtech.jgiven.junit6.ScenarioTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.IntStream; + +@Execution(ExecutionMode.CONCURRENT) +class JUnit6InheritedParallelizationTest + extends ScenarioTest { + + public static IntStream iterationProvider() { + return IntStream.range(0, 100); + } + + @ParameterizedTest + @MethodSource("iterationProvider") + void firstTest(int i) { + given().a_thread_local_scenario_state(); + when().the_state_on_this_thread_is_set_to("I am the greatest " + i); + then().the_value_on_this_thread_is("I am the greatest " + i); + } + + @Test + void secondTest() { + for (int i = 1; i <= 100; i++) { + given().a_thread_local_scenario_state(); + when().the_state_on_this_thread_is_set_to("I am the best " + i); + then().the_value_on_this_thread_is("I am the best " + i); + } + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InjectedParallelizationTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InjectedParallelizationTest.java new file mode 100644 index 00000000000..b7dbafd75cc --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/JUnit6InjectedParallelizationTest.java @@ -0,0 +1,48 @@ +package com.tngtech.jgiven.junit6.test.concurrency; + +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.IntStream; + +@Execution(ExecutionMode.CONCURRENT) +@ExtendWith(JGivenExtension.class) +class JUnit6InjectedParallelizationTest { + + @ScenarioStage + private Stages.ParallelGivenStage parallelGivenStage; + + @ScenarioStage + private Stages.ParallelWhenStage parallelWhenStage; + + @ScenarioStage + private Stages.ParallelThenStage parallelThenStage; + + + static IntStream iterationProvider() { + return IntStream.range(0, 100); + } + + @ParameterizedTest + @MethodSource("iterationProvider") + void firstTest(int i) { + parallelGivenStage.given().a_thread_local_scenario_state(); + parallelWhenStage.when().the_state_on_this_thread_is_set_to("I am the greatest " + i); + parallelThenStage.then().the_value_on_this_thread_is("I am the greatest " + i); + } + + @Test + void secondTest() { + for (int i = 1; i <= 100; i++) { + parallelGivenStage.given().a_thread_local_scenario_state(); + parallelWhenStage.when().the_state_on_this_thread_is_set_to("I am the best " + i); + parallelThenStage.then().the_value_on_this_thread_is("I am the best " + i); + } + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/Stages.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/Stages.java new file mode 100644 index 00000000000..305b2de75ff --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/concurrency/Stages.java @@ -0,0 +1,54 @@ +package com.tngtech.jgiven.junit6.test.concurrency; + +import com.tngtech.jgiven.Stage; +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.annotation.ProvidedScenarioState; +import org.slf4j.LoggerFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +final class Stages { + private Stages() { + } + + + static class ParallelGivenStage extends Stage { + + @ProvidedScenarioState + private ThreadLocal scenarioState = new ThreadLocal<>(); + + ParallelGivenStage a_thread_local_scenario_state() { + logState(this, scenarioState); + return this; + } + } + + static class ParallelWhenStage extends Stage { + + @ExpectedScenarioState + private ThreadLocal scenarioState; + + ParallelWhenStage the_state_on_this_thread_is_set_to(String value) { + logState(this, scenarioState); + scenarioState.set(value); + return this; + } + } + + static class ParallelThenStage extends Stage { + @ExpectedScenarioState + private ThreadLocal scenarioState; + + ParallelThenStage the_value_on_this_thread_is(String expectation) { + logState(this, scenarioState); + assertThat(scenarioState.get()).isEqualTo(expectation); + return this; + } + } + + private static void logState(Stage stage, ThreadLocal stageState) { + LoggerFactory.getLogger(stage.getClass()).trace("Object {} on thread {} with state {} and thread local value {}", + stage, Thread.currentThread().getId(), stageState, stageState.get()); + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/CustomJUnit6TagConfiguration.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/CustomJUnit6TagConfiguration.java new file mode 100644 index 00000000000..5ff834cbe44 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/CustomJUnit6TagConfiguration.java @@ -0,0 +1,15 @@ +package com.tngtech.jgiven.junit6.test.configuration; + +import com.tngtech.jgiven.config.AbstractJGivenConfiguration; +import org.junit.jupiter.api.Tag; + +public class CustomJUnit6TagConfiguration extends AbstractJGivenConfiguration { + + @Override + public void configure() { + configureTag(Tag.class) + .name("custom name") + .color("blue") + .description("custom description"); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6DefaultTagConfigurationTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6DefaultTagConfigurationTest.java new file mode 100644 index 00000000000..2b8ed0f7519 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6DefaultTagConfigurationTest.java @@ -0,0 +1,21 @@ +package com.tngtech.jgiven.junit6.test.configuration; + +import com.tngtech.jgiven.junit6.JGivenExtension; +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(JGivenExtension.class) +class JUnit6DefaultTagConfigurationTest extends SimpleScenarioTest { + + @Test + @Tag("test-tag") + void JUnit6_tags_are_converted_to_JGiven_tags_using_default_configuration() { + given().no_explicit_configuration(); + when().the_configuration_is_queried(); + then().the_tag_configuration_has_the_color("orange") + .and().the_tag_configuration_has_the_name("") + .and().the_tag_configuration_has_the_description("JUnit 5/6 Tag"); + } +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6ExtensionWithJGivenConfigurationTest.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6ExtensionWithJGivenConfigurationTest.java new file mode 100644 index 00000000000..986ed57fa39 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/JUnit6ExtensionWithJGivenConfigurationTest.java @@ -0,0 +1,25 @@ +package com.tngtech.jgiven.junit6.test.configuration; + +import com.tngtech.jgiven.annotation.JGivenConfiguration; +import com.tngtech.jgiven.junit6.JGivenExtension; +import com.tngtech.jgiven.junit6.SimpleScenarioTest; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(JGivenExtension.class) +@JGivenConfiguration(CustomJUnit6TagConfiguration.class) +public class JUnit6ExtensionWithJGivenConfigurationTest + extends SimpleScenarioTest { + + @Test + @Tag("test-tag") + public void JUnit6_tags_are_converted_to_JGiven_tags_using_custom_configuration() { + given().the_configuration_defined_on(getClass()); + when().the_configuration_is_queried(); + then().the_tag_configuration_has_the_name("custom name") + .and().the_tag_configuration_has_the_description("custom description") + .and().the_tag_configuration_has_the_color("blue"); + } + +} diff --git a/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/TagConfigurationStage.java b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/TagConfigurationStage.java new file mode 100644 index 00000000000..f997b7c13b3 --- /dev/null +++ b/jgiven-junit6/src/test/java/com/tngtech/jgiven/junit6/test/configuration/TagConfigurationStage.java @@ -0,0 +1,55 @@ +package com.tngtech.jgiven.junit6.test.configuration; + +import com.tngtech.jgiven.Stage; +import com.tngtech.jgiven.config.ConfigurationUtil; +import com.tngtech.jgiven.config.TagConfiguration; +import org.junit.jupiter.api.Tag; + +import static org.assertj.core.api.Assertions.assertThat; + +class TagConfigurationStage extends Stage { + + private Class configurationTarget; + private TagConfiguration configuration; + + TagConfigurationStage no_explicit_configuration() { + return this; + } + + TagConfigurationStage the_configuration_defined_on(Class target) { + configurationTarget = target; + return this; + } + + TagConfigurationStage the_configuration_is_queried() { + configuration = ConfigurationUtil + .getConfiguration(configurationTarget) + .getTagConfiguration(Tag.class); + return this; + } + + TagConfigurationStage the_tag_configuration_has_the_color(String color) { + configurationIsNotNull(); + assertThat(configuration.getColor()).isEqualTo(color); + return this; + } + + TagConfigurationStage the_tag_configuration_has_the_description(String description) { + configurationIsNotNull(); + assertThat(configuration.getDescription()).isEqualTo(description); + return this; + } + + TagConfigurationStage the_tag_configuration_has_the_name(String name) { + configurationIsNotNull(); + assertThat(configuration.getName()).isEqualTo(name); + return this; + } + + private void configurationIsNotNull() { + if (configuration == null) { + throw new IllegalStateException("Tag configuration was never set"); + } + } + +} diff --git a/jgiven-junit6/src/test/resources/junit-platform.properties b/jgiven-junit6/src/test/resources/junit-platform.properties new file mode 100644 index 00000000000..50d22635ae6 --- /dev/null +++ b/jgiven-junit6/src/test/resources/junit-platform.properties @@ -0,0 +1,6 @@ +# Necessary to have the parallel tests actually run in parallel. +# Default settings will ensure that only the class annotated with a concurrent execution mode will +# be run in parallel. +junit.jupiter.execution.parallel.enabled = true +junit.jupiter.execution.parallel.mode.default = SAME_THREAD +junit.jupiter.execution.parallel.mode.classes.default = SAME_THREAD diff --git a/jgiven-maven-plugin/build.gradle.kts b/jgiven-maven-plugin/build.gradle.kts index 988bd1fabf1..6ba836d66e5 100644 --- a/jgiven-maven-plugin/build.gradle.kts +++ b/jgiven-maven-plugin/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { testImplementation(project(":jgiven-html5-report")) - testImplementation(platform(libs.junit.bom)) + testImplementation(platform(libs.junit6.bom)) testImplementation("org.junit.jupiter:junit-jupiter-api") testImplementation("org.junit.jupiter:junit-jupiter-engine") testImplementation("org.junit.jupiter:junit-jupiter-params") diff --git a/jgiven-spring-junit5/build.gradle.kts b/jgiven-spring-junit5/build.gradle.kts index 766b52d28fd..3e454e211d8 100644 --- a/jgiven-spring-junit5/build.gradle.kts +++ b/jgiven-spring-junit5/build.gradle.kts @@ -5,16 +5,16 @@ plugins { id("jgiven-java") } -description = "Module for using Spring dependency injection together with JGiven and JUnit 5" +description = "Module for using Spring dependency injection together with JGiven and JUnit 5 (Deprecated: Use jgiven-spring-junit6 for Spring 7 support)" dependencies { api(project(":jgiven-spring")) api(project(":jgiven-junit5")) - if (rootProject.hasProperty("junitVersion")) { - implementation(platform("org.junit:junit-bom:${rootProject.property("junitVersion")}")) + if (rootProject.hasProperty("junit5Version")) { + implementation(platform("org.junit:junit-bom:${rootProject.property("junit5Version")}")) } else { - implementation(platform(libs.junit.bom)) + implementation(platform(libs.junit5.bom)) } compileOnly(libs.bundles.spring.compile) @@ -24,7 +24,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-engine") testImplementation("org.junit.jupiter:junit-jupiter-params") testRuntimeOnly(libs.junit.platform.launcher) - testImplementation(libs.bundles.spring.test) + testImplementation(libs.bundles.spring6.test) testImplementation(libs.hypersql.database) testImplementation(libs.bundles.aspectj.spring.test) } diff --git a/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/DualSpringScenarioTest.java b/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/DualSpringScenarioTest.java index 2a2c71e4cda..2cbf8abf8a6 100644 --- a/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/DualSpringScenarioTest.java +++ b/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/DualSpringScenarioTest.java @@ -17,7 +17,11 @@ * @param the THEN stage class * * @since 1.0.0 + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.integration.spring.junit6.DualSpringScenarioTest DualSpringScenarioTest} + * from {@code jgiven-spring-junit6} for Spring 7.x compatibility. + * This module will continue to support Spring 6.x but is deprecated for future Spring versions. */ +@Deprecated(since = "3.0.0", forRemoval = false) @ExtendWith( {SpringExtension.class, JGivenExtension.class} ) public class DualSpringScenarioTest extends DualScenarioTestBase implements BeanFactoryAware { diff --git a/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SimpleSpringScenarioTest.java b/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SimpleSpringScenarioTest.java index 373a60f76ea..6f6ce7e0598 100644 --- a/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SimpleSpringScenarioTest.java +++ b/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SimpleSpringScenarioTest.java @@ -16,7 +16,11 @@ * @param the stage class * * @since 1.0.0 + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.integration.spring.junit6.SimpleSpringScenarioTest SimpleSpringScenarioTest} + * from {@code jgiven-spring-junit6} for Spring 7.x compatibility. + * This module will continue to support Spring 6.x but is deprecated for future Spring versions. */ +@Deprecated(since = "3.0.0", forRemoval = false) @ExtendWith( {SpringExtension.class, JGivenExtension.class} ) public class SimpleSpringScenarioTest extends SimpleScenarioTestBase implements BeanFactoryAware { diff --git a/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SpringScenarioTest.java b/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SpringScenarioTest.java index 1d57d096583..b5a1020f49c 100644 --- a/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SpringScenarioTest.java +++ b/jgiven-spring-junit5/src/main/java/com/tngtech/jgiven/integration/spring/junit5/SpringScenarioTest.java @@ -18,7 +18,11 @@ * @param the THEN stage class * * @since 1.0.0 + * @deprecated As of JGiven 3.0.0, use {@link com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest SpringScenarioTest} + * from {@code jgiven-spring-junit6} for Spring 7.x compatibility. + * This module will continue to support Spring 6.x but is deprecated for future Spring versions. */ +@Deprecated(since = "3.0.0", forRemoval = false) @ExtendWith( {SpringExtension.class, JGivenExtension.class} ) public class SpringScenarioTest extends ScenarioTestBase implements BeanFactoryAware { diff --git a/jgiven-spring-junit5/src/test/resources/jgiven-spring.xml b/jgiven-spring-junit5/src/test/resources/jgiven-spring.xml index 034bf687845..225b5806750 100644 --- a/jgiven-spring-junit5/src/test/resources/jgiven-spring.xml +++ b/jgiven-spring-junit5/src/test/resources/jgiven-spring.xml @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/jgiven-spring-junit6/build.gradle.kts b/jgiven-spring-junit6/build.gradle.kts new file mode 100644 index 00000000000..c69cc2adbbe --- /dev/null +++ b/jgiven-spring-junit6/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + id("java-library") + id("jgiven-publishing") + id("jgiven-checkstyle") + id("jgiven-java") +} + +description = "Module for using Spring dependency injection together with JGiven and JUnit 6/5" + +dependencies { + api(project(":jgiven-spring")) + api(project(":jgiven-junit6")) + + + if (rootProject.hasProperty("junit6Version")) { + implementation(platform("org.junit:junit-bom:${rootProject.property("junit6Version")}")) + } else { + implementation(platform(libs.junit6.bom)) + } + + compileOnly(libs.spring.context) + compileOnly(libs.spring.test) + compileOnly("org.junit.jupiter:junit-jupiter-api") + + testImplementation(project(":jgiven-html5-report")) + testImplementation("org.junit.jupiter:junit-jupiter-engine") + testImplementation("org.junit.jupiter:junit-jupiter-params") + testRuntimeOnly(libs.junit.platform.launcher) + testImplementation(libs.bundles.spring.test) + testImplementation(libs.hypersql.database) + testImplementation(libs.bundles.aspectj.spring.test) +} + +tasks.named("test") { + useJUnitPlatform() + finalizedBy("jgivenHtml5Report") +} diff --git a/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/DualSpringScenarioTest.java b/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/DualSpringScenarioTest.java new file mode 100644 index 00000000000..ef3a5d23d7f --- /dev/null +++ b/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/DualSpringScenarioTest.java @@ -0,0 +1,34 @@ +package com.tngtech.jgiven.integration.spring.junit6; + +import com.tngtech.jgiven.base.DualScenarioTestBase; +import com.tngtech.jgiven.impl.Scenario; +import com.tngtech.jgiven.integration.spring.SpringStageCreator; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Base class for Spring and JUnit 6 test with two stage class parameters + * + * @param the GIVEN and WHEN stage class + * @param the THEN stage class + * @since 1.0.0 + */ +@ExtendWith({SpringExtension.class, JGivenExtension.class}) +public class DualSpringScenarioTest extends + DualScenarioTestBase implements BeanFactoryAware { + + private Scenario scenario = createScenario(); + + @Override + public Scenario getScenario() { + return scenario; + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) { + getScenario().setStageCreator(beanFactory.getBean(SpringStageCreator.class)); + } +} diff --git a/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SimpleSpringScenarioTest.java b/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SimpleSpringScenarioTest.java new file mode 100644 index 00000000000..31ad8de6a72 --- /dev/null +++ b/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SimpleSpringScenarioTest.java @@ -0,0 +1,33 @@ +package com.tngtech.jgiven.integration.spring.junit6; + +import com.tngtech.jgiven.base.SimpleScenarioTestBase; +import com.tngtech.jgiven.impl.Scenario; +import com.tngtech.jgiven.integration.spring.SpringStageCreator; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Base class for Spring and JUnit 6 test with only one stage class parameter + * + * @param the stage class + * @since 1.0.0 + */ +@ExtendWith({SpringExtension.class, JGivenExtension.class}) +public class SimpleSpringScenarioTest extends + SimpleScenarioTestBase implements BeanFactoryAware { + + private Scenario scenario = createScenario(); + + @Override + public Scenario getScenario() { + return scenario; + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) { + getScenario().setStageCreator(beanFactory.getBean(SpringStageCreator.class)); + } +} diff --git a/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SpringScenarioTest.java b/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SpringScenarioTest.java new file mode 100644 index 00000000000..46dae641cc7 --- /dev/null +++ b/jgiven-spring-junit6/src/main/java/com/tngtech/jgiven/integration/spring/junit6/SpringScenarioTest.java @@ -0,0 +1,35 @@ +package com.tngtech.jgiven.integration.spring.junit6; + +import com.tngtech.jgiven.base.ScenarioTestBase; +import com.tngtech.jgiven.impl.Scenario; +import com.tngtech.jgiven.integration.spring.SpringStageCreator; +import com.tngtech.jgiven.junit6.JGivenExtension; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Base class for Spring and JUnit 6 test with three stage classes + * + * @param the GIVEN stage class + * @param the WHEN stage class + * @param the THEN stage class + * @since 1.0.0 + */ +@ExtendWith({SpringExtension.class, JGivenExtension.class}) +public class SpringScenarioTest extends + ScenarioTestBase implements BeanFactoryAware { + + private Scenario scenario = createScenario(); + + @Override + public Scenario getScenario() { + return scenario; + } + + @Override + public void setBeanFactory(BeanFactory beanFactory) { + getScenario().setStageCreator(beanFactory.getBean(SpringStageCreator.class)); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/config/TestSpringConfig.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/config/TestSpringConfig.java new file mode 100644 index 00000000000..b01a8d37aaa --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/config/TestSpringConfig.java @@ -0,0 +1,12 @@ +package com.tngtech.jgiven.integration.spring.junit6.config; + +import com.tngtech.jgiven.integration.spring.EnableJGiven; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableJGiven +@ComponentScan(basePackages = "com.tngtech.jgiven.integration.spring.junit6.test") +public class TestSpringConfig { + +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/AdditionalStageTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/AdditionalStageTest.java new file mode 100644 index 00000000000..214d5fb29b5 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/AdditionalStageTest.java @@ -0,0 +1,76 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import com.tngtech.jgiven.Stage; +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.integration.spring.JGivenStage; +import com.tngtech.jgiven.integration.spring.junit6.DualSpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.SimpleSpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.config.TestSpringConfig; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = TestSpringConfig.class) +public class AdditionalStageTest extends SimpleSpringScenarioTest { + + @JGivenStage + static class AdditionalStage extends Stage { + private final TestBean testBean; + + AdditionalStage(TestBean testBean) { + this.testBean = testBean; + } + + public AdditionalStage an_additional_stage_is_injected() { + return this; + } + + public AdditionalStage spring_beans_of_this_stage_are_injected() { + Assertions.assertThat(testBean).isNotNull(); + return this; + } + } + + @Nested + @ContextConfiguration(classes = TestSpringConfig.class) + class SimpleTest extends SimpleSpringScenarioTest { + @ScenarioStage + AdditionalStage additionalStage; + + @Test + public void beans_are_injected_in_additional_stages() { + additionalStage.when().an_additional_stage_is_injected(); + additionalStage.then().spring_beans_of_this_stage_are_injected(); + } + } + + @Nested + @ContextConfiguration(classes = TestSpringConfig.class) + class DualTest extends DualSpringScenarioTest { + @ScenarioStage + AdditionalStage additionalStage; + + @Test + public void beans_are_injected_in_additional_stages() { + additionalStage.when().an_additional_stage_is_injected(); + additionalStage.then().spring_beans_of_this_stage_are_injected(); + } + + } + + @Nested + @ContextConfiguration(classes = TestSpringConfig.class) + class GivenWhenThenStagesTest extends SpringScenarioTest { + @ScenarioStage + AdditionalStage additionalStage; + + @Test + public void beans_are_injected_in_additional_stages() { + additionalStage.when().an_additional_stage_is_injected(); + additionalStage.then().spring_beans_of_this_stage_are_injected(); + } + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleSpringRuleScenarioTestTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleSpringRuleScenarioTestTest.java new file mode 100644 index 00000000000..d63a501a3c8 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleSpringRuleScenarioTestTest.java @@ -0,0 +1,18 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import com.tngtech.jgiven.integration.spring.junit6.SimpleSpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.config.TestSpringConfig; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ContextConfiguration; + + +@ContextConfiguration(classes = TestSpringConfig.class) +public class SimpleSpringRuleScenarioTestTest extends SimpleSpringScenarioTest { + + @Test + public void spring_can_inject_beans_into_stages() { + given().a_step_that_is_a_spring_component(); + when().methods_on_this_component_are_called(); + then().beans_are_injected(); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleTestSpringSteps.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleTestSpringSteps.java new file mode 100644 index 00000000000..2babf28cc9e --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SimpleTestSpringSteps.java @@ -0,0 +1,46 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import com.tngtech.jgiven.annotation.NestedSteps; +import com.tngtech.jgiven.integration.spring.JGivenStage; +import org.assertj.core.api.Assertions; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * example for a Spring Bean that is used as a step + *

+ * note this bean neither inherits from {@link com.tngtech.jgiven.Stage} + * nor is annotated with the {@link JGivenStage} annotation, i.e. it is + * possible (but not recommended) to use unmodified already existing + * spring beans as stages. + *
+ * + */ +@JGivenStage +class SimpleTestSpringSteps { + + @Autowired + TestBean testBean; + + public SimpleTestSpringSteps a_step_that_is_a_spring_component() { + return this; + } + + public SimpleTestSpringSteps methods_on_this_component_are_called() { + return this; + } + + public SimpleTestSpringSteps method_with_parameter_is_called(String message) { + testBean.sayHello(message); + return this; + } + + public void beans_are_injected() { + Assertions.assertThat(testBean).isNotNull(); + } + + @NestedSteps + public void a_nested_step() { + this.beans_are_injected(); + this.methods_on_this_component_are_called(); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleFreshInstanceForEachTestTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleFreshInstanceForEachTestTest.java new file mode 100644 index 00000000000..327cbde44b7 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleFreshInstanceForEachTestTest.java @@ -0,0 +1,31 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.config.TestSpringConfig; +import com.tngtech.jgiven.integration.spring.junit6.test.proxy.ThenNewInstanceStage; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = TestSpringConfig.class) +public class SpringRuleFreshInstanceForEachTestTest + extends SpringScenarioTest { + + private static Object previousInstance; + + @Test + public void spring_should_have_new_stage_instance_for_each_test_case_A() { + checkStepInstance(); + } + + @Test + public void spring_should_have_new_stage_instance_for_each_test_case_B() { + checkStepInstance(); + } + + private void checkStepInstance() { + given().a_step_that_is_a_spring_component(); + then().the_step_instance_is_not_the_same_as_on_previous_run(previousInstance); + previousInstance = then(); + } + +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleScenarioTestTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleScenarioTestTest.java new file mode 100644 index 00000000000..78d46f318fb --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringRuleScenarioTestTest.java @@ -0,0 +1,17 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.config.TestSpringConfig; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = TestSpringConfig.class) +public class SpringRuleScenarioTestTest extends SpringScenarioTest { + + @Test + public void spring_can_inject_beans_into_stages() { + given().a_step_that_is_a_spring_component(); + when().methods_on_this_component_are_called(); + then().beans_are_injected(); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringScenarioWithParameterizedTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringScenarioWithParameterizedTest.java new file mode 100644 index 00000000000..4205b5aa5f0 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/SpringScenarioWithParameterizedTest.java @@ -0,0 +1,19 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest; +import com.tngtech.jgiven.integration.spring.junit6.config.TestSpringConfig; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = TestSpringConfig.class) +public class SpringScenarioWithParameterizedTest extends SpringScenarioTest { + + @ParameterizedTest(name = "{index} [{arguments}] param name") + @ValueSource(strings = {"Hello", "World"}) + public void spring_can_inject_beans_into_stages(String param) { + given().a_step_that_is_a_spring_component(); + when().method_with_parameter_is_called(param); + then().beans_are_injected(); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/TestBean.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/TestBean.java new file mode 100644 index 00000000000..e0ee7adbb3a --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/TestBean.java @@ -0,0 +1,15 @@ +package com.tngtech.jgiven.integration.spring.junit6.test; + +import org.springframework.stereotype.Component; + +@Component +public class TestBean { + + public String computeSomething() { + return "result"; + } + + public String sayHello(String message) { + return "Hello " + message; + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStage.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStage.java new file mode 100644 index 00000000000..8a2f6e06308 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStage.java @@ -0,0 +1,24 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.annotation.ProvidedScenarioState; +import com.tngtech.jgiven.integration.spring.JGivenStage; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +@JGivenStage +public class GivenTestStage { + + @Autowired + private HelloWorldService helloWorldService; + + @ProvidedScenarioState + private MessageToTheWorld message; + + public GivenTestStage should_say_hello() { + assertThat(helloWorldService).isNotNull(); + + message = helloWorldService.sayHello(); + return this; + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStageWithTransactional.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStageWithTransactional.java new file mode 100644 index 00000000000..1794c0985f0 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/GivenTestStageWithTransactional.java @@ -0,0 +1,26 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.annotation.ProvidedScenarioState; +import com.tngtech.jgiven.integration.spring.JGivenStage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +@JGivenStage +@Transactional +public class GivenTestStageWithTransactional { + + @Autowired + private HelloWorldService helloWorldService; + + @ProvidedScenarioState + private MessageToTheWorld message; + + public void should_say_hello() { + assertThat(helloWorldService).isNotNull(); + + message = helloWorldService.sayHello(); + } + +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/HelloWorldService.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/HelloWorldService.java new file mode 100644 index 00000000000..7136695da54 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/HelloWorldService.java @@ -0,0 +1,14 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import org.springframework.stereotype.Service; + +@Service +public class HelloWorldService { + public MessageToTheWorld sayHello() { + return new MessageToTheWorld("Hello"); + } + + public MessageToTheWorld appendWorld(MessageToTheWorld messageToTheWorld) { + return new MessageToTheWorld(messageToTheWorld.getMessage() + " World!"); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/MessageToTheWorld.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/MessageToTheWorld.java new file mode 100644 index 00000000000..9e644b29c7c --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/MessageToTheWorld.java @@ -0,0 +1,17 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +public class MessageToTheWorld { + private String message; + + public MessageToTheWorld(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ProxyTestConfig.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ProxyTestConfig.java new file mode 100644 index 00000000000..b8d3fad0570 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ProxyTestConfig.java @@ -0,0 +1,29 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.integration.spring.EnableJGiven; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; + +@EnableJGiven +@ComponentScan(basePackages = "com.tngtech.jgiven.integration.spring.junit6.test.proxy") +@EnableTransactionManagement +@EnableAspectJAutoProxy(proxyTargetClass = true) +public class ProxyTestConfig { + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder().build(); + } + + @Bean + public PlatformTransactionManager transactionManager(DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringProxyTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringProxyTest.java new file mode 100644 index 00000000000..31255759d70 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringProxyTest.java @@ -0,0 +1,23 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = ProxyTestConfig.class) +public class SpringProxyTest extends SpringScenarioTest { + + @Autowired + private ApplicationContext applicationContext; + + @Test + public void with_spring_proxies_autowired_should_also_work() throws Exception { + given().should_say_hello(); + + when().appendWorld_is_called(); + + then().the_message_should_equal_$("Hello World!"); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringTransactionalTest.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringTransactionalTest.java new file mode 100644 index 00000000000..3d3dda7b3c4 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/SpringTransactionalTest.java @@ -0,0 +1,18 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.integration.spring.junit6.SpringScenarioTest; +import org.junit.jupiter.api.Test; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = ProxyTestConfig.class) +public class SpringTransactionalTest extends SpringScenarioTest { + + @Test + public void with_transactional_autowired_should_also_work() throws Exception { + given().should_say_hello(); + + when().appendWorld_is_called(); + + then().the_message_should_equal_$("Hello World!"); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenNewInstanceStage.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenNewInstanceStage.java new file mode 100644 index 00000000000..e7caf338d77 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenNewInstanceStage.java @@ -0,0 +1,16 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.annotation.Hidden; +import com.tngtech.jgiven.integration.spring.JGivenStage; + +import static org.assertj.core.api.Assertions.assertThat; + +@JGivenStage +public class ThenNewInstanceStage { + + public void the_step_instance_is_not_the_same_as_on_previous_run(@Hidden Object previousInstance) { + if (previousInstance != null) { + assertThat(this).isNotSameAs(previousInstance); + } + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenTestStage.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenTestStage.java new file mode 100644 index 00000000000..3aa701c380b --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/ThenTestStage.java @@ -0,0 +1,18 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + + +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.integration.spring.JGivenStage; + +import static org.assertj.core.api.Assertions.assertThat; + +@JGivenStage +public class ThenTestStage { + + @ExpectedScenarioState + private MessageToTheWorld message; + + public void the_message_should_equal_$(String expectedMessage) { + assertThat(message.getMessage()).isEqualTo(expectedMessage); + } +} diff --git a/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/WhenTestStage.java b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/WhenTestStage.java new file mode 100644 index 00000000000..4ae6cefeb90 --- /dev/null +++ b/jgiven-spring-junit6/src/test/java/com/tngtech/jgiven/integration/spring/junit6/test/proxy/WhenTestStage.java @@ -0,0 +1,25 @@ +package com.tngtech.jgiven.integration.spring.junit6.test.proxy; + +import com.tngtech.jgiven.annotation.ExpectedScenarioState; +import com.tngtech.jgiven.integration.spring.JGivenStage; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.assertj.core.api.Assertions.assertThat; + +@JGivenStage +public class WhenTestStage { + + @Autowired + private HelloWorldService helloWorldService; + + @ExpectedScenarioState + private MessageToTheWorld message; + + public void appendWorld_is_called() { + assertThat(helloWorldService).isNotNull(); + assertThat(message).isNotNull(); + + message = helloWorldService.appendWorld(message); + } + +} diff --git a/jgiven-spring-junit6/src/test/resources/jgiven-spring.xml b/jgiven-spring-junit6/src/test/resources/jgiven-spring.xml new file mode 100644 index 00000000000..fbea72f651b --- /dev/null +++ b/jgiven-spring-junit6/src/test/resources/jgiven-spring.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/jgiven-tests/build.gradle.kts b/jgiven-tests/build.gradle.kts index 9304cb03df5..0c13ec1f8e3 100644 --- a/jgiven-tests/build.gradle.kts +++ b/jgiven-tests/build.gradle.kts @@ -9,11 +9,11 @@ description = "JGiven Tests - Contains BDD tests for JGiven written in JGiven" dependencies { implementation(project(":jgiven-junit")) implementation(project(":jgiven-testng")) - implementation(project(":jgiven-junit5")) + implementation(project(":jgiven-junit6")) implementation(project(":jgiven-asciidoc-report")) implementation(project(":jgiven-html5-report")) implementation(libs.bundles.junit4) - implementation(platform(libs.junit.bom)) + implementation(platform(libs.junit6.bom)) implementation("org.junit.jupiter:junit-jupiter-api") implementation("org.junit.jupiter:junit-jupiter-engine") implementation(libs.slf4j.java.util.logging) diff --git a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JGivenReportExtractingExtension.java b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JGivenReportExtractingExtension.java index 58d5b4fa7ef..3efb14c191c 100644 --- a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JGivenReportExtractingExtension.java +++ b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JGivenReportExtractingExtension.java @@ -3,12 +3,13 @@ import com.tngtech.jgiven.exception.JGivenWrongUsageException; import com.tngtech.jgiven.impl.ScenarioBase; import com.tngtech.jgiven.impl.ScenarioHolder; -import com.tngtech.jgiven.junit5.JGivenExtension; +import com.tngtech.jgiven.junit6.JGivenExtension; import com.tngtech.jgiven.report.model.ReportModel; +import org.junit.jupiter.api.extension.ExtensionContext; + import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import org.junit.jupiter.api.extension.ExtensionContext; /** * Extracts the report Model from within the Test context before it gets deleted. diff --git a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JUnit5AfterMethodTests.java b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JUnit6AfterMethodTests.java similarity index 85% rename from jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JUnit5AfterMethodTests.java rename to jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JUnit6AfterMethodTests.java index 6de7bbd3ebd..2cb2dda9a9b 100644 --- a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JUnit5AfterMethodTests.java +++ b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/JUnit6AfterMethodTests.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(JGivenReportExtractingExtension.class) -public class JUnit5AfterMethodTests extends ScenarioTestBase { +public class JUnit6AfterMethodTests extends ScenarioTestBase { private final Scenario scenario = createScenario(); @@ -19,14 +19,14 @@ public Scenario getScenario() { } @Test - public void a_failing_JUnit_5_test() { + public void a_failing_JUnit_6_test() { given().nothing(); when().a_step_fails(); then().something_happened(); } @Test - public void a_succeeding_JUnit5_test() { + public void a_succeeding_JUnit6_test() { given().nothing(); when().something_happens(); then().something_happened(); @@ -34,7 +34,7 @@ public void a_succeeding_JUnit5_test() { @Test @Disabled - public void a_skipped_JUnit5_test() { + public void a_skipped_JUnit6_test() { given().nothing(); when().something_happens(); then().something_happened(); @@ -46,3 +46,4 @@ public void modifyScenario() { getScenario().getModel().getLastScenarioModel().addCase(new ScenarioCaseModel()); } } + diff --git a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/TestScenarioRepository.java b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/TestScenarioRepository.java index 8f6e906f09d..e6a44578ca3 100644 --- a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/TestScenarioRepository.java +++ b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/TestScenarioRepository.java @@ -283,8 +283,8 @@ public static TestScenario testWithTwoCasesAndTheFirstOneFails() { return new TestScenario(TestWithTwoCasesAndAFailingOne.class); } - public static TestScenario junit5TestsWithModificationsInAfterMethod() { - return new TestScenario(JUnit5AfterMethodTests.class); + public static TestScenario junit6TestsWithModificationsInAfterMethod() { + return new TestScenario(JUnit6AfterMethodTests.class); } public static TestScenario testNgTestWithAFailingCase() { diff --git a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/JUnit5AssumptionTestScenarios.java b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/JUnit6AssumptionTestScenarios.java similarity index 95% rename from jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/JUnit5AssumptionTestScenarios.java rename to jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/JUnit6AssumptionTestScenarios.java index 2c0e2e4e641..b8c436bc7ab 100644 --- a/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/JUnit5AssumptionTestScenarios.java +++ b/jgiven-tests/src/main/java/com/tngtech/jgiven/tests/assumptions/JUnit6AssumptionTestScenarios.java @@ -9,7 +9,7 @@ @SuppressWarnings("NewClassNamingConvention") @ExtendWith(JGivenReportExtractingExtension.class) -public class JUnit5AssumptionTestScenarios { +public class JUnit6AssumptionTestScenarios { @ScenarioStage GivenTestStage givenTestStage; diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/AssumptionsTest.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/AssumptionsTest.java index 901bfd85f7e..0833eb1221c 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/AssumptionsTest.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/AssumptionsTest.java @@ -3,7 +3,7 @@ import com.tngtech.jgiven.testframework.ThenTestFramework; import com.tngtech.jgiven.testframework.WhenTestFramework; -import com.tngtech.jgiven.tests.assumptions.JUnit5AssumptionTestScenarios; +import com.tngtech.jgiven.tests.assumptions.JUnit6AssumptionTestScenarios; import com.tngtech.jgiven.tests.assumptions.JUnitAssumptionTestScenarios; import com.tngtech.jgiven.tests.assumptions.TestNgAssumptionTestScenarios; import org.junit.Test; @@ -69,7 +69,7 @@ public void junit5_does_not_fail_for_failing_assumption_in_second_stage() { } private void junit5_handles_assumptions_correctly(String testName) { - given().a_test_named_$(testName, JUnit5AssumptionTestScenarios.class); + given().a_test_named_$(testName, JUnit6AssumptionTestScenarios.class); when().the_test_is_executed_with_JUnit5(); then().the_test_is_ignored() .the_report_model_contains_$_scenarios(1); diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/GivenScenarioTest.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/GivenScenarioTest.java index f381ba1d2f9..9c67b3eeb05 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/GivenScenarioTest.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/GivenScenarioTest.java @@ -140,8 +140,8 @@ public void a_pending_scenario_with_a_data_provider() { testScenario = new TestScenario(PendingDataProviderTests.class); } - public SELF junit5_tests_with_scenario_modifications_in_after_method() { - testScenario = TestScenarioRepository.junit5TestsWithModificationsInAfterMethod(); + public SELF junit6_tests_with_scenario_modifications_in_after_method() { + testScenario = TestScenarioRepository.junit6TestsWithModificationsInAfterMethod(); return self(); } diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/JUnit5Executor.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/JUnit6Executor.java similarity index 94% rename from jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/JUnit5Executor.java rename to jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/JUnit6Executor.java index d1959d78163..d9a973d0762 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/JUnit5Executor.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/JUnit6Executor.java @@ -1,4 +1,4 @@ -package com.tngtech.jgiven.junit5; +package com.tngtech.jgiven.junit6; import com.tngtech.jgiven.testframework.TestExecutionResult; import com.tngtech.jgiven.testframework.TestExecutor; @@ -9,7 +9,7 @@ import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.launcher.core.LauncherFactory; -public class JUnit5Executor extends TestExecutor { +public class JUnit6Executor extends TestExecutor { @Override public TestExecutionResult execute(Class testClass, String testMethod) { diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/JUnit5ExecutorTest.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/JUnit6ExecutorTest.java similarity index 95% rename from jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/JUnit5ExecutorTest.java rename to jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/JUnit6ExecutorTest.java index 783827b185f..6af783d746f 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/JUnit5ExecutorTest.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/JUnit6ExecutorTest.java @@ -1,4 +1,4 @@ -package com.tngtech.jgiven.junit5; +package com.tngtech.jgiven.junit6; import com.tngtech.jgiven.GivenScenarioTest; import com.tngtech.jgiven.JGivenScenarioTest; @@ -9,13 +9,13 @@ import org.junit.Test; @FeatureJUnit5 -public class JUnit5ExecutorTest +public class JUnit6ExecutorTest extends JGivenScenarioTest, WhenTestFramework, ThenTestFramework> { @Test public void tests_with_scenario_modifications_in_after_method() { - given().junit5_tests_with_scenario_modifications_in_after_method(); + given().junit6_tests_with_scenario_modifications_in_after_method(); when().the_test_class_is_executed_with_JUnit5(); then().each_scenario_contains_$_cases(2); } diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/Junit5TestExecutionResult.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/Junit6TestExecutionResult.java similarity index 94% rename from jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/Junit5TestExecutionResult.java rename to jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/Junit6TestExecutionResult.java index 9db7f164346..33fc67bd121 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/Junit5TestExecutionResult.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/Junit6TestExecutionResult.java @@ -1,4 +1,4 @@ -package com.tngtech.jgiven.junit5; +package com.tngtech.jgiven.junit6; import com.tngtech.jgiven.report.model.ReportModel; import com.tngtech.jgiven.testframework.TestExecutionResult; @@ -6,13 +6,13 @@ import java.util.Map; import java.util.stream.Stream; -class Junit5TestExecutionResult extends TestExecutionResult { +class Junit6TestExecutionResult extends TestExecutionResult { private final ReportModel report; private final Map methodResults; private final Map, org.junit.platform.engine.TestExecutionResult> classResults; - public Junit5TestExecutionResult(ReportModel report, + public Junit6TestExecutionResult(ReportModel report, Map result, Map, org.junit.platform.engine.TestExecutionResult> classResults) { this.report = report; diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/TestExecutionResultProvider.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/TestExecutionResultProvider.java similarity index 96% rename from jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/TestExecutionResultProvider.java rename to jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/TestExecutionResultProvider.java index 3ad53f902ec..d4ecea02cd9 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/junit5/TestExecutionResultProvider.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/junit6/TestExecutionResultProvider.java @@ -1,17 +1,18 @@ -package com.tngtech.jgiven.junit5; +package com.tngtech.jgiven.junit6; import com.tngtech.jgiven.report.model.ReportModel; import com.tngtech.jgiven.testframework.TestExecutionResult; import com.tngtech.jgiven.tests.JGivenReportExtractingExtension; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + class TestExecutionResultProvider implements TestExecutionListener { private final Map methodExecutionResults = new HashMap<>(); @@ -53,6 +54,6 @@ private void handleTestMethodFinished(MethodSource testSource, public TestExecutionResult getExecutionResult() { - return new Junit5TestExecutionResult(reportModel, methodExecutionResults, classExecutionResults); + return new Junit6TestExecutionResult(reportModel, methodExecutionResults, classExecutionResults); } } diff --git a/jgiven-tests/src/test/java/com/tngtech/jgiven/testframework/TestExecutor.java b/jgiven-tests/src/test/java/com/tngtech/jgiven/testframework/TestExecutor.java index cd1bb18e296..289cbd5eb33 100644 --- a/jgiven-tests/src/test/java/com/tngtech/jgiven/testframework/TestExecutor.java +++ b/jgiven-tests/src/test/java/com/tngtech/jgiven/testframework/TestExecutor.java @@ -1,7 +1,7 @@ package com.tngtech.jgiven.testframework; import com.tngtech.jgiven.junit.JUnitExecutor; -import com.tngtech.jgiven.junit5.JUnit5Executor; +import com.tngtech.jgiven.junit6.JUnit6Executor; import com.tngtech.jgiven.testng.TestNgExecutor; public abstract class TestExecutor { @@ -11,7 +11,7 @@ public static TestExecutor getExecutor(TestFramework framework) { case JUnit: return new JUnitExecutor(); case JUnit5: - return new JUnit5Executor(); + return new JUnit6Executor(); case TestNG: return new TestNgExecutor(); default: diff --git a/settings.gradle b/settings.gradle index 3d6bbe75c4d..f24f74c0b98 100644 --- a/settings.gradle +++ b/settings.gradle @@ -44,7 +44,9 @@ include ':jgiven-core', ':jgiven-tests', ':jgiven-examples', ':jgiven-junit5', + ':jgiven-junit6', ':jgiven-spring-junit5', + ':jgiven-spring-junit6', ':jgiven-gradle-plugin' def timingEnabled = System.getenv("JGivenTiming")