Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP Config - Suites #179

Merged
merged 2 commits into from
Dec 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
325 changes: 223 additions & 102 deletions user_guide/configuration/suites.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,71 +10,146 @@ With suites you can configure Behat to test different kinds of features
using different kinds of contexts and doing so in one run. Test suites are
really powerful and ``behat.yml`` makes them that much more powerful:

.. code-block:: yaml

# behat.yml

default:
suites:
core_features:
paths: [ '%paths.base%/features/core' ]
contexts: [ CoreDomainContext ]
user_features:
paths: [ '%paths.base%/features/web' ]
filters: { role: user }
contexts: [ UserContext ]
admin_features:
paths: [ '%paths.base%/features/web' ]
filters: { role: admin }
contexts: [ AdminContext ]
.. code-block:: php

<?php
// behat.php

use App\Tests\Behat\Context\AdminContext;
use App\Tests\Behat\Context\CoreDomainContext;
use App\Tests\Behat\Context\UserContext;
use Behat\Config\Config;
use Behat\Config\Config\Filter\RoleFilter;
use Behat\Config\Profile;
use Behat\Config\Suite;

$profile = new Profile('default')
->withSuite(
new Suite('core_features')
->withPaths('%paths.base%/features/core')
->withContexts(CoreDomainContext::class)
)
->withSuite(
new Suite('user_features')
->withFilter(new RoleFilter('user'))
->withPaths('%paths.base%/features/web')
->withContexts(UserContext::class)
)
->withSuite(
new Suite('admin_features')
->withFilter(new RoleFilter('admin'))
->withPaths('%paths.base%/features/web')
->withContexts(AdminContext::class)
)
;

return new Config()
->withProfile($profile)
;

.. note::

On PHP < 8.4, you need to wrap new invocations with parentheses before calling config object methods.

.. code-block:: php

// ...
// $profile = new Profile('default')
$profile = (new Profile('default'))
->withSuite(
// new Suite('core_features')
(new Suite('core_features'))
->withPaths('%paths.base%/features/core')
->withContexts(CoreDomainContext::class)
)
// ...

Suite Paths
-----------

One of the most obvious settings of the suites is the ``paths``
configuration:

.. code-block:: yaml
.. code-block:: php

<?php
// behat.php

# behat.yml
use Behat\Config\Config;
use Behat\Config\Profile;
use Behat\Config\Suite;

default:
suites:
core_features:
paths:
- '%paths.base%/features'
- '%paths.base%/test/features'
- '%paths.base%/vendor/.../features'
$profile = new Profile('default')
->withSuite(
new Suite('core_features')
->withPaths(
'%paths.base%/features',
'%paths.base%/test/features',
'%paths.base%/vendor/.../features',
)
)
;

return (new Config())
->withProfile($profile)
;

As you might imagine, this option tells Behat where to search for test features.
You could, for example, tell Behat to look into the
``features/web`` folder for features and test them with ``WebContext``:

.. code-block:: yaml
.. code-block:: php

# behat.yml
<?php
// behat.php

default:
suites:
web_features:
paths: [ '%paths.base%/features/web' ]
contexts: [ WebContext ]
use App\Tests\Behat\Context\WebContext;
use Behat\Config\Config;
use Behat\Config\Profile;
use Behat\Config\Suite;

You then might want to also describe some API-specific features in
``features/api`` and test them with an API-specific ``ApiContext``. Easy:
$profile = new Profile('default')
->withSuite(
new Suite('web_features')
->withPaths('%paths.base%/features/web')
->withContexts(WebContext::class)
)
;

.. code-block:: yaml
return new Config()
->withProfile($profile)
;

# behat.yml
You then might want to also describe some API-specific features in
``features/api`` and test them with an API-specific ``ApiContext``. Easy:

default:
suites:
web_features:
paths: [ '%paths.base%/features/web' ]
contexts: [ WebContext ]
api_features:
paths: [ '%paths.base%/features/api' ]
contexts: [ ApiContext ]
.. code-block:: php

<?php
// behat.php

use App\Tests\Behat\Context\ApiContext;
use App\Tests\Behat\Context\WebContext;
use Behat\Config\Config;
use Behat\Config\Profile;
use Behat\Config\Suite;

$profile = new Profile('default')
->withSuite(
new Suite('web_features')
->withPaths('%paths.base%/features/web')
->withContexts(WebContext::class)
)
->withSuite(
new Suite('api_features')
->withPaths('%paths.base%/features/api')
->withContexts(ApiContext::class)
)
;

return new Config()
->withProfile($profile)
;

This will cause Behat to:

Expand Down Expand Up @@ -103,27 +178,36 @@ criteria. The Gherkin parser comes bundled with a set of cool filters
such as *tags* and *name* filters. You can use these filters to run
features with specific tag (or name) in specific contexts:

.. code-block:: yaml

# behat.yml

default:
suites:
web_features:
paths: [ '%paths.base%/features' ]
contexts: [ WebContext ]
filters:
tags: '@web'
api_features:
paths: [ '%paths.base%/features' ]
contexts: [ ApiContext ]
filters:
tags: '@api'

.. note::

The ``@`` character is a special and requires the tag to be
put in quotes.
.. code-block:: php

<?php
// behat.php

use App\Tests\Behat\Context\ApiContext;
use App\Tests\Behat\Context\WebContext;
use Behat\Config\Config;
use Behat\Config\Filter\TagFilter;
use Behat\Config\Profile;
use Behat\Config\Suite;

$profile = new Profile('default')
->withSuite(
new Suite('web_features')
->withFilter(new TagFilter('@web'))
->withPaths('%paths.base%/features')
->withContexts(WebContext::class)
)
->withSuite(
new Suite('api_features')
->withFilter(new TagFilter('@api'))
->withPaths('%paths.base%/features')
->withContexts(ApiContext::class)
)
;

return new Config()
->withProfile($profile)
;

This configuration will tell Behat to run features and scenarios
tagged as ``@web`` in ``WebContext`` and features and scenarios
Expand All @@ -132,22 +216,36 @@ in the same folder. How cool is that? But it gets even better,
because Gherkin 4+ (used in Behat 3+) added a very special *role*
filter. That means, you can now have nice actor-based suites:

.. code-block:: yaml

# behat.yml

default:
suites:
user_features:
paths: [ '%paths.base%/features' ]
contexts: [ UserContext ]
filters:
role: user
admin_features:
paths: [ '%paths.base%/features' ]
contexts: [ AdminContext ]
filters:
role: admin
.. code-block:: php

<?php
// behat.php

use App\Tests\Behat\Context\AdminContext;
use App\Tests\Behat\Context\UserContext;
use Behat\Config\Config;
use Behat\Config\Filter\RoleFilter;
use Behat\Config\Profile;
use Behat\Config\Suite;

$profile = new Profile('default')
->withSuite(
new Suite('user_features')
->withFilter(new RoleFilter('user'))
->withPaths('%paths.base%/features')
->withContexts(UserContext::class)
)
->withSuite(
new Suite('api_features')
->withFilter(new RoleFilter('admin'))
->withPaths('%paths.base%/features')
->withContexts(AdminContext::class)
)
;

return (new Config())
->withProfile($profile)
;

A Role filter takes a look into the feature description block:

Expand All @@ -172,14 +270,22 @@ option to override the filters at the command line.

This is achieved by specifying the filter in the gherkin configuration:

.. code-block:: yaml
.. code-block:: php

<?php
// behat.php

use Behat\Config\Config;
use Behat\Config\Filter\TagFilter;
use Behat\Config\Profile;

# behat.yml
$profile = new Profile('default')
->withFilter(new TagFilter('~@wip'))
;

default:
gherkin:
filters:
tags: '~@wip'
return new Config()
->withProfile($profile)
;

In this instance, scenarios tagged as @wip will be ignored unless the CLI
command is run with a custom filter, e.g.:
Expand All @@ -203,20 +309,35 @@ against different contexts *or* the same contexts configured differently.
This basically means that you can use the same subset of features to
develop different layers of your application with Behat:

.. code-block:: yaml

# behat.yml

default:
suites:
domain_features:
paths: [ '%paths.base%/features' ]
contexts: [ DomainContext ]
web_features:
paths: [ '%paths.base%/features' ]
contexts: [ WebContext ]
filters:
tags: '@web'
.. code-block:: php

<?php
// behat.php

use App\Tests\Behat\Context\DomainContext;
use App\Tests\Behat\Context\WebContext;
use Behat\Config\Config;
use Behat\Config\Filter\TagFilter;
use Behat\Config\Profile;
use Behat\Config\Suite;

$profile = new Profile('default')
->withSuite(
new Suite('domain_features')
->withPaths('%paths.base%/features')
->withContexts(DomainContext::class)
)
->withSuite(
new Suite('web_features')
->withFilter(new TagFilter('@web'))
->withPaths('%paths.base%/features')
->withContexts(WebContext::class)
)
;

return new Config()
->withProfile($profile)
;

In this case, Behat will first run all the features from the ``features/``
folder in ``DomainContext`` and then only those tagged with ``@web`` in
Expand Down
Loading