You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by bu...@apache.org on 2013/07/18 09:14:43 UTC
svn commit: r869932 - in /websites/staging/isis/trunk: cgi-bin/ content/
content/core/specsupport-and-integtestsupport.html
Author: buildbot
Date: Thu Jul 18 07:14:43 2013
New Revision: 869932
Log:
Staging update by buildbot for isis
Modified:
websites/staging/isis/trunk/cgi-bin/ (props changed)
websites/staging/isis/trunk/content/ (props changed)
websites/staging/isis/trunk/content/core/specsupport-and-integtestsupport.html
Propchange: websites/staging/isis/trunk/cgi-bin/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Thu Jul 18 07:14:43 2013
@@ -1 +1 @@
-1503780
+1504377
Propchange: websites/staging/isis/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Thu Jul 18 07:14:43 2013
@@ -1 +1 @@
-1503780
+1504377
Modified: websites/staging/isis/trunk/content/core/specsupport-and-integtestsupport.html
==============================================================================
--- websites/staging/isis/trunk/content/core/specsupport-and-integtestsupport.html (original)
+++ websites/staging/isis/trunk/content/core/specsupport-and-integtestsupport.html Thu Jul 18 07:14:43 2013
@@ -292,9 +292,17 @@ or regular integration tests.</p>
<p>Like the <code>IsisSystemForTest</code> class, the <code>ScenarioExecution</code> class also binds an instance of itself onto a <code>ThreadLocal</code>. It can then be accessed in both BDD step defs and in integration tests using <code>ScenarioExecution.current()</code> static method.</p>
-<h3>CukeStepDefsAbstract and IntegrationTestAbstract</h3>
+<h3>CukeGlueAbstract and IntegrationTestAbstract</h3>
-<p>The <code>CukeStepDefsAbstract</code> acts as a convenience superclass for writing BDD step definitions. Similarly, the <code>IntegrationTestAbstract</code> acts as a convenience subclass for writing integration tests. These two classes are very similar in that they both delegate to an underlying <code>ScenarioExecution</code>.</p>
+<p>The <code>CukeGlueAbstract</code> acts as a convenience superclass for writing BDD step definitions. Similarly, the <code>IntegrationTestAbstract</code> acts as a convenience subclass for writing integration tests. These two classes are very similar in that they both delegate to an underlying <code>ScenarioExecution</code>.</p>
+
+<h3>Separate Glue from Specs</h3>
+
+<p>The "glue" (step definitions) are intended to be reused across features. We therefore recommend that they reside in a separate package, and are organized by the entity type upon which they act. </p>
+
+<p>For example, given a feature that involves <code>Customer</code> and <code>Order</code>, have the step definitions pertaining to <code>Customer</code> reside in <code>CustomerGlue</code>, and the step definitions pertaining to <code>Order</code> reside in <code>OrderGlue</code>.</p>
+
+<p>The Cucumber-JVM spec runner allows you to indicate which package(s) should be recursively searched to find any glue.</p>
<h3>Integration- vs Unit- Scope</h3>
@@ -444,12 +452,12 @@ or regular integration tests.</p>
<ul>
<li>a <code>XxxSpec.feature</code> file, describing the feature and the scenarios (given/when/then)s that constitute its acceptance criteria</li>
-<li>a <code>XxxSpec.java</code> class file to run the specification (all boilerplate). This must have the same basename as the <code>.feature</code> file</li>
-<li>one or several <code>XxxStepDefs</code> constituting the step definitions to be matched against. (I believe...) these must reside in the same package as the specification.</li>
+<li>a <code>RunSpecs.java</code> class file to run the specification (all boilerplate). This will run all <code>.feature</code> files in the same package or subpackages.</li>
+<li>one or several <code>XxxGlue</code> constituting the step definitions to be matched against. These are normally placed in a separate package(s) to the specifications; the <code>glue</code> attribute of the Cucumber-JVM JUnit runner indicates which package(s) to search in.</li>
<li>a system initializer class. This can be reused with any integration tests (eg the <code>ToDoSystemInitializer</code> class, shown above).</li>
</ul>
-<p>It's usually more convenient to place the <code>.feature</code> files in <code>src/test/java</code>, rather than <code>src/test/resources</code>. If you wish to do this, then your integration test module's <code>pom.xml</code> must contain:</p>
+<p>You may find it more convenient to place the <code>.feature</code> files in <code>src/test/java</code>, rather than <code>src/test/resources</code>. If you wish to do this, then your integration test module's <code>pom.xml</code> must contain:</p>
<pre><code><build>
<testResources>
@@ -473,7 +481,8 @@ or regular integration tests.</p>
<p>Let's now look at the a specification for the <code>ToDoItem'</code>s "completed" feature. Firstly, the <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findAndComplete.feature"><code>ToDoItemSpec_findAndComplete.feature</code></a>:</p>
-<pre><code>Feature: Find And Complete ToDo Items
+<pre><code>@ToDoItemsFixture
+Feature: Find And Complete ToDo Items
@integration
Scenario: Todo items once completed are no longer listed
@@ -483,22 +492,29 @@ or regular integration tests.</p>
Then the item is no longer listed as incomplete
</code></pre>
-<p>The corresponding <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findCompletedAndMarkAsNotYetComplete.java"><code>ToDoItemSpec_findAndComplete</code></a> class is just boilerplate:</p>
+<p>The <code>@ToDoItemsFixture</code> is a custom tag we've specified to indicate the prerequisite fixtures to be loaded; more on this in a moment. The <code>@integration</code> tag, meanwhile, says that this feature should be run with integration-level scope. (If we wanted to run at unit-level scope, the tag would be <code>@unit</code>).</p>
+
+<p>The <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/RunSpecs.java"><code>RunSpecs</code></a> class to run this feature (and any other features in this package or subpackages) is just boilerplate:</p>
<pre><code>@RunWith(Cucumber.class)
@Cucumber.Options(
format = {
- "html:target/cucumber-html-report"
+ "html:target/cucumber-html-report",
+ "json:target/cucumber.json"
},
+ glue={"classpath:com.mycompany.integration.glue"},
strict = true,
tags = { "~@backlog", "~@ignore" })
-public class ToDoItemSpec_findAndComplete {
+public class RunSpecs {
+ // intentionally empty
}
</code></pre>
-<p>The heavy lifting is done in the <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/ToDoItemStepDefs.java"><code>ToDoItemStepDefs</code></a> class:</p>
+<p>The JSON formatter allows integration with enhanced reports, for example as provided by <a href="http://www.masterthought.net/section/cucumber-reporting">Masterthought.net</a> (screenshots at end of page). (Commented out) configuration for this is provided in the example todo app <code>integtests</code> module's <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/pom.xml">pom.xml</a>.</p>
-<pre><code>public class ToDoItemStepDefs extends CukeStepDefsAbstract {
+<p>The bootstrapping of Isis can be moved into a <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/BootstrappingGlue.java"><code>BootstrappingGlue</code></a> step definition:</p>
+
+<pre><code>public class BootstrappingGlue extends CukeGlueAbstract {
@Before(value={"@integration"}, order=100)
public void beforeScenarioIntegrationScope() {
@@ -514,12 +530,29 @@ public class ToDoItemSpec_findAndComplet
after(sc);
}
- @Before(value={"@integration"}, order=20000)
+ // bootstrapping of @unit scope omitted
+}
+</code></pre>
+
+<p>The fixture to run also lives in its own step definition, <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/CatalogOfFixturesGlue.java"><code>CatalogOfFixturesGlue</code></a>:</p>
+
+<pre><code>public class CatalogOfFixturesGlue extends CukeGlueAbstract {
+
+ @Before(value={"@integration", "@ToDoItemsFixture"}, order=20000)
public void integrationFixtures() throws Throwable {
scenarioExecution().install(new ToDoItemsFixture());
- }
+ }
+
+ // fixture for @unit, @ToDoItemsFixture omitted
+
+}
+</code></pre>
+
+<p>Note that this is annotated with a tag (<code>@ToDoItemsFixture</code>) so that the correct fixture runs. (We might have a whole variety of these).</p>
+
+<p>The step definitions pertaining to <code>ToDoItem</code> then reside in the <a href="https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java"><code>ToDoItemGlue</code></a> class. This is where the heavy lifting gets done:</p>
- // //////////////////////////////////////
+<pre><code>public class ToDoItemGlue extends CukeGlueAbstract {
@Given("^there are a number of incomplete ToDo items$")
public void there_are_a_number_of_incomplete_ToDo_items() throws Throwable {