We have three technologies JBehave for acceptance tests, Selenium for web application testing and Spring dealing with infrastructure. In this post I will talk about integrating JBehave with Selenium 2 and Spring.
For this example I have created a very simple web application using Spring MVC. I know that business logic is not accurate to the reality, but it is simple enough to illustrate how to integrate all these technologies together.
I have divided this post in three main subsections:
- Integrating JBehave with Spring. There is no web application here, only business logic.
- Integrating Spring MVC with Selenium 2. Only to show how easy is implementing automated tests with Selenium 2.
- Integrating JBehave with Selenium 2. Web application used in previous example but instead of using only Selenium for automating testing, JBehave instructs to Selenium which steps should execute.
- Integrating JBehave with Spring:
- TradingService, that defines a method for creating stocks. TradingServiceImpl is the implementation.
- Stock, that contains stock information and logic about its status.
- StockAlertStatus is Stock status Enum.
@Steps because we want Spring creates automatically this bean. TradingService is the business logic we want to test, and is injected using Autowire annotation. And finally one method for each Given, When, Then. Explained quickly, when JBehave finds an @Given, it searches into loaded stories for a phrase starting with Given. After that checks if @Given string value matches the Given definition expressed in story file. If matches then inject the story parameters as method parameters, for example STK1 as string parameter, or 5 as double threshold parameter. Moreover, in this case because we are using Examples in our story file, @Named annotation for each parameter is required. The named parameters allow the parameters to be injected using the table row values with the corresponding header name. Each parameter is converted from String to required parameter type.
We have written stories, and how to execute them (TradingServiceSteps class). JBehave requires another class, that will be responsible of configurating it. Basically you should configure Step classes and story files location, and what kind of reports are generated.
In our case, because we are integrating JBehave with Spring, some information is provided using Spring Injection.
This class is where JBehave is configured and is responsible for running all stories. Let's examine the most important lines:
In line 1 we specify a JUnit runner for running JBehave stories with Spring.
In line 2 we are configuring JBehave with Enum parameter converter, see that StockAlertStatus is an enum, because it is not a primitive parameter, a converter should be provided. JBehave comes with some convertes, but we can implement ours too.
In line 3 the embedder that we will use. This is the standard embedder for JBehave. Embedder represents an entry point to all of JBehave's functionality that is embeddable into other launchers.
And finally with @UsingSpring we are providing two Spring files, one where step classes are defined, and the other one where JBehave is configured.
This is a generic configuration file, that I use in all projects. You configure the output, the classloader for Embedder and prefix for parameters
And finally a Spring context file where all step classes are defined. And you know what, thanks of Spring this is as simple as:
No magic, remember that each Step class has an @Steps annotation? Thanks of component-scan, you don't have to define each Step class in @UsingSteps annotation or using
Now run previous class as JUnit, and reports with results are generated.
- Integrating Spring MVC with Selenium 2
Most important sections of previous JSP are:
JSP taglibs <form:input path=""/> like <form:input path="name"/> in form, and <div id="result">. These fields are important because they are used by Selenium for filling form and asserting showed status.
For example, in Selenium class:
WebElement name = driver.findElement(id("name")) returns a "reference" to <input id="name" type="text"> element and using sendKeys method, you are sending keyboard chars to that component.
WebElement element = driver.findElement(id("result")), returns a "reference" to div element and using
assertThat(element.getText(), is(StockAlertStatus.OFF.name())); getText method, none tag characters of element are returned.
Now running this test is as simple as running TraderIsAlertedSelenium class as a simple JUnit test class. When running this class a browser (Firefox in this case) will be opened, and all programmed interactions will be executed on your screen.
- Integrating JBehave with Selenium 2 and Spring
Download Full Code