The issue
I was checking a bunch of Behat features left by former developers on a project, and noticed that the Rake rule to run them looked like:
$ behat -c config/behat.yml features
But this looked suspiciously like defaut options. How about running them more simply like just $ behat
? Alas, this would throw something like:
[InvalidArgumentException] Can't find applicable feature loader Maybe you've forgot to create `features/` folder?
Specifying the Behat configuration file but not the features directory like this didn't change a thing:
$ behat -c config/behat.yml
[InvalidArgumentException] Can't find applicable feature loader Maybe you've forgot to create `features/` folder?
And yet the behat.yml
appeared to look sane:
default: paths: features: '%behat.paths.base%/features' bootstrap: '%behat.paths.features%/bootstrap' extensions: Behat\MinkExtension\Extension: goutte: ~ selenium2: ~ base_url: http://some.site Drupal\DrupalExtension\Extension: blackbox: ~ api_driver: 'drupal' drupal: drupal_root: 'public/drupal' drush: alias: 'somealias' region_map: content: "#content" 'left header': '#header-left' 'right header': '#header-right' 'right sidebar': '#column-right' footer: "#footer-region" selectors: message_selector: '.messages' error_message_selector: '.messages.messages-error' success_message_selector: '.messages.messages-status'
The features were indeed in the (project dir)/features
, the bootstrap was indeed from (project dir)/features/bootstrap
. Modifying the bootstrap
line showed that it was being used correctly. And yet the features line never worked. I tried multiple variants like these:
# As per the Behat docs at http://docs.behat.org/guides/7.config.html#paths : default: paths: features: features # Trying to specify the base path : default: paths: features: %behat.paths.base%/features # Trying to get rid of the IDE YAML parser warnings : default: paths: features: '%behat.paths.base%/features'
All of which didn't change a thing. What could be going wrong ?
The diagnostic
I dug into the LocatorProcessor::process() function, and decided to dump what was going on. The function looks like this:
Some data printing easily showed that the setFeaturesPaths()
call received an empty string as the value of the features
argument, while the loadboostrapScripts()
received a well-formed value from the behat.paths.bootstrap
parameter.
Well, that made sense: when a Symfony2 Command like the Behat console is called without an argument, it does not default to the matching parameter. But then, how about looking into the behat.paths.features
parameter ?
That turned out to be the missing link: the value of the features
parameter was actually something like (project dir)/config/features
, not (project dir)/features
as expected. In other words, that parameter is relative to the Behat config file, not to the current working directory. Which of course, the Behat documentation had been explaining all along:
%behat.paths.base% - current working dir or configuration path (if configuration file exists and loaded).
The solution
After Reading The Fine Manual armed with the results of this diagnostic, the solution was painfully obvious. Since the config file was in config/behat.yml
, just climb back one level from it:
default: paths: features: '%behat.paths.base%/../features' bootstrap: '%behat.paths.features%/bootstrap' # ...snip...
And, of course, the test suite now ran with just a simple:
$ behat