BDD – Best Practices for BDD and Cucumber in Java

bddcucumberjavaseleniumunit testing

I'm trying to understand some best practices when it comes to BDD and Cucumber. I've only recently started to use it,
and the first feature I have written a test for is testing a search feature, more specifically how a Repository layer
integrates with a JPA EntityManager that has been injected using the @PersistenceContext annotation. It does this by
creating an EJBContainer using the GlassFish embedded maven dependency and initialising the persistence layer this way.
It works so I'm fairly happy with that.

Now I'm at the stage where I want to start using Selenium with Cucumber to test the search feature of the JSF page. Which
I'm assuming I'll be able to check the contents of a HTML table after the search has been submitted.

Is it possible to use the same feature file with a different steps class that does Selenium testing? Is this a good practice?
At the moment none of this Cucumber stuff feels like unit testing, it all feels like Integration testing!

What I have in mind is something like the following organisation

test
    |
    java
    |   |
    |   feature
    |       |
    |       web
    |       |  |
    |       |  user
    |       |      UserSearchWebSteps
    |       |      UserAddWebSteps
    |       |      UserDeleteWebSteps
    |       |      UserWebTest
    |       db
    |          |
    |          user
    |              UserSearchDBSteps
    |              UserAddDBSteps
    |              UserDeleteDBSteps
    |              UserDBTest
    resources
        |
        feature
            |
            user
                search_users.feature
                add_user.feature
                delete_user.feature

So the steps would be organised at the level of web or db, and then in this example each user step is under that. With
a corresponding runner test class that runs all those steps

And as both the web and db levels expect the same results I'd have shared feature files.

The UserXXXTest would then specify in it's cucumber options where to find the feature file, and because the steps for web
and db are separated at the pacakge level having a step method with the same regexp shouldn't be an issue.

@RunWith(Cucumber.class)
@CucumberOptions(features =
{
    "src/test/resources/feature/user"
})
public class UserDBTest
{

}

Best Answer

Traditionally in BDD we'd start with the outside and move in, so we'd have a web page, then from there move to the actual DB connections until the scenario worked with the web page.

However, your question about whether you can use the same feature file with different steps at different levels is appropriate and applicable.

I don't think at the moment that Cucumber actually does this. Behat for PHP does. Konstantin Kudryashov's post on how to model the domain using the same end-to-end scenarios that work through the web layer may give you some ideas about how to do this kind of thing well (short version: remember to make your scenarios declarative!)

If you wanted to do it in Cucumber, I think it might be possible if you used symbolic links to mirror the feature files that you wanted to run in both places? You'll need some jiggery-pokery to get it to work. But... the theory is very sound, and Konstantin who's a well-respected BDD community member has been exploring this space for a while.

Even at lower levels, though, it wouldn't be a unit test, but an integration test.

It is possible to use BDD at a unit level (it started there, after all) but you'd probably want to use something like RSpec rather than the heavier-weight system-level frameworks.