Behat: Calling a "step" from another one?

Created on 5 Jun 2014  路  13Comments  路  Source: Behat/Behat

Hi guys.

I have a question related to the new Shiny Behat version :)

Sometimes, you may be in a need of calling a step from another one. Previously, it was possible to do such thing from a given step:

/**
 * @When /^I do something$/
 */
public function iDoSomething($page)
{
    return new Step\Then('I should do this too');
}

Now, this stuff does not exist anymore, at least in the way presented above. From a code point of view, it is now a matter of calling a method much more than a step, as in:

/**
 * @When /^I do something$/
 */
public function iDoSomething($page)
{
    $this->iShouldDoThisToo();
}

However, is it a matter of organizing the code? Is there a way to call a given method for a given context?

If not, what would be the best thing to do for such thing please?

I may have missed something in the doc or misunderstood a given concept... Thanks for the help guys.

Most helpful comment

I think step chaining was important and step calling was a bridge for accessing steps between contexts.

I am working on behat 2.x to 3.x migration and it is a big drawback for us that chaining and step access in not supported in shining behat 3.

Consider a situation:

  1. For custom form field library, so that library will define how to set/get values from custom fields. For this you need to write form_context and step definition.
  2. For multiple authentication plugins, you do the same. Write custom steps in different context to get user authenticated.

Now if you are testing a page, you need steps from above contexts to authenticate user and fill custom form fields.

With Step access from different contexts, it was not required for dev to search code to find out what api in which context should be used. Step definition list is enough to get them going.

Current problems:

  1. Dev has to know more about what all context api's availabl, before they can re-use it.
  2. Inter context communication is not possible #558
  3. Step chaining used to help wrap few steps which were repeated in multiple scenarios in different modules/plugins. Like login step, which includes:
    a) Expand navigation if JS
    b ) Click on login link
    c) Fill user name
    d) Fill password
    e) Press login

Will appreciate if anyone can help/guide me how this can be achieved elegantly in behat 3.
My issues are:

  1. How to call different steps from different (20+) contexts. Api calling might work, but it's not as easy as just calling new Given and not to worry about different context and not knowing which api is in which context.
  2. Chain/Combine steps for reuse (like login).

All 13 comments

IIRC just the class namespaces was renamed, so this should look like:

use Behat\Behat\Definition\Call;

/**
 * @When /^I do something$/
 */
public function iDoSomething($page)
{
    return new Call\Then('I should do this too');
}

@stloyd nope. Chained steps don't exist in Behat 3

Since it wasn't such a great idea after all, it was taken out of the core. Just use OO :)

The feature is provided as an extension tho: https://github.com/Behat/ChainedStepsExtension

@jakzal the extension does not work currently. It was working with some previous implementation of Behat 3 the beta versions) but not with the final version. And I haven't spent time on it to figure whether it can be fixed entirely now

Yept, but it's still there. If anyone feels the need he can contribute a fix.

It is not part of the core anymore and as @jakzal described there was a very good reason for that.

Let's say you have OneContext which does not extends MinkContext but MinkContext is used in the same suite as OneContext. How can you access MinkContext methods from OneContext ? It would solve the issue. Thanks.

@B2F which methods? Usually you need to access the Mink Session, in which case you need to extend the RawMinkContext class.

I think step chaining was important and step calling was a bridge for accessing steps between contexts.

I am working on behat 2.x to 3.x migration and it is a big drawback for us that chaining and step access in not supported in shining behat 3.

Consider a situation:

  1. For custom form field library, so that library will define how to set/get values from custom fields. For this you need to write form_context and step definition.
  2. For multiple authentication plugins, you do the same. Write custom steps in different context to get user authenticated.

Now if you are testing a page, you need steps from above contexts to authenticate user and fill custom form fields.

With Step access from different contexts, it was not required for dev to search code to find out what api in which context should be used. Step definition list is enough to get them going.

Current problems:

  1. Dev has to know more about what all context api's availabl, before they can re-use it.
  2. Inter context communication is not possible #558
  3. Step chaining used to help wrap few steps which were repeated in multiple scenarios in different modules/plugins. Like login step, which includes:
    a) Expand navigation if JS
    b ) Click on login link
    c) Fill user name
    d) Fill password
    e) Press login

Will appreciate if anyone can help/guide me how this can be achieved elegantly in behat 3.
My issues are:

  1. How to call different steps from different (20+) contexts. Api calling might work, but it's not as easy as just calling new Given and not to worry about different context and not knowing which api is in which context.
  2. Chain/Combine steps for reuse (like login).

That's what I want. But, ...in V3. Step reusable, scenario reusable.

Step1 with more than one gherkin descriptions. (One To Many)
Step2 will never have the same gherkin description(s) with Step1.
It seems Step.GherkinDescriptions.
Then.
Context.Steps
MyProject.Contexts

Step3 reuse Context1.Step1 and Context2.Step2, Then exists in Context3

Then. Problem is in suites : which context should i put in ?
Step3 depends on Context1 and Context2.

Idea. Build a auto-generated cached Context in run-time ?

AutoGeneratedContext collects all contexts steps used in this suite .

Unfortunately, I've found that actually removing this feature was a bad choice. I'm sure it could be abused but in my case (testing remote APIs) it was really important.. now trying to find a workaround :(

@johnhunt This was abused too much. Maybe PageObject could help you with that matters :)
Or maybe you want to do too much in one scenario.

This is more about complaining, that question with help to find a solution.

The only solution I've found is to create a monster context that does everything so I can run steps such as:
When I visit "https://blahblah" I expect the JSON node value "a.b.c" to equal "john" and retry 10 times, every 30 seconds.

What I'd really like to do is use the distinct out the box contexts and then just jump back.. oh well :/ (I have created a monster context that inherits from ubirak rest and json inspectors

Was this page helpful?
0 / 5 - 0 ratings

Related issues

patxi1980 picture patxi1980  路  9Comments

legovaer picture legovaer  路  6Comments

xorik picture xorik  路  3Comments

diamondsea picture diamondsea  路  6Comments

beeblebrox3 picture beeblebrox3  路  8Comments