Behat Mink: 06 - Annotated Hooks

 

Hooks

Hooks allow you to execute your custom code just before or just after each of these actions. Behat allows you to use the following hooks:

  1. The BeforeSuite hook is run before any feature in the suite runs. For example, you could use this to set up the project you are testing. This hook receives an optional argument with an instance of the Behat\Testwork\Hook\Scope\BeforeSuiteScope class.
  2. The AfterSuite hook is run after all features in the suite have run. This hooks is useful to dump or print some kind of statistics or tear down your application after testing. This hook receives an optional argument with an instance of the Behat\Testwork\Hook\Scope\AfterSuiteScope class.
  3. The BeforeFeature hook is run before a feature runs. This hook receives an optional argument with an instance of the Behat\Behat\Hook\Scope\BeforeFeatureScope class.
  4. The AfterFeature hook is run after Behat finishes executing a feature. This hook receives an optional argument with an instance of the Behat\Behat\Hook\Scope\AfterFeatureScope class.
  5. The BeforeScenario hook is run before a specific scenario will run. This hook receives an optional argument with an instance of the Behat\Behat\Hook\Scope\BeforeScenarioScope class.
  6. The AfterScenario hook is run after Behat finishes executing a scenario. This hook receives an optional argument with an instance of the Behat\Behat\Hook\Scope\AfterScenarioScope class.
  7. The BeforeStep hook is run before a step runs. This hook receives an optional argument with an instance of the Behat\Behat\Hook\Scope\BeforeStepScope class.
  8. The AfterStep hook is run after Behat finishes executing a step. This hook receives an optional argument with an instance of the Behat\Behat\Hook\Scope\AfterStepScope class.

You can use any of these hooks by annotating any of your methods in your context class:

/**
 * @BeforeSuite
 */
public static function prepare($scope)
{
    // prepare system for test suite
    // before it runs
}

 

Suite Hooks

Suite hooks are run outside of the scenario context. It means that your context class (e.g. FeatureContext) is not instantiated yet and the only way Behat can execute code in it is through the static calls. That is why suite hooks must be defined as static methods in the context class:

use Behat\Testwork\Hook\Scope\BeforeSuiteScope;
use Behat\Testwork\Hook\Scope\AfterSuiteScope;

/** @BeforeSuite */
public static function setup(BeforeSuiteScope $scope)
{
}

/** @AfterSuite */
public static function teardown(AfterSuiteScope $scope)
{
}

There are two suite hook types available:

  • @BeforeSuite - executed before any feature runs.
  • @AfterSuite - executed after all features have run.

Feature Hooks

Same as suite hooks, feature hooks are ran outside of the scenario context. So same as suite hooks, your feature hooks must be defined as static methods inside your context:

use Behat\Behat\Hook\Scope\BeforeFeatureScope;
use Behat\Behat\Hook\Scope\AfterFeatureScope;

/** @BeforeFeature */
public static function setupFeature(BeforeFeatureScope $scope)
{
}

/** @AfterFeature */
public static function teardownFeature(AfterFeatureScope $scope)
{
}

There are two feature hook types available:

  • @BeforeFeature - gets executed before every feature in suite.
  • @AfterFeature - gets executed after every feature in suite.

Scenario Hooks

Scenario hooks are triggered before or after each scenario runs. These hooks are executed inside an initialized context instance, so not only could they be simple context instance methods, they will also have access to any object properties you set during your scenario:

use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Behat\Hook\Scope\AfterScenarioScope;

/** @BeforeScenario */
public function before(BeforeScenarioScope $scope)
{
}

/** @AfterScenario */
public function after(AfterScenarioScope $scope)
{
}

There are two scenario hook types available:

  • @BeforeScenario - executed before every scenario in each feature.
  • @AfterScenario - executed after every scenario in each feature.

Now, the interesting part:

The @BeforeScenario hook executes not only before each scenario in each feature, but before each example row in the scenario outline. Yes, each scenario outline example row works almost the same as a usual scenario.

@AfterScenario functions exactly the same way, being executed both after usual scenarios and outline examples.

Step Hooks

Step hooks are triggered before or after each step runs. These hooks are run inside an initialized context instance, so they are just plain context instance methods in the same way as scenario hooks are:

use Behat\Behat\Hook\Scope\BeforeStepScope;
use Behat\Behat\Hook\Scope\AfterStepScope;

/** @BeforeStep */
public function beforeStep(BeforeStepScope $scope)
{
}

/** @AfterStep */
public function afterStep(AfterStepScope $scope)
{
}

There are two step hook types available:

  • @BeforeStep - executed before every step in each scenario.
  • @AfterStep - executed after every step in each scenario.

Tagged Hooks

Sometimes you may want a certain hook to run only for certain scenarios, features or steps. This can be achieved by associating a @BeforeFeature, @AfterFeature, @BeforeScenario or @AfterScenario hook with one or more tags. You can also use OR (||) and AND (&&) tags:

/**
 * @BeforeScenario @database,@orm
 */
public function cleanDatabase()
{
    // clean database before
    // @database OR @orm scenarios
}

Use the && tag to execute a hook only when it has all provided tags:

/**
 * @BeforeScenario @database&&@fixtures
 */
public function cleanDatabaseFixtures()
{
    // clean database fixtures
    // before @database @fixtures
    // scenarios
}

 

 

 

 

Tags