Tuesday, December 15, 2009

Breaking the JBehave Inheritance Hierarchy

JBehave is a great framework for behavior driven development (BDD) under Java that relies on implementing a base Scenario class to create JBehave tests.  This causes JBehave tests to become awkward within JUnit 3 or any other test framework that requires its own inheritance hierarchy.  There is a tendency in Java for frameworks to avoid extension opting instead for the use of annotations or delegation.  Here, I have created a simple class with two constructors and a single method for use in test.
  • The constructor that takes a class will follow the JBehave documentation on UnderscoredCamelCaseResolver which locates the test file in the same folder as the class passed in and with a name following the documented rules.
  • The constructor that takes a String will locate the test file at the location specified.
  • runScenario() will resolve all of the steps in the given step file and run them - calling the "given", "when", and "then" functionality in the provided Step class (given in the constructor).
  • setPendingErrorStrategy() allows you to switch between failing and passing when errors (such as incomplete tests) are encountered.

public class JbehaveIntegrationDelegate{ private final Steps candidateSteps; private final ScenarioNameResolver scenarioNameResolver; private PendingErrorStrategy pendingErrorStrategy = PendingErrorStrategy.FAILING; public JbehaveIntegrationDelegate(Steps candidateSteps, final Class className){ this.candidateSteps = candidateSteps; scenarioNameResolver = new UnderscoredCamelCaseResolver(){ @Override protected String resolveFileName( Class scenarioClass) { return super.resolveFileName(className); } }; } public JbehaveIntegrationDelegate(Steps candidateSteps, final String testFileName){ this.candidateSteps = candidateSteps; scenarioNameResolver = new ScenarioNameResolver(){ @Override public String resolve(Class arg0) { return testFileName; } }; } public void runScenario() throws Throwable { JBehaveScenario scenario = new JBehaveScenario(candidateSteps, scenarioNameResolver, pendingErrorStrategy); scenario.runScenario(); } public void setPendingErrorStrategy(PendingErrorStrategy strategy){ this.pendingErrorStrategy=strategy; } class JBehaveScenario extends Scenario { public JBehaveScenario( Steps candidateSteps, final ScenarioNameResolver scenarioNameResolver, final PendingErrorStrategy pendingErrorStrategy) { super(new PropertyBasedConfiguration() { @Override public ScenarioDefiner forDefiningScenarios() { return new ClasspathScenarioDefiner( scenarioNameResolver, new PatternScenarioParser(this)); } @Override public PendingErrorStrategy forPendingSteps() { return pendingErrorStrategy; } }, candidateSteps); } } }

No comments:

Post a Comment


Bookmark and Share