Title: [1558] trunk/core: JBEHAVE-133: Applied Paul's PicoStepsFactory from spike.
Revision
1558
Author
mauro
Date
2010-02-07 12:31:49 -0600 (Sun, 07 Feb 2010)

Log Message

JBEHAVE-133:  Applied Paul's PicoStepsFactory from spike.  Added scenario that uses Pico-composed steps in trader example.

Modified Paths

Added Paths

Diff

Modified: trunk/core/examples/trader/pom.xml (1557 => 1558)

--- trunk/core/examples/trader/pom.xml	2010-02-06 09:44:54 UTC (rev 1557)
+++ trunk/core/examples/trader/pom.xml	2010-02-07 18:31:49 UTC (rev 1558)
@@ -10,10 +10,13 @@
   <name>JBehave Trader Example</name>
 
   <dependencies>
+    <dependency>
+      <groupId>org.jbehave</groupId>
+      <artifactId>jbehave-pico</artifactId>
+      <version>${jbehave.version}</version>
+    </dependency>
   </dependencies>
   <build>
-    <sourceDirectory>src/main/java</sourceDirectory>
-    <testSourceDirectory>src/behaviour/java</testSourceDirectory>
     <resources>
       <resource>
         <directory>${basedir}/src/main/java</directory>
@@ -38,7 +41,7 @@
                 <artifactItem>
                   <groupId>org.jbehave.site</groupId>
                   <artifactId>jbehave-site-resources</artifactId>
-                  <version>2.0.1</version>
+                  <version>2.0.2</version>
                   <outputDirectory>${project.build.directory}/jbehave-reports/rendered</outputDirectory>
                 </artifactItem>
               </artifactItems>

Modified: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java (1557 => 1558)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java	2010-02-06 09:44:54 UTC (rev 1557)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderScenario.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -10,6 +10,7 @@
 import org.jbehave.examples.trader.model.Stock;
 import org.jbehave.examples.trader.model.Trader;
 import org.jbehave.examples.trader.persistence.TraderPersister;
+import org.jbehave.examples.trader.service.TradingService;
 import org.jbehave.scenario.JUnitScenario;
 import org.jbehave.scenario.PropertyBasedConfiguration;
 import org.jbehave.scenario.RunnableScenario;
@@ -22,6 +23,7 @@
 import org.jbehave.scenario.reporters.FilePrintStreamFactory;
 import org.jbehave.scenario.reporters.ScenarioReporter;
 import org.jbehave.scenario.reporters.ScenarioReporterBuilder;
+import org.jbehave.scenario.steps.CandidateSteps;
 import org.jbehave.scenario.steps.ParameterConverters;
 import org.jbehave.scenario.steps.SilentStepMonitor;
 import org.jbehave.scenario.steps.StepMonitor;
@@ -58,9 +60,13 @@
         configuration.usePatternBuilder(new PrefixCapturingPatternBuilder("%")); // use '%' instead of '$' to identify parameters
         configuration.useMonitor(monitor);
         
-        addSteps(new StepsFactory(configuration).createCandidateSteps(new TraderSteps()));
+        addSteps(createSteps(configuration));
     }
 
+    protected CandidateSteps[] createSteps(StepsConfiguration configuration) {
+        return new StepsFactory(configuration).createCandidateSteps(new TraderSteps(new TradingService()));
+    }
+
     private TraderPersister mockTradePersister() {
         return new TraderPersister(new Trader("Mauro", asList(new Stock("STK1", 10.d))));
     }

Modified: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderSteps.java (1557 => 1558)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderSteps.java	2010-02-06 09:44:54 UTC (rev 1557)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/TraderSteps.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -12,6 +12,7 @@
 import org.jbehave.examples.trader.model.Stock;
 import org.jbehave.examples.trader.model.Trader;
 import org.jbehave.examples.trader.model.Stock.AlertStatus;
+import org.jbehave.examples.trader.service.TradingService;
 import org.jbehave.scenario.annotations.Alias;
 import org.jbehave.scenario.annotations.Aliases;
 import org.jbehave.scenario.annotations.Given;
@@ -19,6 +20,8 @@
 import org.jbehave.scenario.annotations.Then;
 import org.jbehave.scenario.annotations.When;
 import org.jbehave.scenario.definition.ExamplesTable;
+import org.jbehave.scenario.steps.CandidateSteps;
+import org.jbehave.scenario.steps.StepsFactory;
 
 /**
  * POJO holding the candidate steps for the trader example.  
@@ -27,10 +30,15 @@
  */
 public class TraderSteps {
 
+    private TradingService service;    
     private Stock stock;
     private Trader trader;
     private List<Trader> traders = new ArrayList<Trader>();
     private List<Trader> searchedTraders;
+        
+    public TraderSteps(TradingService service) {
+        this.service = service;
+    }
 
     @Given("a trader of name %trader")
     public void aTrader(Trader trader) {
@@ -65,7 +73,7 @@
         for (Map<String, String> row : rows) {
             String name = row.get("name");
             String rank = row.get("rank");
-            traders.add(new Trader(name, rank));
+            traders.add(service.newTrader(name, rank));
         }
         Collections.sort(traders);
         return traders;
@@ -74,7 +82,7 @@
     @Given("a stock of symbol %symbol and a threshold of %threshold")
     @Alias("a stock of <symbol> and a <threshold>") // alias used with examples table
     public void aStock(@Named("symbol") String symbol, @Named("threshold") double threshold) {
-        stock = new Stock(symbol, threshold);
+        stock = service.newStock(symbol, threshold);
     }
 
     @When("the stock is traded at price %price")

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/PicoTraderScenario.java (0 => 1558)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/PicoTraderScenario.java	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/PicoTraderScenario.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,36 @@
+package org.jbehave.examples.trader.pico;
+
+import org.jbehave.examples.trader.TraderScenario;
+import org.jbehave.examples.trader.TraderSteps;
+import org.jbehave.examples.trader.service.TradingService;
+import org.jbehave.scenario.RunnableScenario;
+import org.jbehave.scenario.steps.CandidateSteps;
+import org.jbehave.scenario.steps.StepsConfiguration;
+import org.jbehave.scenario.steps.pico.PicoStepsFactory;
+import org.picocontainer.Characteristics;
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.PicoContainer;
+import org.picocontainer.behaviors.Caching;
+import org.picocontainer.injectors.ConstructorInjection;
+
+public class PicoTraderScenario extends TraderScenario {
+
+    public PicoTraderScenario(Class<? extends RunnableScenario> scenarioClass) {
+        super(scenarioClass);
+    }
+
+    @Override
+    protected CandidateSteps[] createSteps(StepsConfiguration configuration) {
+        PicoContainer parent = createPicoContainer();
+        return new PicoStepsFactory(configuration, parent).createCandidateSteps();
+    }
+
+    private PicoContainer createPicoContainer() {
+        MutablePicoContainer parent = new DefaultPicoContainer(new Caching().wrap(new ConstructorInjection()));
+        parent.as(Characteristics.USE_NAMES).addComponent(TradingService.class);
+        parent.as(Characteristics.USE_NAMES).addComponent(TraderSteps.class);
+        return parent;
+    }
+    
+}

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/scenarios/WildcardSearch.java (0 => 1558)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/scenarios/WildcardSearch.java	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/scenarios/WildcardSearch.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,11 @@
+package org.jbehave.examples.trader.pico.scenarios;
+
+import org.jbehave.examples.trader.pico.PicoTraderScenario;
+
+public class WildcardSearch extends PicoTraderScenario {
+
+    public WildcardSearch() {
+        super(WildcardSearch.class);
+    }
+    
+}

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/scenarios/wildcard_search.scenario (0 => 1558)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/scenarios/wildcard_search.scenario	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/pico/scenarios/wildcard_search.scenario	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,19 @@
+Scenario: Traders can be searched by name.   This is the same scenario as
+org.jbehave.examples.trader.scenarios.wildcard_search, with the only difference that
+the candidate steps class (TraderSteps) is created, with it dependency, via a PicoContainer.
+
+Given the traders: 
+|name|rank|
+|Larry|Stooge 3|
+|Moe|Stooge 1|
+|Curly|Stooge 2|
+!-- This is a comment, which will be ignored in the execution
+When a wildcard search ".*y" is executed
+!-- This is another comment, also ignored, 
+but look Ma! I'm on a new line!
+Then the traders returned are:
+|name|rank|
+|Larry|Stooge 3|
+|Curly|Stooge 2|
+
+

Added: trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/service/TradingService.java (0 => 1558)

--- trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/service/TradingService.java	                        (rev 0)
+++ trunk/core/examples/trader/src/main/java/org/jbehave/examples/trader/service/TradingService.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,16 @@
+package org.jbehave.examples.trader.service;
+
+import org.jbehave.examples.trader.model.Stock;
+import org.jbehave.examples.trader.model.Trader;
+
+public class TradingService {
+
+    public Stock newStock(String symbol, double threshold) {
+        return new Stock(symbol, threshold);
+    }
+
+    public Trader newTrader(String name, String rank) {
+        return new Trader(name, rank);
+    }
+
+}

Modified: trunk/core/examples/trader-test-scope/pom.xml (1557 => 1558)

--- trunk/core/examples/trader-test-scope/pom.xml	2010-02-06 09:44:54 UTC (rev 1557)
+++ trunk/core/examples/trader-test-scope/pom.xml	2010-02-07 18:31:49 UTC (rev 1558)
@@ -9,6 +9,13 @@
   <artifactId>jbehave-trader-test-scope-example</artifactId>
   <name>JBehave Trader Test Scope Example</name>
 
+  <dependencies>
+    <dependency>
+      <groupId>org.jbehave</groupId>
+      <artifactId>jbehave-pico</artifactId>
+      <version>${jbehave.version}</version>
+    </dependency>
+  </dependencies>
   <build>
     <!-- JBEHAVE-155: we can run scenarios in test scope -->
     <testSourceDirectory>${basedir}/../trader/src/main/java</testSourceDirectory>

Modified: trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/Steps.java (1557 => 1558)

--- trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/Steps.java	2010-02-06 09:44:54 UTC (rev 1557)
+++ trunk/core/jbehave-core/src/main/java/org/jbehave/scenario/steps/Steps.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -13,6 +13,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
 import org.jbehave.scenario.annotations.AfterScenario;
 import org.jbehave.scenario.annotations.Alias;
 import org.jbehave.scenario.annotations.Aliases;
@@ -311,4 +313,10 @@
         }
 
     }
+    
+    @Override
+    public String toString() {
+       return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+    }
+    
 }

Property changes: trunk/core/jbehave-pico

Name: svn:ignore
   + target

Added: trunk/core/jbehave-pico/pom.xml (0 => 1558)

--- trunk/core/jbehave-pico/pom.xml	                        (rev 0)
+++ trunk/core/jbehave-pico/pom.xml	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,26 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.jbehave</groupId>
+    <artifactId>jbehave</artifactId>
+    <version>2.5-SNAPSHOT</version>
+  </parent>
+  <artifactId>jbehave-pico</artifactId>
+  <name>JBehave PicoContainer Support</name>
+  <description>Extension of JBehave Core that allows CandidateSteps instances to be composed using a PicoContainer</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.jbehave</groupId>
+      <artifactId>jbehave-core</artifactId>
+      <version>${pom.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.picocontainer</groupId>
+      <artifactId>picocontainer</artifactId>
+      <version>2.10-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>

Added: trunk/core/jbehave-pico/src/behaviour/java/org/jbehave/scenario/steps/pico/PicoStepsFactoryBehaviour.java (0 => 1558)

--- trunk/core/jbehave-pico/src/behaviour/java/org/jbehave/scenario/steps/pico/PicoStepsFactoryBehaviour.java	                        (rev 0)
+++ trunk/core/jbehave-pico/src/behaviour/java/org/jbehave/scenario/steps/pico/PicoStepsFactoryBehaviour.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,95 @@
+package org.jbehave.scenario.steps.pico;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+
+import org.jbehave.scenario.annotations.Given;
+import org.jbehave.scenario.steps.CandidateSteps;
+import org.jbehave.scenario.steps.Steps;
+import org.jbehave.scenario.steps.StepsConfiguration;
+import org.junit.Before;
+import org.junit.Test;
+import org.picocontainer.Characteristics;
+import org.picocontainer.DefaultPicoContainer;
+import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.behaviors.Caching;
+import org.picocontainer.injectors.AbstractInjector;
+import org.picocontainer.injectors.ConstructorInjection;
+
+public class PicoStepsFactoryBehaviour {
+
+    private static Field stepsInstance;
+
+    @Before
+    public void setUp() throws NoSuchFieldException {
+        stepsInstance = Steps.class.getDeclaredField("instance");
+        stepsInstance.setAccessible(true);
+    }
+
+    private MutablePicoContainer createPicoContainer() {
+        return new DefaultPicoContainer(new Caching().wrap(new ConstructorInjection()));
+    }
+
+    @Test
+    public void ensureThatStepsCanBeCreated() throws NoSuchFieldException, IllegalAccessException {
+        // Given
+        MutablePicoContainer parent = createPicoContainer();
+        parent.as(Characteristics.USE_NAMES).addComponent(FooSteps.class);
+        PicoStepsFactory factory = new PicoStepsFactory(new StepsConfiguration(), parent);
+        // When
+        CandidateSteps[] steps = factory.createCandidateSteps();
+        // Then 
+        assertFooStepsFound(steps);
+    }
+
+
+    @Test
+    public void ensureThatStepsWithStepsWithDependencyCanBeCreated() throws NoSuchFieldException, IllegalAccessException {
+        MutablePicoContainer parent = createPicoContainer();
+        parent.as(Characteristics.USE_NAMES).addComponent(FooStepsWithDependency.class);
+        parent.addComponent(Integer.class, 42);
+        // When
+        PicoStepsFactory factory = new PicoStepsFactory(new StepsConfiguration(), parent);
+        CandidateSteps[] steps = factory.createCandidateSteps();
+        // Then
+        assertFooStepsFound(steps);
+        assertEquals(42, (int) ((FooStepsWithDependency) stepsInstance.get(steps[0])).integer);
+    }
+
+    private void assertFooStepsFound(CandidateSteps[] steps) throws NoSuchFieldException, IllegalAccessException {
+        assertEquals(1, steps.length);
+        assertTrue(steps[0] instanceof Steps);
+        Object instance = stepsInstance.get(steps[0]);
+        assertTrue(instance instanceof FooSteps);
+    }
+
+
+    @Test(expected=AbstractInjector.UnsatisfiableDependenciesException.class)
+    public void ensureThatStepsWithMissingDependenciesCannotBeCreated() throws NoSuchFieldException, IllegalAccessException {
+        MutablePicoContainer parent = createPicoContainer();
+        parent.as(Characteristics.USE_NAMES).addComponent(FooStepsWithDependency.class);
+        PicoStepsFactory factory = new PicoStepsFactory(new StepsConfiguration(), parent);
+        // When
+        factory.createCandidateSteps();
+        // Then ... expected exception is thrown        
+    }
+
+    public static class FooSteps {
+
+        @Given("a step with a $param")
+        public void aStepWithAParam(String param) {
+        }
+
+    }
+
+    public static class FooStepsWithDependency extends FooSteps {
+        private final Integer integer;
+
+        public FooStepsWithDependency(Integer steps) {
+            this.integer = steps;
+        }
+
+    }
+}

Added: trunk/core/jbehave-pico/src/main/java/org/jbehave/scenario/steps/pico/PicoStepsFactory.java (0 => 1558)

--- trunk/core/jbehave-pico/src/main/java/org/jbehave/scenario/steps/pico/PicoStepsFactory.java	                        (rev 0)
+++ trunk/core/jbehave-pico/src/main/java/org/jbehave/scenario/steps/pico/PicoStepsFactory.java	2010-02-07 18:31:49 UTC (rev 1558)
@@ -0,0 +1,53 @@
+package org.jbehave.scenario.steps.pico;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jbehave.scenario.steps.CandidateSteps;
+import org.jbehave.scenario.steps.Steps;
+import org.jbehave.scenario.steps.StepsConfiguration;
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.PicoContainer;
+
+/**
+ * A factory class for {...@link CandidateSteps} that uses a {...@link PicoContainer}
+ * for the composition and instantiation of all components that contains
+ * scenario annotated methods.
+ * 
+ * @author Paul Hammant
+ * @author Mauro Talevi
+ */
+public class PicoStepsFactory {
+
+    private final StepsConfiguration configuration;
+    private final PicoContainer parent;
+
+    public PicoStepsFactory(StepsConfiguration configuration, PicoContainer parent) {
+        this.configuration = configuration;
+        this.parent = parent;
+    }
+
+    public CandidateSteps[] createCandidateSteps() {
+        List<Steps> steps = new ArrayList<Steps>();
+        for (ComponentAdapter<?> adapter : parent.getComponentAdapters()) {
+            if (containsScenarioAnnotations(adapter.getComponentImplementation())) {
+                steps.add(new Steps(configuration, parent.getComponent(adapter.getComponentKey())));
+            }
+        }
+        return steps.toArray(new CandidateSteps[steps.size()]);
+    }
+
+    private boolean containsScenarioAnnotations(Class<?> componentClass) {
+        for (Method method : componentClass.getMethods()) {
+            for (Annotation annotation : method.getAnnotations()) {
+                if (annotation.annotationType().getName().startsWith("org.jbehave.scenario.annotations")) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+}

Modified: trunk/core/pom.xml (1557 => 1558)

--- trunk/core/pom.xml	2010-02-06 09:44:54 UTC (rev 1557)
+++ trunk/core/pom.xml	2010-02-07 18:31:49 UTC (rev 1558)
@@ -6,11 +6,12 @@
   <version>2.5-SNAPSHOT</version>
   <name>JBehave</name>
   <inceptionYear>2003</inceptionYear>
-  <description />
+  <description>JBehave is a project that supports and facilitates Behaviour-Driven Development.</description>
   <url>http://jbehave.org</url>
 
   <modules>
     <module>jbehave-core</module>
+    <module>jbehave-pico</module>
     <module>jbehave-ant</module>
     <module>jbehave-maven-plugin</module>
   </modules>


To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to