Testmode
Testmode keeps live and generated content out of Behat assertions. While test mode is on, it filters the listings in the views you register. Only nodes with a matching title, terms with a matching name and users with a matching email remain. A scenario's assertions then cover only test content, even on a site full of demo pages or a copy of production.
This page is for developers writing Behat tests on a project built from Vortex. It shows how to register a view with Testmode and how to turn test mode on for a scenario. The module documentation is the reference for its full API.
How it works
Testmode filtering relies on 3 conventions:
- Test content created in Behat features has titles that start with
[TEST]. - The views to filter are registered in the
testmode.settingsconfiguration. - Behat scenarios tagged with
@testmodeturn filtering on before they run and off after they end.
While filtering is on, the registered views show only content that matches
the test patterns, such as [TEST% for node titles.
Testmode keeps its on/off flag in the state system, so switching it never
touches configuration. While it's on, users with the
administer site configuration permission see a warning on every page. The
warning starts with Test mode is enabled. and links to the Testmode
settings at /admin/config/development/testmode. A warning outside a test
run means a run stopped before it switched test mode off.
To turn test mode off by hand, use 1 of the following:
- On the Testmode settings page, select Disabled under Test mode, then click Save configuration.
- From code, call
Testmode::getInstance()->disableTestMode(). - With Drush, delete the state flag, then invalidate the
testmode:viewscache tag that Testmode adds to the views it filters, so their cached listings are rebuilt.
The Drush route uses the following commands:
ahoy drush state:delete testmode.enabled
ahoy drush cache:tags testmode:views
The second command reports Invalidated tag(s): testmode:views. Confirm
that the warning no longer appears on the next page you load.
Configuration
Testmode is configured through the testmode.settings configuration object:
| Key | Type | Description |
|---|---|---|
views_node | string[] | Node view machine names to filter |
views_term | string[] | Term view machine names to filter |
views_user | string[] | User view machine names to filter |
pattern_node | string[] | MySQL LIKE patterns for node titles |
pattern_term | string[] | MySQL LIKE patterns for term names |
pattern_user | string[] | MySQL LIKE patterns for user emails |
list_term | bool | If true, filters the taxonomy term overview page with the term patterns. If false, leaves that page unfiltered |
The default settings do the following:
- Filter the
contentanduser_admin_peopleviews - Match node titles and term names against
[TEST% - Match user emails against
%example% - Filter the term overview page
Vortex adds testmode to config_exclude_modules in
settings.testmode.php,
so the module and its settings stay out of the exported configuration.
Configuration import therefore doesn't enable the module, so
scripts/provision-10-enable-dev-modules.sh
installs it instead, with the other
development modules, in the
local, ci, dev and stage environments. The ys_demo module also
declares it as a dependency, so installing the demo module brings it in.
Register a view programmatically
The Testmode singleton reads and writes that configuration. The settings
stay out of the exported configuration, so register a view from a deploy
hook in your module's MODULE.deploy.php file, as ys_demo does in
ys_demo.deploy.php:
use Drupal\testmode\Testmode;
function ys_demo_deploy_configure_testmode(): string {
$testmode = Testmode::getInstance();
$views = $testmode->getNodeViews();
if (!in_array('ys_demo_pages', $views)) {
$views[] = 'ys_demo_pages';
$testmode->setNodeViews($views);
}
return 'Configured testmode to filter the pages view.';
}
The singleton has a getter and a setter for every key in the configuration table:
| Key | Getter | Setter |
|---|---|---|
views_node | getNodeViews() | setNodeViews() |
views_term | getTermViews() | setTermViews() |
views_user | getUserViews() | setUserViews() |
pattern_node | getNodePatterns() | setNodePatterns() |
pattern_term | getTermPatterns() | setTermPatterns() |
pattern_user | getUserPatterns() | setUserPatterns() |
list_term | getListTerm() | setTermsList() |
The view and pattern setters accept an array or a newline-separated string.
The list_term setter takes a boolean. Its method name, setTermsList(),
doesn't mirror the getter's getListTerm(). To stop filtering the term
overview page, call setTermsList(FALSE). On the settings page, the same
switch is the Include Taxonomy Terms Overview checkbox.
To drive the mode itself, the singleton has the following methods:
enableTestMode()turns test mode on.disableTestMode()turns test mode off.toggleTestMode()turns test mode on when passedTRUE, and off when passedFALSE.isTestMode()returnsTRUEwhile test mode is on.
Behat integration
The @testmode tag turns test mode on for a single scenario and off again
when it ends. The tag comes from TestmodeTrait in
behat-steps. FeatureContext
extends the DrupalContext class, which already includes the trait, so the
tag works without extra wiring. A tagged scenario fails straight away if
the testmode module isn't enabled:
@testmode
Scenario: Pages view shows only test content when test mode is enabled
Given the following page content exists:
| title | status | moderation_state |
| [TEST] First test page | 1 | published |
| [TEST] Second test page | 1 | published |
When I go to "/pages"
Then I should see "[TEST] First test page"
And I should see "[TEST] Second test page"
And I should not see "Demo page"
The [TEST] prefix in content titles matches the default [TEST% pattern
configured in Testmode. Only matching content appears in registered views,
so the generated Demo page nodes stay out of the assertions.
To run the suite, or only this feature with
ahoy test-bdd tests/behat/features/pages.feature, see
Behat.
Example in Vortex
The ys_demo module puts these pieces together:
- It ships a pages view at
/pages. - It registers the view with Testmode in the
ys_demo_deploy_configure_testmodedeploy hook. - The
pages.featureBehat feature intests/behat/featurescovers the view and demonstrates the@testmodetag against the generated content that the view filters out.