[cucumber-jvm] Sharing context between steps in multiple objects

7,545 views
Skip to first unread message

Arnaud Bailly

unread,
Oct 6, 2011, 4:47:25 AM10/6/11
to cu...@googlegroups.com, frederic.d...@polyspot.com
Hello,
We have started to implement BDD using cucumber-jvm and we are running into a small issue which might be due to our lack of understanding on how cucumber is supposed to be used and run.

Basically, what we want to do is sharing steps across features, along with the state that is needed for each step to work properly.

Here is a (contrived) example:

A first feature goes like this:

Feature:
 In order to frobnicate
 ...

 Scenario: user can retrieve some data from server
   Given server is started
   And server stores data 42 at address foo
   When user asks for foo
   Then user gets 42


A second feature then:
Feature:
 In order to
 ...

 Scenario: user is notified
   Given server is started
   And server stores data 42 at address foo
   When user1 changes foo to 43
   And user2 asks for foo
   Then user2 gets 43

Here, we would like to share the "server ..." steps defined in class A  with "changes ..." steps defined in class B, along with the underlying server object that we connect to. Our implementation is in java and here the steps are correctly found across two classes but of course two instances are created, one A and one B and no sharing occurs between the two.

I vaguely suspect this might go against cucumber spirit yet this seems a pretty common use case : sharing some state across steps.

Thanks for helping,

Arnaud

aslak hellesoy

unread,
Oct 6, 2011, 5:09:34 AM10/6/11
to cu...@googlegroups.com, frederic.d...@polyspot.com
On Thu, Oct 6, 2011 at 9:47 AM, Arnaud Bailly <arnaud...@gmail.com> wrote:
Hello,
We have started to implement BDD using cucumber-jvm and we are running into a small issue which might be due to our lack of understanding on how cucumber is supposed to be used and run.

Basically, what we want to do is sharing steps

I'm assuming you mean step definitions (java) and not steps (gherkin)
 
across features, along with the state that is needed for each step to work properly.

Here is a (contrived) example:

A first feature goes like this:

Feature:
 In order to frobnicate
 ...

 Scenario: user can retrieve some data from server
   Given server is started
   And server stores data 42 at address foo
   When user asks for foo
   Then user gets 42


A second feature then:
Feature:
 In order to
 ...

 Scenario: user is notified
   Given server is started
   And server stores data 42 at address foo
   When user1 changes foo to 43
   And user2 asks for foo
   Then user2 gets 43

Here, we would like to share the "server ..." steps defined in class A  with "changes ..." steps defined in class B, along with the underlying server object that we connect to. Our implementation is in java and here the steps are correctly found across two classes but of course two instances are created, one A and one B and no sharing occurs between the two.


Cucumber-JVM uses a DI container to instantiate step definition classes. This means you can inject stepdef instance A insto stepdef instance B. You can also inject non-stepdef classes (app classes or test helper classes). For example:

// test scope classes

public class StepDefsA {
    public(StepDefsB b, AHelper h) {}
}

public class StepDefsB {
    public(AHelper h, MyApp app) {}
}

public class AHelper {
    public int sharedState;
}

// app scope classes

public class MyApp {
}

I vaguely suspect this might go against cucumber spirit yet this seems a pretty common use case : sharing some state across steps.


It's not against the spirit.

Aslak
 
Thanks for helping,

Arnaud

--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cu...@googlegroups.com.
To unsubscribe from this group, send email to cukes+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.

Arnaud Bailly

unread,
Oct 6, 2011, 5:29:41 AM10/6/11
to cu...@googlegroups.com, frederic.d...@polyspot.com

Cucumber-JVM uses a DI container to instantiate step definition classes. This means you can inject stepdef instance A insto stepdef instance B. You can also inject non-stepdef classes (app classes or test helper classes). For example:

// test scope classes

public class StepDefsA {
    public(StepDefsB b, AHelper h) {}
}

public class StepDefsB {
    public(AHelper h, MyApp app) {}
}

public class AHelper {
    public int sharedState;
}

// app scope classes

public class MyApp {
}

That's very interesting. IIUC, this means we can use any cucumber-DIFramework configuration to control the construction of the steps tree ?


I vaguely suspect this might go against cucumber spirit yet this seems a pretty common use case : sharing some state across steps.


It's not against the spirit.


Great! Love to live in harmony with the universe :-)


Thanks for your help,
Arnaud

aslak hellesoy

unread,
Oct 6, 2011, 5:47:56 AM10/6/11
to cu...@googlegroups.com, frederic.d...@polyspot.com
On Thu, Oct 6, 2011 at 10:29 AM, Arnaud Bailly <arnaud...@gmail.com> wrote:

Cucumber-JVM uses a DI container to instantiate step definition classes. This means you can inject stepdef instance A insto stepdef instance B. You can also inject non-stepdef classes (app classes or test helper classes). For example:

// test scope classes

public class StepDefsA {
    public(StepDefsB b, AHelper h) {}
}

public class StepDefsB {
    public(AHelper h, MyApp app) {}
}

public class AHelper {
    public int sharedState;
}

// app scope classes

public class MyApp {
}

That's very interesting. IIUC, this means we can use any cucumber-DIFramework configuration to control the construction of the steps tree ?

Yes.

Allow me to be a little pedantic about terminology. "steps" is what you will find in gherkin source. "step definitions" is what you will find in programming language source - mapping a regexp to a piece of code.

If we all use these terms appropriately there will be less confusion in our conversations.

Aslak

aslak hellesoy

unread,
Sep 3, 2012, 6:13:45 AM9/3/12
to cu...@googlegroups.com
On Mon, Sep 3, 2012 at 11:06 AM, bond_007 <agile...@gmail.com> wrote:
> Can you please give more details on sharing step definition.

Avoid feature-coupled step definitions:
https://github.com/cucumber/cucumber/wiki/Feature-Coupled-Step-Definitions-(Antipattern)

> Did you mean to
> include only 'public' without method name
>
> I had similar problem where steps are common between two features file. For
> me it says "Duplicate step definitions" error

What part of the error message is unclear to you?

Aslak

> Following are the details
> ------------------------
> When I run the command
> mvn -e -Dtest=DeleteRecordTest clean test
> I get the following
> Tests in error:
> initializationError(com.company_name.projectname.test.DeleteRecordTest):
> Duplicate step definitions in
> com.company_name.projectname.steps.DeleteRecordStepdefs.i_am_on_the_home_page()
> in file:/C:/workspace/project-name/target/test-classes/ and
> com.company_name.projectname.steps.AddRecordTestStepdefs.i_am_on_the_home_page()
> in file:/C:/workspace/project-name/target/test-classes/
>
>
> Two different Features definitions
>
> addRecord.feature
> Feature: add a record
> As a user I want to add items from home page
>
> Scenario: add item
> Given I am on the home page
> When I click the add items in the home page
> Then the added item should be added to the list
> deleterecord.feature
> Feature: add a record
> As a user I want to delete items from home page
>
> Scenario: add item
> Given I am on the home page
> When I click the delete items in the home page
> Then a confirmation message should be displayed
> And the item should be removed to the list
>
>
> Package structure
> ----------------------------------
> src/main/java
> com.company_name.projectname.pages
>
> src/test/resources
> com.company_name.projectname.cucumber
> addRecord.feature
> deleteRecord.feature
>
> src/test/java
> com.company_name.projectname.steps
> AddRecordStepdefs.java
> DeleteRecordStepdefs.java
> com.company_name.projectname.test
> AddRecordTest.java
> DeleteRecordTest.java
>
>
>
>
> ----------------------------------------------------
> Test details
> ---------------
> DeleteRecordTest.java
> ====================
> @RunWith(Cucumber.class)
> @Cucumber.Options(
> features =
> "classpath:com/company_name/projectname/cucumber/deleteRecord.feature",
> glue = {"com.company_name.projectname.steps"},
> format={"pretty", "html:target/cucumber"}
> )
> public class DeleteRecordTest {
>
> }
>
> ---------------
> AddRecordTest.java
> ====================
> @RunWith(Cucumber.class)
> @Cucumber.Options(
> features =
> "classpath:com/company_name/projectname/cucumber/addRecord.feature",
> glue = {"com.company_name.projectname.steps"},
> format={"pretty", "html:target/cucumber"}
> )
> public class AddRecordTest {
> --
> -- Rules --
>
> 1) Please prefix the subject with [Ruby], [JVM] or [JS].
> 2) Please use interleaved answers
> http://en.wikipedia.org/wiki/Posting_style#Interleaved_style
> 3) If you have a question, don't reply to an existing message. Start a new
> topic instead.
>
> You received this message because you are subscribed to the Google Groups
> Cukes group. To post to this group, send email to cu...@googlegroups.com. To
> unsubscribe from this group, send email to
> cukes+un...@googlegroups.com. For more options, visit this group at
> https://groups.google.com/d/forum/cukes?hl=en
>
>

Akinsowon Peter-Thomas

unread,
Mar 10, 2017, 6:36:46 AM3/10/17
to Cukes
Hi Aslak, Was the last question moved to a new topic? I have a similar problem getting the "Duplicate step definitions" error. I created seperate step definitions but used the same Classes in both with a few different variables.
Reply all
Reply to author
Forward
0 new messages