Behat: Non-standard features path support in Behat 2.4.0

Created on 15 May 2012  路  11Comments  路  Source: Behat/Behat

I have my features under test/behat/ rather than features/ due to project conventions. To point Behat at the correct path, I have a config/behat.yml with the following content:

default:
  paths:
    features:  '%%BEHAT_BASE_PATH%%'
    bootstrap: '%behat.paths.features%/bootstrap'

and I invoke Behat with the following command:

bin/behat -c config/behat.yml test/behat/

This works in Behat 2.3.5, but in 2.4.0 I get a "Context class not found" error.

Most helpful comment

use %behat.paths.base% instead of %%BEHAT_BASE_PATH%%.

%behat.paths.base% directs to either:

  • behat.yml (or custom config) directory path, if config file exists and loaded
  • current working directory in other cases

There's no magic %%...%% directives in Behat anymore. Only:

  • behat.paths.base - described above
  • behat.paths.features - features path (defaults to features)
  • behat.paths.bootstrap - bootstraps path (defaults to %behat.paths.features%/bootstrap)

Also, all paths are relative from behat.paths.base by default, meaning, that you can use just features instead of %behat.paths.base%/features.

All 11 comments

use %behat.paths.base% instead of %%BEHAT_BASE_PATH%%.

%behat.paths.base% directs to either:

  • behat.yml (or custom config) directory path, if config file exists and loaded
  • current working directory in other cases

There's no magic %%...%% directives in Behat anymore. Only:

  • behat.paths.base - described above
  • behat.paths.features - features path (defaults to features)
  • behat.paths.bootstrap - bootstraps path (defaults to %behat.paths.features%/bootstrap)

Also, all paths are relative from behat.paths.base by default, meaning, that you can use just features instead of %behat.paths.base%/features.

Ah, ok. Thanks.

So just to clarify: there's no means now of referencing the features directory passed via commandline in the config file, so can't add paths relative to it?

And also no way of loading features from a non-standard directory without using behat.yml, since bootstrap isn't found by default in any passed directory?

e.g. 'behat foo', where foo/bootstrap/FeatureContext.php exists, still gives the 'Context not found' error?

Yep. Just no magic happens now. Custom directories are still supported, but you need to specify them explicitly in config:

# behat.yml
default:
  paths:
    features:   'foo'
    bootstrap:  'foo/bootstrap'

Paths in config are relative from config path. So, just put behat.yml whenever you want and call Behat with --config:

$> behat --config=/usr/local/etc/global_behat.yml

Thanks for the clarification. The challenge comes when you have a number of features spread across different paths (e.g. modules). It makes a single global config with shared profiles for the entire suite somewhat difficult to use. Instead, it forces copying of behat.yml into each module somewhere, which then need to be kept in sync in some way - unless I've not understood this correctly?

It's a shame that the paths can't be overridden by commandline options; this would make running a suite programatically a tiny bit easier, I think.

Why not using profiles? Each module have it's own profile and shortname:

# behat.yml

# project suite: 
# features/
# features/bootstrap
default:
  paths:
    features: 'features'

# module1 suite:
# modules/module_1/features/
# modules/module_1/features/bootstrap
module1:
  paths:
    features: 'modules/module_1/features'

# module2 suite:
# modules/module_2/features/
# modules/module_2/bootstrap/
module2:
  paths:
    features:  'modules/module_2/features'
    bootstrap: 'modules/module_2/bootstrap'

Then just run them independently:

$> behat
$> behat -p=module1
$> behat -p=module2

The problem with guessing path from argument is that argument could be anything. Now any extension could extend Behat and provide support for it's custom loaders. For example, Symfony2Extension adds support for bundle-related paths:

$> behat @SomeBundleName/login.feature

You just can't get path from it before loading suite.

Thanks, but a profile for each module means that these need to be known in advance and behat.yml edited manually, rather than being able to load features dynamically. I'll look into writing a custom loader, and check out the Symfony extension.

@zeebinz maybe it would be easier to create specific extension for your configuration, with custom Context\ClassGuesser and custom Gherkin\Loader. This way, you'll be able to autoload everything in your suite-specific way.

Thanks everzet, that sounds like a good solution, now to dig a bit deeper into the code. :)

Any progress on the extention part?

Was this page helpful?
0 / 5 - 0 ratings