You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/07/18 09:14:35 UTC

svn commit: r1504377 - /isis/site/trunk/content/core/specsupport-and-integtestsupport.md

Author: danhaywood
Date: Thu Jul 18 07:14:34 2013
New Revision: 1504377

URL: http://svn.apache.org/r1504377
Log:
updates to spec support

Modified:
    isis/site/trunk/content/core/specsupport-and-integtestsupport.md

Modified: isis/site/trunk/content/core/specsupport-and-integtestsupport.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/core/specsupport-and-integtestsupport.md?rev=1504377&r1=1504376&r2=1504377&view=diff
==============================================================================
--- isis/site/trunk/content/core/specsupport-and-integtestsupport.md (original)
+++ isis/site/trunk/content/core/specsupport-and-integtestsupport.md Thu Jul 18 07:14:34 2013
@@ -38,10 +38,17 @@ Of relevance only to BDD specs, the `Sce
 
 Like the `IsisSystemForTest` class, the `ScenarioExecution` class also binds an instance of itself onto a `ThreadLocal`.  It can then be accessed in both BDD step defs and in integration tests using `ScenarioExecution.current()` static method.
 
-### CukeStepDefsAbstract and IntegrationTestAbstract ###
+### CukeGlueAbstract and IntegrationTestAbstract ###
 
-The `CukeStepDefsAbstract` acts as a convenience superclass for writing BDD step definitions.  Similarly, the `IntegrationTestAbstract` acts as a convenience subclass for writing integration tests.  These two classes are very similar in that they both delegate to an underlying `ScenarioExecution`.
+The `CukeGlueAbstract` acts as a convenience superclass for writing BDD step definitions.  Similarly, the `IntegrationTestAbstract` acts as a convenience subclass for writing integration tests.  These two classes are very similar in that they both delegate to an underlying `ScenarioExecution`.
 
+### Separate Glue from Specs ###
+
+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.  
+
+For example, given a feature that involves `Customer` and `Order`, have the step definitions pertaining to `Customer` reside in `CustomerGlue`, and the step definitions pertaining to `Order` reside in `OrderGlue`.
+
+The Cucumber-JVM spec runner allows you to indicate which package(s) should be recursively searched to find any glue.
 
 ### Integration- vs Unit- Scope
 
@@ -189,13 +196,13 @@ BDD specifications contain a few more pa
 
 * a `XxxSpec.feature` file, describing the feature and the scenarios (given/when/then)s that constitute its acceptance criteria
 
-* a `XxxSpec.java` class file to run the specification (all boilerplate).  This must have the same basename as the `.feature` file
+* a `RunSpecs.java` class file to run the specification (all boilerplate).  This will run all `.feature` files in the same package or subpackages.
 
-* one or several `XxxStepDefs` constituting the step definitions to be matched against.  (I believe...) these must reside in the same package as the specification.
+* one or several `XxxGlue` constituting the step definitions to be matched against.  These are normally placed in a separate package(s) to the specifications; the `glue` attribute of the Cucumber-JVM JUnit runner indicates which package(s) to search in.
 
 * a system initializer class.  This can be reused with any integration tests (eg the `ToDoSystemInitializer` class, shown above).
 
-It's usually more convenient to place the `.feature` files in `src/test/java`, rather than `src/test/resources`.  If you wish to do this, then your integration test module's `pom.xml` must contain:
+You may find it more convenient to place the `.feature` files in `src/test/java`, rather than `src/test/resources`.  If you wish to do this, then your integration test module's `pom.xml` must contain:
  
     <build>
         <testResources>
@@ -218,6 +225,7 @@ It's usually more convenient to place th
 
 Let's now look at the a specification for the `ToDoItem'`s "completed" feature.  Firstly, the [`ToDoItemSpec_findAndComplete.feature`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findAndComplete.feature):
 
+    @ToDoItemsFixture
     Feature: Find And Complete ToDo Items
 
         @integration
@@ -227,22 +235,29 @@ Let's now look at the a specification fo
           And   mark the item as complete
           Then  the item is no longer listed as incomplete 
 
-The corresponding [`ToDoItemSpec_findAndComplete`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/ToDoItemSpec_findCompletedAndMarkAsNotYetComplete.java) class is just boilerplate:
+The `@ToDoItemsFixture` is a custom tag we've specified to indicate the prerequisite fixtures to be loaded; more on this in a moment.  The `@integration` 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 `@unit`).
+
+The [`RunSpecs`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/RunSpecs.java) class to run this feature (and any other features in this package or subpackages) is just boilerplate:
 
     @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 
     }
-    
-The heavy lifting is done in the [`ToDoItemStepDefs`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/specs/todoitem/ToDoItemStepDefs.java) class:
 
-    public class ToDoItemStepDefs extends CukeStepDefsAbstract {
-       
+The JSON formatter allows integration with enhanced reports, for example as provided by [Masterthought.net](http://www.masterthought.net/section/cucumber-reporting) (screenshots at end of page).  (Commented out) configuration for this is provided in the example todo app `integtests` module's [pom.xml](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/pom.xml).
+
+The bootstrapping of Isis can be moved into a [`BootstrappingGlue`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/BootstrappingGlue.java) step definition:
+
+    public class BootstrappingGlue extends CukeGlueAbstract {
+    
         @Before(value={"@integration"}, order=100)
         public void beforeScenarioIntegrationScope() {
             PropertyConfigurator.configure("logging.properties");
@@ -256,13 +271,28 @@ The heavy lifting is done in the [`ToDoI
             assertMocksSatisfied();
             after(sc);
         }
-    
-        @Before(value={"@integration"}, order=20000)
+
+        // bootstrapping of @unit scope omitted
+    }
+
+The fixture to run also lives in its own step definition, [`CatalogOfFixturesGlue`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/CatalogOfFixturesGlue.java):
+
+    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
+    
+    }
+
+Note that this is annotated with a tag (`@ToDoItemsFixture`) so that the correct fixture runs.  (We might have a whole variety of these).
+     
+The step definitions pertaining to `ToDoItem` then reside in the [`ToDoItemGlue`](https://github.com/apache/isis/blob/master/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java) class.  This is where the heavy lifting gets done:
+
+    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 {