diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d8b94486..d4586cdf8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## New Features +* Added possibility to use JGiven in JUnit by just using two rules. No deriving from ScenarioTest is necessary anymore * Allow multiple formatter annotations on arguments, e.g., "@Quoted @YesNo", see [#204](https://github.com/TNG/JGiven/issues/204). * Added a new comment() method to provide further information on specific step method invocations, see [#50](https://github.com/TNG/JGiven/issues/50). * Steps can now have multiple attachments [#194](https://github.com/TNG/JGiven/issues/194). diff --git a/docs/getting_started.adoc b/docs/getting_started.adoc index ef35df39b3..5023126095 100644 --- a/docs/getting_started.adoc +++ b/docs/getting_started.adoc @@ -10,7 +10,8 @@ First of all you create a JUnit test class that inherits from `com.tngtech.jgive [source] ---- -include::{sourcedir}/JGivenTemplateTest.java[tags=noPackage] +include::{sourcedir}/MyShinyJGivenTest.java[tags=header] +} ---- The `ScenarioTest` requires 3 type parameters. Each of these type parameters represents a stage of the Given-When-Then notation. Note that there is also the `SimpleScenarioTest` class that only requires a single type parameter. In that case, all your scenario steps are defined in a single class. @@ -52,4 +53,24 @@ The scenario is then executed like any other JUnit test, for example, by using y [source,bash] ---- $ mvn test ----- \ No newline at end of file +---- + +=== Using JUnit Rules directly instead of deriving from ScenarioTest +Sometimes it is not possible to derive your test class from the `ScenarioTest` class, because you might already have a common base class that you cannot easily modify. +In that case you can directly use the JUnit Rules of JGiven. Instead of providing your stage classes as type parameters, you inject the stages into the test class with the `@ScenarioStage` annotation. + +[source,java] +---- +include::{sourcedir}/UsingRulesTest.java[tags=noPackage] +---- + +Note that your stage classes have to inherit from the `Stage` class in order to have the `given(), when()`, and `then()` methods. +You can now also define convenient methods in your test class to get cleaner scenarios if you like: + +[source,java] +---- +public GivenSomeState given() { + return someStage.given(); +} +---- + diff --git a/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/userguide/UsingRulesTest.java b/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/userguide/UsingRulesTest.java new file mode 100644 index 0000000000..54a702c59b --- /dev/null +++ b/jgiven-examples/src/test/java/com/tngtech/jgiven/examples/userguide/UsingRulesTest.java @@ -0,0 +1,36 @@ +package com.tngtech.jgiven.examples.userguide; + +import com.tngtech.jgiven.annotation.ScenarioStage; +import com.tngtech.jgiven.junit.ScenarioExecutionRule; +import com.tngtech.jgiven.junit.ScenarioReportRule; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; + +//tag::noPackage[] + +public class UsingRulesTest { + + @ClassRule + public static final ScenarioReportRule writerRule = new ScenarioReportRule(); + + @Rule + public final ScenarioExecutionRule scenarioRule = new ScenarioExecutionRule(); + + @ScenarioStage + GivenSomeState someState; + + @ScenarioStage + WhenSomeAction someAction; + + @ScenarioStage + ThenSomeOutcome someOutcome; + + @Test + public void something_should_happen() { + someState.given().some_state(); + someAction.when().some_action(); + someOutcome.then().some_outcome(); + } +} +//end::noPackage[] diff --git a/jgiven-junit/src/main/java/com/tngtech/jgiven/junit/ScenarioExecutionRule.java b/jgiven-junit/src/main/java/com/tngtech/jgiven/junit/ScenarioExecutionRule.java index 1b1f48dfbb..f7b5f2a72f 100644 --- a/jgiven-junit/src/main/java/com/tngtech/jgiven/junit/ScenarioExecutionRule.java +++ b/jgiven-junit/src/main/java/com/tngtech/jgiven/junit/ScenarioExecutionRule.java @@ -57,6 +57,13 @@ public ScenarioExecutionRule( Object testInstance, ScenarioBase scenario ) { this.scenario = scenario; } + /** + * @since 0.12.0 + */ + public ScenarioExecutionRule() { + this.scenario = new ScenarioBase(); + } + /** * @since 0.8.1 */ @@ -64,6 +71,13 @@ public ScenarioExecutionRule( ScenarioBase scenario ) { this.scenario = scenario; } + /** + * Returns the ScenarioBase instance of this rule + */ + public ScenarioBase getScenario() { + return scenario; + } + @Override public Statement apply( final Statement base, final FrameworkMethod method, final Object target ) { return new Statement() { diff --git a/jgiven-junit/src/test/java/com/tngtech/jgiven/junit/OnlyRulesTest.java b/jgiven-junit/src/test/java/com/tngtech/jgiven/junit/OnlyRulesTest.java new file mode 100644 index 0000000000..61bfc227f6 --- /dev/null +++ b/jgiven-junit/src/test/java/com/tngtech/jgiven/junit/OnlyRulesTest.java @@ -0,0 +1,40 @@ +package com.tngtech.jgiven.junit; + +import com.tngtech.jgiven.annotation.ScenarioStage; +import org.junit.ClassRule; +import org.junit.Rule; + +import com.tngtech.jgiven.Stage; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Verifies that JGiven can be used without inheriting from any class, + * just by using the two JGiven rules + */ +public class OnlyRulesTest { + + @ClassRule + public static final ScenarioReportRule writerRule = new ScenarioReportRule(); + + @Rule + public final ScenarioExecutionRule scenarioRule = new ScenarioExecutionRule(); + + @ScenarioStage + TestStage stage; + + @Test + public void JGiven_can_be_used_just_by_using_JUnit_rules() { + stage.given().something(); + + assertThat(scenarioRule.getScenario().getScenarioModel().getCase(0).getFirstStep().getLastWord().getValue()).isEqualTo("something"); + } + + public static class TestStage extends Stage { + public void something() { + + } + } + +}