4

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
{

}
PDStat
  • 783
  • 1
  • 6
  • 9

2 Answers2

4

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.

Lunivore
  • 4,232
  • 1
  • 18
  • 23
2

I believe you've misunderstood a fundamental concept. Behavior Driven Development is not unit testing. If you're waiting until after you've written your code before you create your feature file, you're doing it wrong. The benefit BDD provides is that you get your business partner to tell you how they will evaluate whether or not the code meets their requirements before you start coding. And this is expressed as the scenarios in the feature file. Your non-technical business partner should be able to read the scenarios and understand exactly what is being tested. (In fact, if you're really doing it right, the business are writing the feature files as a result of the three amigos meeting.) You should still be unit testing as you code. BDD = does the application perform the way the business expects it to. Unit Testing = does the code perform the way the developer expects it to. There is a subtle but incredibly important difference between those two.

user186326
  • 31
  • 1
  • 1
    This is a rather large wall of text you have. Could you [edit] it so that it is broken up a bit into easier to read pieces? –  Jul 07 '15 at 13:06
  • BDD actually started as a way of looking at the behaviour of classes, rather than systems; JBehave (the first BDD tool) was originally a replacement for JUnit. – Lunivore Jul 16 '15 at 10:49
  • Actually, JBehave is explicitly a Java port of a Ruby tool, so can't be the first. And it works with junit rather than replacing it. – soru Jul 16 '15 at 13:25
  • 1
    @Soru Dan North created JBehave back in 2004. He ported it to Ruby, which became RBehave, which became RSpec's story runner, which became Cucumber. And originally it was a replacement for JUnit. I know this because I helped him write JBehave 1.0 and the core of JBehave 2.0. Dan's introductory post also talks explicitly about how he started BDD as a replacement for TDD, and the use of the word "should" instead of "test": http://dannorth.net/introducing-bdd/ – Lunivore Jul 18 '15 at 08:26
  • @Soru I wrote a bit more about the move from class-level examples to system-level scenarios, and Chris Matts' involvement, here: http://lizkeogh.com/2011/06/27/atdd-vs-bdd-and-a-potted-history-of-some-related-stuff/ - please pass this on to whoever gave you your version of history. – Lunivore Jul 18 '15 at 08:34
  • I have to admit, I wasn't aware of the pre-ruby history of jbehave. However, I think that early jbehave is a completely different use case than the current jbehave 2. It was a BDD developer testing tool replacing junit, now it's an ATDD analyst tool that not really best suited for developer testing. For at least some types of software, you still need a unit test tool to find and guard against bugs without customer interaction. – soru Jul 18 '15 at 10:57
  • @Soru Agreed, but you can still do BDD at a unit level, exploring the behaviour of classes and methods instead of systems. We took the capability out of JBehave 2 because it was possible and easier with JUnit. Here's an NUnit example, showing the Given / When / Then in comments: https://github.com/lunivore/WiPFlash/blob/master/WiPFlash.Behavior/Framework/WaiterBehaviour.cs – Lunivore Jul 20 '15 at 11:35