Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cucumber-JVM considers all (@Given, @When, @Then) annotations to be interchangeable

It has come (quite brutally) to my attention that with cucumber-JVM, when you define features whose steps have seemingly identical names they are considered interchangeable.

Given

Feature: Grab that cash with both hands and make a stash

  Scenario: Spend it
    Given Jack has 5 dollars
    When  Jack wants to buy Lear Jet
    Then  He doesn't have enough cash

  Scenario: acquire it
    Given Jack is broke
    But   his wealth is slowly growing
    When  Jack has 5 dollars
    Then  He can afford a pack of gum

  Scenario: own it
    Given Jack is broke
    But   he has a job that's paid 5 dollar an hour
    When  He works an hour
    Then  Jack has 5 dollars
@Given("^Jack has 5 dollars$")
public void set_it() throws Throwable {
    this.jack = new Person();
    jack.setCashAmount(5);
}

@When("^Jack has 5 dollars$")
public void wait_it() throws Throwable {
    jack.waitFor(wealth(is(equalTo(5))));
}

@Then("^Jack has 5 dollars$")
public void check_it() throws Throwable {
    assertThat("Jack should have 5 dollars by now",
               jack.getCashAmount(),
               is(equalTo(5)));
}

When

I run this feature with cucumber (with mvn/intelliJ plugin/eclipse plugin/magical crystal ball/other ridiculous medium)

Then

I get the following message :

cucumber.runtime.DuplicateStepDefinitionException: Duplicate step definitions in my.project.MySteps.wait_it() in file:[...] and my.project.MySteps.set_it() in file:[...]
    at cucumber.runtime.RuntimeGlue.addStepDefinition(RuntimeGlue.java:33)
    at cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:151)
    at cucumber.runtime.java.MethodScanner.scan(MethodScanner.java:68)
    at cucumber.runtime.java.MethodScanner.scan(MethodScanner.java:41)
    at cucumber.runtime.java.JavaBackend.loadGlue(JavaBackend.java:86)
...

And a bunch of other irrelevant line from which I'll spare you.

Diagnostic

Cucumber does not seem to make a difference between @Given("a"), @When("a") and @Then("a") (and @And and @But which I don't really know what they were intended for in the first place since those are just syntactic sugar for "same as what I just did")

But as implementation suggest, those 3 steps are profoundly different from one another. Each sentence is properly describing what the test should do, and implementation that ensues is univocal.

  • A "Given" step should setup the test pre-conditions
  • A "When" step should trigger an action or await one
  • A "Then" step should assert a state of the system afterward.

What am I missing there?

Is there a way to tell Cucumber how to rely not only on regexp but also on step types (which, to me, should be the default behavior)?

like image 226
Ar3s Avatar asked Sep 09 '15 16:09

Ar3s


People also ask

Does Cucumber JVM support global hook?

Almost all BDD automation frameworks have some sort of hooks that run before and after scenarios. However, not all frameworks have global hooks that run once at the beginning or end of a suite of scenarios – and Cucumber-JVM is one of these unlucky few.

What are annotations in Cucumber?

Annotation is a predefined text, which holds a specific meaning. It lets the compiler/interpreter know, what should be done upon execution. Cucumber has got the following few annotations − Given − It describes the pre-requisite for the test to be executed.

What is difference between given when and then in Cucumber?

Describe an initial context ( Given steps) Describe an event ( When steps) Describe an expected outcome ( Then steps)


1 Answers

Yes, this is how it is supposed to work. The step name by itself should be clear enough to see whether it is about test setup (Given), some action (When) or verifying the outcome (Then).

The action step can usually be worded so it contains a verb, for distinguishing setup and assertions I agree that it is sometimes quite difficult. You would have to come up with your own conventions here, one possibility could be the following:

Given Jack is broke
 When Jack earns 5 dollars
 Then Jack should have 5 dollars
like image 133
Jörn Horstmann Avatar answered Oct 07 '22 00:10

Jörn Horstmann