Ivan's Brain Dump




read

The purpose of this post is to explain how to write BDD acceptance tests in Java using the gherkin syntax, run those with JUnit and implement them using Web Browser automation.

Before I begin let me assure you that I haven’t left the .NET church for the Java one and while I really don’t enjoy writing in Java and using Eclipse sometimes a man has to do what a man has to do.

So yeah I spend an afternoon trying to figure out the state of BDD (Behavior Driven Development) tools for Java and it’s pretty poor so far. If you want to write gherkin syntax based behavioral specifications, which are executable inside Eclipse as JUnit tests you are stuck only with JBehave. JBehave however is a monster with poor documentation, not so easily discoverable fluent API and little to none third party documentation content on forums and sites. BTW don’t get fooled like me – insetad of getting the core package you want to get the Web package because the latter has all the .jar dependencies bundled unlike the first one. Enough bashing, lets get down to business.

Let’s say we have the following “Search” story and a more specific scenario – “display an error dialog if I don’t fill in the search form”:

Narrative: I should be able to search

Scenario: I should see an error if I try to search without filling in the search form fields.

When I open 'http://mysite.com'
When I click on the 'Search' button
Then I should see an error

First thing you will notice is that JBehave doesn’t support the “And” keyword so we can’t wring “When I open … AND I click on the Seach button”.

Similar to other gherkin/cucumber based frameworks JBehave allows us to implement each step of the scenario as a method in a class, which optionally takes parameters mapped to words from the scenario. The above one can be stubbed like bellow. Also not that if properly configured you can make JBehave junit runner spit out the stubs for you to copy paste in your code (more about that later):

public class Search
{
	@When("I open '$page'")
	public void whenIOpen(String page)
	{
		// TODO
	}

	@When("I click on the '$buttonText' button")
	public void whenIClickOnTheButton(String buttonText)
	{
		// TODO
	}

	@Then("I should see an error")
	public void thenIShouldSeeAnError(){
		// TODO
	}
}

To implement the browser automation in Java there exist a Java variant of the Ruby watir library (and the .NET Watin library) called … surprise… watiJ. It’s available here. Major pitfall with it though is that it actually embeds the IE COM component and mozilla’s ghecko engine instead launching the real IE/Firefox (like the above mentioned framework do) and it only supports IE6 and I saw some C++ runtime problems with the ghecko engine. Nevertheless to give you a feel of how the above tests can be implemented:

public class Search extends StoryBase {

	@When("I open '$page'")
	public void whenIOpen(String page)
	{
		WebBrowser.open(page).pauseUntilReady();
	}

	@When("I click on the '$buttonText' button")
	public void whenIClickOnTheButton(String buttonText)
	{
		Tag button = WebBrowser.find.button().with.name("search");
		assertNotNull(button);
		button.click().pauseUntilReady();
	}

	@Then("I should see an error")
	public void thenIShouldSeeAnError(){
		Tag errorDialogTitleDiv = WebBrowser.find.span().with.className("dijitDialogTitle");
		assertNotNull(errorDialogTitleDiv);
		assertEquals("Error", errorDialogTitleDiv.get.innerHTML());
	}
}

Now, how about running them? A few things before that:

  • JBehave expects you to save stories as .story files in your source code tree
  • JBehave expects you to implement and configure problematically a *JUnitStory *for each story, so that it’s runnable through JUnit.
  • It will take your JUnitStory subclass implementation – for example “HelloWorldStory extends JUnitStory” *and look for the plain text file hello_world_story.story*

To save myself from having to configure each story  I present you my *StoryBase *base class, which:

  • Initializes WatiJ and exposes it to subclasses
  • Configures JBehave to look for the .story files in the same directory as the class.
  • Configures JBehave/JUnit to look for the steps test methods of a story scenario in the subclass.
  • Configures JBehave to print out detailed information in the Console whilst running (such as the method stubs if any are missing)
  • Configures JBehave to spit out HTML report in myproject/target/jbehave-report/

Here it is:

public abstract class StoryBase extends JUnitStory {
    protected final static WebSpec WebBrowser = new WebSpec().ie();

    @Override
    public Configuration configuration() {
        return new MostUsefulConfiguration()
            .useStoryLoader(new LoadFromClasspath(this.getClass().getClassLoader()))
    	    .useStoryReporterBuilder(
    	    		new StoryReporterBuilder()
    	    			.withDefaultFormats()
    	    			.withFormats(Format.HTML, Format.CONSOLE)
    	    			.withRelativeDirectory("jbehave-report")
			);
    }

    @Override
    public List candidateSteps() {
        return new InstanceStepsFactory(configuration(), this).createCandidateSteps();
    }
}

Then all that’s left is to make the Search class extend the StoryBase class and it is now runnable in JUnit inside and outside Eclipse.

public class Search extends StoryBase {
}


 

Blog Logo

Ivan Zlatev


Published

Image

Ivan's Brain Dump

Back to Overview