Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/issue 373 improve testing for jupiter #827

Merged
merged 3 commits into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/junit5.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public class JGiven5ScenarioTest
}
}
----
Please note that JGiven is built around each scenario, i.e. test method, having its own test instance. Therefore, we cannot support JUnit's per-class test instance lifecycle. An exception will be thrown if any such attempt is made.

=== Example Project

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
import static com.tngtech.jgiven.report.model.ExecutionStatus.FAILED;
import static com.tngtech.jgiven.report.model.ExecutionStatus.SUCCESS;

import java.util.EnumSet;

import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.*;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;

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 java.util.EnumSet;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.TestInstancePostProcessor;

/**
* This extension enables JGiven for JUnit 5 Tests.
Expand All @@ -39,14 +44,16 @@ public class JGivenExtension implements
BeforeAllCallback,
AfterAllCallback,
BeforeEachCallback,
AfterEachCallback {
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().get());
if (!context.getDisplayName().equals(context.getTestClass().get().getSimpleName())) {
Expand All @@ -62,6 +69,7 @@ public void beforeAll(ExtensionContext context) {
}
}


@Override
public void afterAll(ExtensionContext context) {
ScenarioHolder.get().removeScenarioOfCurrentThread();
Expand All @@ -75,7 +83,7 @@ public void beforeEach(ExtensionContext context) {
}

@Override
public void afterEach(ExtensionContext context) throws Exception {
public void afterTestExecution(ExtensionContext context) throws Exception {
ScenarioBase scenario = getScenario();
try {
if (context.getExecutionException().isPresent()) {
Expand All @@ -96,10 +104,6 @@ public void afterEach(ExtensionContext context) throws Exception {
}
}

private ScenarioBase getScenario() {
return ScenarioHolder.get().getScenarioOfCurrentThread();
}

@Override
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
ScenarioBase currentScenario = ScenarioHolder.get().getScenarioOfCurrentThread();
Expand All @@ -125,4 +129,21 @@ public void postProcessTestInstance(Object testInstance, ExtensionContext contex
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();
}
}
4 changes: 4 additions & 0 deletions jgiven-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ 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-html5-report')
implementation "junit:junit:$junitVersion"
implementation "org.junit.jupiter:junit-jupiter-api:5.8.2"
implementation "org.junit.jupiter:junit-jupiter-engine:5.8.2"
implementation "org.junit.platform:junit-platform-runner:1.8.2"
implementation "org.testng:testng:$testngVersion"
implementation "com.tngtech.java:junit-dataprovider:$junitDataproviderVersion"
implementation 'com.beust:jcommander:1.82'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.tngtech.jgiven.tags;

import com.tngtech.jgiven.annotation.IsTag;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@FeatureTestFramework
@IsTag( name = "JUnit5",
description = "Tests can be be executed with JUnit5" )
@Retention( RetentionPolicy.RUNTIME )
public @interface FeatureJUnit5 {

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ public GivenTestStage an_exception_is_thrown() {
throw new RuntimeException("Some Exception");
}

public void nothing() {
public GivenTestStage nothing() {
return this;
}

public void a_failed_step(boolean fail) {
public GivenTestStage a_failed_step(boolean fail) {
if (fail) {
throw new IllegalArgumentException();
}
return this;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import com.tngtech.jgiven.junit.ScenarioTest;
import org.junit.Test;

public class GuaranteedFieldRealTest extends ScenarioTest<GuaranteedFieldRealTest.RealGiven, GuaranteedFieldRealTest.RealWhen, GuaranteedFieldRealTest.RealThen> {
public class GuaranteedFieldRealTest extends
ScenarioTest<GuaranteedFieldRealTest.RealGiven, GuaranteedFieldRealTest.RealWhen, GuaranteedFieldRealTest.RealThen> {

@Test
public void a_sample_test() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.tngtech.jgiven.tests;

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.report.model.ReportModel;
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.
*/
public class JGivenReportExtractingExtension extends JGivenExtension {

private static final Map<Class<?>, ReportModel> modelHolder = new ConcurrentHashMap<>();

public static Optional<ReportModel> getReportModelFor(Class<?> testClass) {
return Optional.ofNullable(modelHolder.get(testClass));
}


@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
Class<?> testClass = context.getTestClass()
.orElseThrow(() -> new JGivenWrongUsageException("tests without test class are not supported yet"));
Optional.ofNullable(ScenarioHolder.get())
.map(ScenarioHolder::getScenarioOfCurrentThread)
.map(ScenarioBase::getModel)
.ifPresent(model -> modelHolder.put(testClass, model));
super.afterTestExecution(context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.tngtech.jgiven.tests;

import com.tngtech.jgiven.base.ScenarioTestBase;
import com.tngtech.jgiven.impl.Scenario;
import com.tngtech.jgiven.report.model.ScenarioCaseModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(JGivenReportExtractingExtension.class)
public class JUnit5AfterMethodTests extends ScenarioTestBase<GivenTestStage, WhenTestStage, ThenTestStage> {

private final Scenario<GivenTestStage, WhenTestStage, ThenTestStage> scenario = createScenario();

@Override
public Scenario<GivenTestStage, WhenTestStage, ThenTestStage> getScenario() {
return scenario;
}

@Test
public void a_failing_JUnit_5_test() {
given().nothing();
when().a_step_fails();
then().something_happened();
}

@Test
public void a_succeeding_JUnit5_test() {
given().nothing();
when().something_happens();
then().something_happened();
}

@Test
@Disabled
public void a_skipped_JUnit5_test() {
given().nothing();
when().something_happens();
then().something_happened();
}


@AfterEach
public void modifyScenario() {
getScenario().getModel().getLastScenarioModel().addCase(new ScenarioCaseModel());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.tngtech.jgiven.impl.Scenario;
import com.tngtech.jgiven.junit.ScenarioTest;
import com.tngtech.jgiven.impl.ScenarioHolder;
import org.junit.jupiter.api.extension.ExtendWith;

@ExtendWith(JGivenReportExtractingExtension.class)
public class ScenarioTestForTesting<GIVEN, WHEN, THEN> extends ScenarioTest<GIVEN,WHEN,THEN> {
@Override
public Scenario<GIVEN, WHEN, THEN> getScenario() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.tngtech.jgiven.tests;

import org.junit.Test;
import org.testng.annotations.Listeners;

import com.tngtech.jgiven.annotation.Description;
import com.tngtech.jgiven.junit.ScenarioTest;
import com.tngtech.jgiven.testng.ScenarioTestListener;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testng.annotations.Listeners;

@Listeners( ScenarioTestListener.class )
@ExtendWith(JGivenReportExtractingExtension.class)
@Description( "Test Description" )
public class TestClassWithDescription extends ScenarioTest<GivenTestStage, WhenTestStage, ThenTestStage> {

@Test
@org.junit.jupiter.api.Test
@org.testng.annotations.Test
public void some_test() {
given().nothing();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package com.tngtech.jgiven.tests;

import com.tngtech.jgiven.testng.ScenarioTestListener;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testng.annotations.Listeners;

import com.tngtech.jgiven.junit.ScenarioTest;
import com.tngtech.jgiven.testng.ScenarioTestListener;

@Listeners( ScenarioTestListener.class )
@ExtendWith(JGivenReportExtractingExtension.class)
public class TestClassWithOnlyIgnoredTests extends ScenarioTestForTesting<GivenTestStage, WhenTestStage, ThenTestStage> {

@Ignore
@Test
@org.junit.jupiter.api.Test
@Disabled
@org.testng.annotations.Test( enabled = false )
public void test() {

Expand Down
Loading