Behat – Mink New Use Of Aliased Subcontexts & Complex Step Chaining

Organization for reuse and refactoring is needed when the number of step definitions inside our context file gets big. Behat allow us to (a) organize steps definitions for our contexts into a main context and several subcontexts, and to (b) abstract larger tasks with repetitive steps via step chaining. These two characteristics combined can make our features very versatile and reusable.

Aliased Subcontexts

To try the feature just load the aliased-subcontext branch by inserting the following line on deps:

version=origin/feature/aliased-subcontexts

The line goes right inside the behat deps specification. In the future this branch feature will be merged into production so this step will not be needed.

Because of our update code example breaks with:

Catchable Fatal Error: Argument 2 passed to Behat\Behat\Context\BehatContext::useContext() must implement interface Behat\Behat\Context\ExtendedContextInterface, none given, called in /home/cordoval/sites-2/Bundle/Features/Context/FeatureContext.php on line 28 and defined in /home/cordoval/sites-2/vendor/behat/Behat/src/Behat/Behat/Context/BehatContext.php line 39

In order to bring the functionality back the new use of context and subcontext should be rendered in the following way. The example will illustrate a main context which extends MinkContext and also loads two BehatContext subcontexts aliased ‘clicking’ and ‘loading’.

class FeatureContext extends MinkContext
{
    public function __construct(HttpKernelInterface $kernel) {
        $this->useContext('clicking', new ClickingContext($kernel));
        $this->useContext('loading', new LoadingContext($kernel));
        parent::__construct($kernel);
    }

The fetching of session within the subcontext class ‘clicking’ requires a call to getMainContext as follows:

class ClickingContext extends BehatContext{
    /**
     * @Then /^I click complete button$/
     */
    public function iClickCompleteButton()
    {
        $page = $this->getMainContext()->getSession()->getPage();
        // ...
    }

And in addition, from the ‘loading’ subcontext one can call methods from ‘clicking’ subcontext via:

class LoadingContext extends BehatContext{
   /**
    * @Given /^I\'m already logged in$/
    */
   public function imAlreadyLoggedIn()
   {
        // this calls a method from the main context
        $this->getMainContext()->iWaitForTheSuggestionBoxToAppear();
 
        // this calls a method from a different subcontext
        $this->getMainContext()->getSubContext('clicking')->iClickCompleteButton();
 
        // ...
   }

Notice that even though you are on the main context you cannot call the methods of a subcontext directly but rather you have to first get that context in order to call its method.

Complex Step Chaining
In order to abstract a step that could comprise more than one individual step or to provide a macro step that is repetitive yet still complex behat allows us to demand from our step the execution of mini-scenarios. An example is found in the behat code itself under features folder at the root of behat package:

/**
 * @Given /I entered "([^"]*)" and expect "([^"]*)"/
 */
public function complexStep($number, $result)
{
    return array(
        new Step\Given("I have entered \"$number\""),
        new Step\When("I press +"),
        new Step\Then("I should see \"$result\" on the screen")
    );
}

We can also chain macro or micro steps using a simple return like:

/**
 * @Given /Я ввел "([^"]*)"/
 */
public function iHaveEnteredRu($number)
{
    return new Step\Given("I have entered \"$number\"");
}

The use of chaining tends to be more application specific whereas the use and grouping of steps in subcontexts tends to enhance readability at the time they are used and promotes the creation of specialized libraries that one can use to thread application scenarios. Planning of these things comes with practice and experience, and things like the auto-generated code done in behat codebase using features are a good example of this. Credits should be given to everzet and stof for taking the time to help me understand more of the basics.

Thanks hope this article finds its place into your learning and feel free to donate if this has helped you.

One thought on “Behat – Mink New Use Of Aliased Subcontexts & Complex Step Chaining

Leave a Reply

Your email address will not be published. Required fields are marked *