11

I'm trying to use BDD in a very simple way, in order to minimize the amount of Java code. I want to create exactly two files, one is my story:

Given user is named "John Doe" 
And user is authenticated
When user changes his password to "a1b2c3"
Then user password equals to "a1b2c3"

Next, I create a Java class:

public class UserManipulator {
  @Given("$user is named $name")
  public User shouldExistOrBeCreated(String name) {
    User user = //...
    return user;
  }
  @Given("$user is authenticated")
  public void shouldBeLoggedIn() {
    // ...
  }
  @When("$user changes his password to $pwd")
  public void shouldChangePassword(User user, String pwd) {
    // ...
  }
  @Then("$user password equals to $pwd")
  public void shouldHaveThisPassword(User user, String pwd) {
    assertEquals(user.getPassword(), pwd);
  }
}

And that's it. I don't want to have any more files, any more unit tests. I want some BDD-framework to find my story file, parse all my Java files, and run them one by one. Is it possible to achieve?

ps. What is important here is a possible reuse of Java methods in my other stories. For example, this is the story no.2:

Given user is named "Michael Doe"   <-- reuse
When user adds $100.00 to his account
Then user account balance is $100.00
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
yegor256
  • 102,010
  • 123
  • 446
  • 597
  • I think this is an excellent idea, so I spent a bit of time to create some mock code. Would this be something you'd be willing to use or is this "too complex"? -> http://pastie.org/1210819 This mock code doesn't match exactly with what you've provided/asked but it got me thinking... – Esko Oct 10 '10 at 08:17
  • @Esko The code you created is nice, but again the idea is to separate BDD stories from Java code entirely. Stories are in plan text, and Java classes are providers of behavioral steps... – yegor256 Oct 10 '10 at 16:29
  • I think you can revisit JBehave now. You have to write one Java class that extends JUnitStories. You then define where it should look for story files via paths, and define the step classes as well. So it doesn't do everything, but it's one file for all stories/steps. Not likely you'll get much better than that... – Mikezx6r Jan 27 '11 at 02:52

9 Answers9

5

You want to have a look at:

Also, this presentation on BDD in Java and Groovy could be of interest.

haylem
  • 22,460
  • 3
  • 67
  • 96
  • @haylem JBehave doesn't allow such an approach. I have to create an instance of JUnitStory class for every story. Which is an overhead, as I see it... – yegor256 Oct 08 '10 at 12:30
  • @Vincenzo: Sorry, I didn't understand your requirement like that. I'm actually not sure I understand. You want a framework to extrapolate and run the test from this story and this Java class over all the Java files of your project? I don't see how that's useful. – haylem Oct 08 '10 at 12:34
  • @haylem The story itself has enough information about what I want to test and how (my scenario). I don't see why I would need to create any other classes on top of it. But in JBehave I have to create them and they are rather complex and error prone.. That's why I'm trying to find a framework which will do all this work for me, maybe on top of JBehave, why not... – yegor256 Oct 08 '10 at 12:38
  • @Vincenzo: have a look at easyb. The syntax is even more lightweight, as it uses groovy. – haylem Oct 08 '10 at 12:41
  • @haylem I just reviewed their presentation, thanks. Easyb is just another mechanism of unit test writing. Yes, it is more lightweight than Java+JUnit, but it's still not what I'm looking for. I want to enable my stories to **reuse** Java constructs, catching them just by RegEx patterns.. I will update the question now to explain better. – yegor256 Oct 08 '10 at 12:48
  • @Vincenzo: OK I understand your idea now. Unfortunately, I don't know of any tools to do that. It seems like a good idea but I don't think there's a widely accepted tool for this use case. – haylem Oct 08 '10 at 13:25
  • @haylem Maybe they just don't exist. Anyway, thanks for your response, I already up-voted it. If there won't be any more answers to my question, I will approve yours. – yegor256 Oct 08 '10 at 17:04
  • @Vincenzo: Thanks for the upvote. Regarding accepting the answer, I honestly don't know what the right thing to do is in that case, as it's not exactly an answer to your question. – haylem Oct 08 '10 at 17:20
  • Specatular development is stopped since 2010 as of 2015 May. – Joel Handwell May 15 '15 at 02:01
5

We use Cucumber, which is a Ruby framework but by bundling JRuby into your project you can easily access your Java objects. It does mean you write your step definitions in Ruby, but it also minimises the amount of Java you write :)

The story format in Cucumber is exactly as you describe in your example, and re-use of story lines is trivial.

Nick
  • 11,475
  • 1
  • 36
  • 47
  • You don't have any more JUnit tests, right? All you have is `.feature` files and JRuby code. Am I correct? – yegor256 Oct 11 '10 at 09:37
  • For our specs, yeah. We fire up Cucumber directly from our Ant build, and don't need to create a Java class for each test or anything like that. – Nick Oct 11 '10 at 15:18
5

The robotframework may be of interest. You can read the details in the user guide here: http://robotframework.googlecode.com/svn/tags/robotframework-2.5.4/doc/userguide/RobotFrameworkUserGuide.html#behavior-driven-style

Robotframework is written in python and new keywords can be implemented in python or jython.

There is also a thesis on the use of RF for ATDD here: http://www.niksula.cs.hut.fi/~jprantan/thesis/thesis_juha_rantanen.pdf

Mark Irvine
  • 1,349
  • 14
  • 24
4

In newer versions of JBehave, you can use the JUnitStories class, which lets one Java class act as the runner for multiple plain text stories. Would this do what you need?

Moss Collum
  • 3,542
  • 3
  • 25
  • 23
3

Not really what you are looking for, but you may want to have a look at Spock.

Justin Muller
  • 1,283
  • 13
  • 21
2

Cucumber JVM is exactly what you are looking for. Simple steps that can be reused, works transparently with JUnit, integrates well with Spring (and many others). The only one additional file that has to be added is a class annotated with @RunWith(Cucumber.class) - one class no matter how many tests and steps you have.

Maciej Walkowiak
  • 12,372
  • 59
  • 63
2

jBehave or Cucumber can be used. Both of them are good.

For jbehave you can visit: http://jbehave.org/

I am using jBehave now. I know very little about Cucumber. I studied little about "Cucumber-JVM".

Guess, both of them are nice

Ripon Al Wasim
  • 36,924
  • 42
  • 155
  • 176
2

I don't think it provides the level of reuse you're looking for but also have a look at Concordion, a BDD framework similar to Fitnesse but much easier to use (specifications are written in plain text, in the form of HTML pages). And it integrates just directly with JUnit and thus also with Maven.

See also

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
1

You could have a look at JGiven. Instead of a text file for your scenario you would write a JUnit test like this:

public class UserManipulatorTest 
       extends ScenarioTest<GivenUser, WhenPasswordChange, ThenUser> {

   @Test
   public void user_can_change_his_password() {
       given().user_is_named( "John Doe" )
          .and().user_is_authenticated(); 
       when().user_changes_his_password_to( "a1b2c3" );
       then().user_password_equals_to( "a1b2c3" );
   }
}

Then you write your step definitions in a so-called stage classes. Typically you have for each stage one class so that they are better reusable. So in your case I would define three stage classes:

public class GivenUser extends Stage<GivenUser> {
    @ProvidedScenarioState
    User user;

    public GivenUser user_is_named(String name) {
        user = //...
        return self();
    }

    public GivenUser user_is_authenticated() {
        // ...
        return self();
    }
}

public class WhenPasswordChange extends Stage<WhenPasswordChange> {
    @ExpectedScenarioState
    User user;

    public WhenPasswordChange user_changes_his_password_to(String pwd) {
        // ...
        return self();
    } 
}

public class ThenUser extends Stage<ThenUser> {
    @ExpectedScenarioState
    User user;

    public ThenUser user_password_equals_to(String pwd) {
        assertEquals(user.getPassword(), pwd);
        return self();
    }
}

Now you can reuse these stage classes in other scenarios. In your example you could reuse the GivenUser stage class and you would define the new stage classes WhenBalanceChange and ThenBalance:

public class BalanceTest 
    extends ScenarioTest<GivenUser, WhenBalanceChange, ThenBalance> {

    @Test
    public void user_can_add_balance_to_his_account() {
        given().user_is_named("Michael Doe");
        when().user_adds_$_to_his_account("$100.00");
        then().user_account_balance_is("$100.00");
    }
}

Note that in JGiven the $ character in a method name is a placeholder for the method argument and will be replaced by it in the generated report.

Disclaimer: I am the author of JGiven.

Jan Schaefer
  • 1,882
  • 1
  • 18
  • 23