I'm trying to reproduce isolated test suites with Behat like I have with Cucumber. I've been trying to tweak the behat.yml file using suites and paths as well as moving files and folders around. Behat results make so little sense that I am starting to conclude that it was not designed with this in mind at all. And the documentation does not describe expected files & folder layouts
For each test suite I want:
- a specific xxx.feature file
- a specific xxxContext.php file, defining a its own
xxxContext
class
I don't want a monolithic FeatureContext.php file. My project is so huge that it would become a nightmare to maintain, not to mention the potential collateral damage between steps. It's OK to have a single behat.yml file if that helps.
I also read this post but I still haven't solved the problem. How I can create isolated test suites with Behat?
Note: I am using behat 3.0-dev
Edit: Here is the "best" I could achieve. I have two suites, one called "OAuth2" and another called "Achievements".
beyat.yml:
default:
suites:
OAuth2:
contexts:
- OAuth2Context
Achievements:
contexts:
- AchievementsContext
File hierarchy:
├── behat.yml
└── features
├── Achievements.feature
├── OAuth2.feature
└── bootstrap
└── OAuth2Context.php <-- Contains the OAuth2Context and AchievementsContext classes. Also, classes are found only if I name this file this way, I don't know why.
My main problem is that when I run behat, it complains that there are missing steps. Basically, the OAuth2Context class is missing steps that were defined in Achievements and the AchievementsContext is missing steps that were defined in OAuth2. This output completely baffles me:
--- OAuth2Context has missing steps. Define them with these snippets:
/**
* @When I say yes
*/
public function iSayYes()
{
throw new PendingException();
}
/**
* @Then you say no
*/
public function youSayNo()
{
throw new PendingException();
}
--- AchievementsContext has missing steps. Define them with these snippets:
/**
* @When I ask for an Access Token with my credentials
*/
public function iAskForAnAccessTokenWithMyCredentials2()
{
throw new PendingException();
}
/**
* @Then I receive an Access Token
*/
public function iReceiveAnAccessToken2()
{
throw new PendingException();
}
/**
* @When I ask for an Access Token with a Partner User grant type where:
*/
public function iAskForAnAccessTokenWithAPartnerUserGrantTypeWhere(TableNode $table)
{
throw new PendingException();
}
I believe that this is because I defined two separate classes in the php file. But I really don't want to make a single monolitic class. In fact, I'd even like two separate PHP files. The Classes are defined this way:
class OAuth2Context implements Context, SnippetAcceptingContext
{
...
/**
* @When I ask for an Access Token with my credentials
*/
public function iAskForAnAccessTokenWithMyCredentials()
{
...
}
...
}
class AchievementsContext implements Context, SnippetAcceptingContext
{
...
/**
* @When I say yes
*/
public function iSayYes()
{
...
}
...
}
Other (smaller) issue is that I have to name my php file OAuth2Context.php instead of FeatureContext.php, otherwise the classes are not found at all. I don't understand this, as it was my understanding that FeatureContext.php was behat's default name.
Edit: SOLUTION, thanks to Jakub Zalas :
Here is the file layout that works:
├── behat.yml
└── features
├── achievements
│ └── Achievements.feature
├── bootstrap
│ ├── AchievementsContext.php <-- AchievementsContext class
│ └── OAuth2Context.php <-- OAuth2Context class
└── oauth
└── OAuth2.feature
With the following beyat.yml file:
default:
suites:
OAuth2:
contexts:
- OAuth2Context
paths: [ %paths.base%/features/oauth ]
Achievements:
contexts:
- AchievementsContext
paths: [ %paths.base%/features/achievements ]
This way I have steps in separated PHP files, which was my main requirement, and separated suites with separated feature files. I am a happy camper!