Search code examples
javaannotationsbddcucumber-jvm

Why isn't @Given repeatable?


I am all new to Cucumber(jvm) and it all seems fine and dandy but :

I don't really know how to have multiple initial conditions (from various scenarios) written in various ways (elegantly) be implemented by a single method.

eg :

Scenario: I really am bad
    Given I really am inexperienced with Cucumber
    When I try to work
    Then what I produce is of poor quality

Scenario: I am on the way to become good (hopefully)
    Given I am a noob
    When I learn new things
    And I practice
    Then my level improves

Since Given I really am inexperienced with Cucumber and Given I am a cuke noob (although not semantically identical) are close enough for me to be implemented in the exact same way, I would like to be able to link them to the same method but

@Given("^I really am inexperienced with Cucumber$")
@Given("^I am a cuke noob$")
public void checkMyLevelIsGenerallyLow() throws Throwable {
    // some very clever code to assess then confirm my mediocre level ... something like if(true) ...
}

But the code presented here-above won't compile as the cucumber.api.java.en.@Given annotation is not java.lang.annotation.@Repeatable ...

one simple solution would be to do something like

public void checkMyLevelIsGenerallyLow() throws Throwable {
    // some very clever code to assess then confirm my mediocre level ... something like if(true) ...
}

@Given("^I really am inexperienced with Cucumber$")
public void check_I_really_am_inexperienced_with_Cucumber() throws Throwable {
    checkMyLevelIsGenerallyLow();
}

@Given("^I am a cuke noob$")
public void check_I_am_a_cuke_noob() throws Throwable {
    checkMyLevelIsGenerallyLow();
}

which would work just fine but would require lots of code for simple things and I am pretty sure there are other ways.

Or even, as I asked myself writing down this question, "Am I simply approaching this question from the right side ?", is what I am trying to acheive even a good idea in terms of BDD ?

I think it's not all bad since gherkin is supposed to hold the semantic and sentence construction and vocabulary choices are contexte (hence scenario) dependent. Yet I should be free of implementing it in whatever way I like.

So to wrap it all up :

  • Should @Given be @Repeatable ?
    • If so, why isn't it ? Is there another way around ?
    • If not, what am I missing in terms of approach ?

Solution

  • Regarding multi-expressive @given

    It might not be the nicest way to do it but scratching my head I thought of that :

    @Given("^I really am inexperienced with Cucumber$|^I am a cuke noob$")
    public void checkMyLevelIsGenerallyLow() throws Throwable {
        // some very clever code to assess then confirm my mediocre level ... something like if(true) ...
    }
    

    And it works ! It is exactly what I was looking for and can even be made a bit more readable like this :

    @Given("^I really am inexperienced with Cucumber$"+
          "|^I am a cuke noob$")
    

    Regarding the non-repeatability @given

    as blalasaadri stated @Given may be @Repeatable but only from Java8 and further since @Repeatable was introduced in Java8.

    Special thanks

    To Ceiling Gecko who made me remember that the simplest and most obvious solutions are usually the best and most elegant.