Behat Contexts – A stretch of imagination – Episode 2 – The almost solution

Hello reader,
in the previous post I have presented 4 viable alternatives to our problem.

“How to have multiple contexts in Behat and maintain the OOP structureparameterssupport an expanding number of context files for a scalable application and most of all, have code hinting available in all the contexts.”

None of them quite hit the sweet-spot. From the coding perspective, for PHP 5.3 we have no tools, we I have tried a hack. The idea was to have the smaller contexts extend each other in the IDE, this provides the code hinting, but at runtime replace the code so that it accommodates Behat’s useContext syntax and logic. This should provide a win-win.

in FeatureContext.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public function __construct(array $parameters)
{
    //get the path to bootstrap in a variable
    $pathToBootstrap = join(DIRECTORY_SEPARATOR,array(getcwd(),"features","bootstrap"));

    //get an array with all the file names that have the Context.php in their name
    $filesFromBootstrap = glob(join(DIRECTORY_SEPARATOR,array($pathToBootstrap,"*Context.php")));

    //for every file modify the internal structure in order to behave as expected by Behat
    foreach($filesFromBootstrap as $filename){
        $handler = fopen($filename,"r");
        $finalClass = fread($handler,filesize($filename));
        $customContexts = array("HelperContext","FrontendContext","BackendContext");
        foreach($customContexts as $context){
            if(stristr($finalClass,"extends ".$context)){
                $finalClass = str_replace("extends ".$context,"extends BehatContext",$finalClass);
                $writeHandler = fopen($pathToBootstrap.DIRECTORY_SEPARATOR."temp.php","w");
                fwrite($writeHandler,$finalClass);
                fclose($writeHandler);
                break;
            }
        }
        fclose($handler);
        $className = str_replace(".php","",basename($filename));

        //include the temporary file
        include($pathToBootstrap.DIRECTORY_SEPARATOR.'temp.php');

        //create the context using Behat's implementation
        $this->useContext($className, new $className($parameters));
    }

    $this->login = $this->getSubcontext("login");
}

 

in the “lower” classes the code looks like:
class HelperContext extends MinkContext{ }
class Helper2Context extends HelperContext{ }
so on and so forth. This will provide the code hinting.

 

Note: The code is not complete, currently it crashes with “Fatal error: Cannot redeclare class BackendContext” ” at the temporary file inclussion. This happens because the contexts are already loaded by Behat before the FeatureContext constructor. In order to fix this, for PHP 5.3 we need to create a patch or drop the already initialized object or to modify the included class’ name. For the second I did not test the behavior or stability of the framework.

Feel free to use the code as desired and fix it.

The next post will include the PHP 5.4 “traits” functionality for the helpers contexts.

Have a nice day,

Gabi

Leave a Reply

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