Chapters

Behat 2.0 brings completely different way to handle testing part of your
features. In 1.x we had 4 separate entities: environment, step definitions,
hooks and bootstrap scripts. In 2.0 we have only one -
Contexts. That’s the biggest and the coolest change
since 1.x. It made features suites much cleaner and extensible.

There were less than half-year between 1.0 and 2.0 releases? Some users already
have big feature suites and don’t want to rewrite them once again. For such
users, Behat 2.0 can become fully backward compatible with 3 very small steps.

There’s no such things as environment or environment configuration in Behat2.
But FeatureContext can successfully emulate
environment objects from Behat 1.x. Let’s say, we have next env.php
configuration:

<?phpfeatures/support/env.php$world->someInitialVar='initial-val';$world->closureFunc=function(){// do something};

The easiest way to migrate is to move this code into
FeatureContext class:

<?phpuseBehat\Behat\Context\ClosuredContextInterface,Behat\Behat\Context\BehatContext,Behat\Behat\Exception\PendingException;useBehat\Gherkin\Node\PyStringNode,Behat\Gherkin\Node\TableNode;classFeatureContextextendsBehatContext{public$someInitialVar='initial-val';publicfunctionclosureFunc(){// do something}}

As you might see, your someInitialVar become an instance variable and
closureFunc() just an instance method. You should move all your variables
and methods carefully, changing all $world to $this in closure methods.

It might be very hard and annoying work, especially on large projects. So, as
you might expect, you have another option:

<?phpuseBehat\Behat\Context\ClosuredContextInterface,Behat\Behat\Context\BehatContext,Behat\Behat\Exception\PendingException;useBehat\Gherkin\Node\PyStringNode,Behat\Gherkin\Node\TableNode;classFeatureContextextendsBehatContext{public$parameters=array();publicfunction__construct(array$parameters){$this->parameters=$parameters;if(file_exists($env=__DIR__.'/../support/env.php')){$world=$this;require_once($env);}}publicfunction__call($name,array$args){if(isset($this->$name)&&is_callable($this->$name)){returncall_user_func_array($this->$name,$args);}else{$trace=debug_backtrace();trigger_error('Call to undefined method '.get_class($this).'::'.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'],E_USER_ERROR);}}}

With this context, you’ll be able to use your old env.php totally untouched.
That’s it. Full BC with 1.x environment.

Taking all previously said into account, fully backward-compatible context will
look like this:

<?phpuseBehat\Behat\Context\ClosuredContextInterface,Behat\Behat\Context\BehatContext,Behat\Behat\Exception\PendingException;useBehat\Gherkin\Node\PyStringNode,Behat\Gherkin\Node\TableNode;if(file_exists(__DIR__.'/../support/bootstrap.php')){require_once__DIR__.'/../support/bootstrap.php';}classFeatureContextextendsBehatContextimplementsClosuredContextInterface{public$parameters=array();publicfunction__construct(array$parameters){$this->parameters=$parameters;if(file_exists(__DIR__.'/../support/env.php')){$world=$this;require(__DIR__.'/../support/env.php');}}publicfunctiongetStepDefinitionResources(){if(file_exists(__DIR__.'/../steps')){returnglob(__DIR__.'/../steps/*.php');}returnarray();}publicfunctiongetHookDefinitionResources(){if(file_exists(__DIR__.'/../support/hooks.php')){returnarray(__DIR__.'/../support/hooks.php');}returnarray();}publicfunction__call($name,array$args){if(isset($this->$name)&&is_callable($this->$name)){returncall_user_func_array($this->$name,$args);}else{$trace=debug_backtrace();trigger_error('Call to undefined method '.get_class($this).'::'.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'],E_USER_ERROR);}}}

You can just copy’n’paste this code into your features/bootstrap/FeatureContext.php
and Behat2 will magically start to work with your 1.x feature suite.