The default application generated by Play has examples of unit and integration tests, however it does not demonstrate how to integrate in any Behaviour Driven Development (BDD) frameworks. The value of a BDD framework like Cucumber is extremely high when attempting to achieve strong collaboration between various stakeholders like Developers and Business Analysts. This post will show you how to get up and running with Cucumber and Play.
Assuming you have already setup a vanilla Play application already, the first thing you need to do is add the dependencies for Cucumber. Go to your build.sbt file and add in the dependencies for Cucumber. In this post, we will be using cucumber-jvm, along with the cucumber-junit launcher.
Let’s create a directory to contain our feature files. I generally put my features in a features directory in the root of my application.
For this directory to be picked up, we need to add it into the classpath when running tests. This is a change we need to make to the build.sbt file.
To keep everything simple, let’s create a very basic feature file. All this will do is go to the landing page and assert the title of the page is equal to the text “Cucumber”.
Create a file features/example.feature containing the following contents.
To get this running, we need a class that is annotated with the Cucumber JUnit runner annotation. So create a class called test/RunCucumber.java with the following contents. The “pretty” flag is optional, but I much prefer that output.
Now let’s checkpoint what we have done so far. If everything is working, we should be able to run Cucumber and it should complain that we are missing step definitions.
To get the scenario to pass, we need to first put a startup hook in place to initialize our server and test browser. Cucumber does provide a @Before hook but this is executed before each and every scenario. We only want to initialize our server and browser once before the very first scenario, so we need to add some state to manage this ourselves.Create a test/GlobalHooks.java class and add the following contents.
There’s also no shutdown hook in Cucumber, so we need to add the clean up of the server and browser into the JVM shutdown hook.
Now we should be able to implement our steps. So create a test/Steps.java file. For the moment, we will just statically reference our TEST_BROWSER. There is a better way to inject this dependency in, which I will cover later.
We should now be in a position to rerun this. The steps should be found, however the title of the page will not be “Cucumber” resulting in a failure.
Let’s correct the title of the page and rerun the test.Navigate to app/views/index.scala.html. Update the title of the page to be “Cucumber”
- Rerun the test and it should succeed.
- The last series of changes will be around integrating with Guice so we can inject our dependencies into the Steps. This will remove the need to directly reference the test browser.Go back into the build.sbt file and add the dependencies for guice as well as cucumber-guice, which provides the binding for guice into cucumber.
- Define a test/CucumberModule.java class which will setup our bindings.
Now change test/GlobalHooks.java to be dependency injected.
Change test/Steps.java to be dependency injected.
- Lastly add a features.cucumber-guice.properties file to refer to our module. So this file should have the following contents.
- Now if we rerun everything, then the test should still pass which will prove that everything has been setup correctly.