Contributed Module Subcontexts

Although not yet a wide-spread practice, the Drupal Extension to Behat and Mink makes it easy for maintainers to include custom step definitions in their contributed projects.

Discovering SubContexts

In order to use contributed step definitions, define the search path in the behat.yml

// sites/default/behat-tests/behat.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
default:
  suites:
    default:
      contexts:
        - FeatureContext
        - Drupal\DrupalExtension\Context\DrupalContext
        - Drupal\DrupalExtension\Context\MinkContext
      paths:
        - "./path_to_module/features"
  extensions:
    Drupal\MinkExtension:
      goutte: ~
      selenium2: ~
      base_url: http://seven.l
    Drupal\DrupalExtension:
      blackbox: ~
      api_driver: 'drupal' 
      drush:
        alias: 'local'
      drupal: 
        drupal_root: '/var/www/seven/drupal' 
      region_map:
        footer: "#footer"
      subcontexts:
        paths:
          - "/var/www/seven/drupal/sites/all"

The Drupal Extension will search recursively within the directory or directories specified to discover and load any file ending in .behat.inc. This system, although created with Drupal contrib projects in mind, searches where it’s pointed, so you can also use it for your own subcontexts, a strategy you might employ to re-use step definitions particular to your shop or company’s development patterns. The paths key allows running tests located in features within the features directory of a contributed/custom module.

Disable autoloading

Autoloading can be disabled in the behat.yml file temporarily with the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
default:
  suites:
    default:
      contexts:
        - FeatureContext
        - Drupal\DrupalExtension\Context\DrupalContext
        - Drupal\DrupalExtension\Context\MinkContext
  extensions:
    Drupal\MinkExtension:
      goutte: ~
      selenium2: ~
      base_url: http://seven.l
    Drupal\DrupalExtension:
      blackbox: ~
      api_driver: 'drupal' 
      drush:
        alias: 'local'
      drupal: 
        drupal_root: '/var/www/seven/drupal' 
      region_map:
        footer: "#footer"
      subcontexts:
        paths:
          - "/var/www/seven/drupal/sites/all"
        autoload: 0

For Contributors

Behat subcontexts are no longer supported in version 3. The Drupal Extension, however, continues to support saving module-specific contexts in a file ending with .behat.inc

Just like functions, preface the filename with the project’s machine name to prevent namespace collisions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php

/**
 * Contains \FooFoo.
 */

use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Behat\Tester\Exception\PendingException;
use Drupal\DrupalExtension\Context\DrupalSubContextBase;
use Drupal\DrupalExtension\Context\DrupalSubContextInterface;

/**
 * Example subcontext.
 */
class FooFoo extends DrupalSubContextBase implements DrupalSubContextInterface {

  /**
   * @var \Drupal\DrupalExtension\Context\DrupalContext
   */
  protected $drupalContext;

  /**
   * @var \Drupal\DrupalExtension\Context\MinkContext
   */
  protected $minkContext;

  /**
   * @BeforeScenario
   */
  public function gatherContexts(BeforeScenarioScope $scope) {
    $environment = $scope->getEnvironment();

    $this->drupalContext = $environment->getContext('Drupal\DrupalExtension\Context\DrupalContext');
    $this->minkContext = $environment->getContext('Drupal\DrupalExtension\Context\MinkContext');
  }

  /**
   * @Given I create a(an) :arg1 content type
   */
  public function CreateAContentType($arg1) {
    $this->minkContext->assertAtPath("admin/structure/types/add");
    $node = [
      'title' => 'Test content!',
    ];
    $this->drupalContext->nodeCreate($node);
  }

  /**
   * @Then /^I should have a subcontext definition$/
   */
  public function assertSubContextDefinition() {
    throw new PendingException();
  }

}