diff --git a/cookbooks/custom_formatter.rst b/cookbooks/custom_formatter.rst index 578f598..31668a9 100644 --- a/cookbooks/custom_formatter.rst +++ b/cookbooks/custom_formatter.rst @@ -150,7 +150,7 @@ etc. } /** - * setParameter will be called for each key given to the formatter in your behat.yml file. + * setParameter will be called for each key given to the formatter in your behat.php file. * We will see that later in the "integration". * In our case, the only allowed parameter is a "file_name" that must be a string : the JSON file that we will write. */ @@ -194,7 +194,7 @@ etc. } /** - * This is the name of the formatter, that will be used in the behat.yml file + * This is the name of the formatter, that will be used in the behat.php file */ public function getName(): string { @@ -508,4 +508,3 @@ About the author Written by `Julien Deniau `__, originally posted as a blog post `on his blog `__. - diff --git a/guides.rst b/guides.rst index 12e3f9d..a68d3b6 100755 --- a/guides.rst +++ b/guides.rst @@ -75,7 +75,6 @@ Documentation Contents user_guide/writing_scenarios user_guide/organizing user_guide/context - user_guide/annotations user_guide/command_line_tool user_guide/configuration user_guide/integrations diff --git a/quick_start.rst b/quick_start.rst index aad9bb7..a881cdc 100644 --- a/quick_start.rst +++ b/quick_start.rst @@ -282,11 +282,10 @@ in our case) and tell Behat that this code represents a specific scenario step .. note:: - Behat uses PHP Attributes for step definitions, step - transformations and hooks. It also supports doc-block - annotations for compatibility with legacy code, but this - syntax is deprecated - see the :doc:`annotations ` documentation - for details. + Behat uses PHP Attributes for step definitions, step transformations and hooks. + In Behat 4.0, we removed support for defining this with PHPDoc annotations. + You can automatically convert these to attributes - see + :doc:`the 4.0 upgrade guide `. ``#[Given('there is a(n) :arg1, which costs £:arg2')]`` above the method tells Behat that this particular method should be executed whenever Behat sees step that diff --git a/releases.rst b/releases.rst index b837935..c9da00a 100644 --- a/releases.rst +++ b/releases.rst @@ -1,17 +1,19 @@ Releases & version support ========================== -Behat follows `Semantic Versioning`_ - breaking changes will only be made in a major release. +Behat follows `Semantic Versioning`_ - therefore we will only make breaking changes to the Public API in a major +release. Note that a significant portion of Behat's codebase is **not considered part of the Public API** - you +can read more in :doc:`the Backward Compatibility documentation `. Supported versions ------------------ -======= ========== ========== ============ ======================================================================= +======= ========== ========== ============ ==================================================================== Major Released Bugfix EOL Security EOL -======= ========== ========== ============ ======================================================================= +======= ========== ========== ============ ==================================================================== `v3.x`_ April 2014 See below See below `Changelog `__ -`v4.x`_ tbc 2025/6 See below See below `Changelog `__ -======= ========== ========== ============ ======================================================================= +`v4.x`_ tbc Q3/26 See below See below `4.x Changelog`_ :doc:`Upgrading ` +======= ========== ========== ============ ==================================================================== As a minimum, a major version series will receive: @@ -82,6 +84,14 @@ Major Released Bugfix EOL Security EOL `v2.x`_ July 2011 June 2015 June 2015 `Changelog `__ ======= ========== ============ ============ ===================================================================== +Additional Releases documentation +--------------------------------- + +.. toctree:: + :maxdepth: 1 + + releases/backwards-compatibility + releases/upgrading-to-4.0 .. _`Semantic Versioning`: http://semver.org/ .. _`official php.net version support page`: https://www.php.net/supported-versions.php @@ -89,3 +99,4 @@ Major Released Bugfix EOL Security EOL .. _`v2.x`: https://github.com/Behat/Behat/releases?q=v2 .. _`v3.x`: https://github.com/Behat/Behat/releases?q=v3 .. _`v4.x`: https://github.com/Behat/Behat/releases?q=v4 +.. _`4.x Changelog`: https://github.com/Behat/Behat/blob/4.x/CHANGELOG.md diff --git a/releases/backwards-compatibility.rst b/releases/backwards-compatibility.rst new file mode 100644 index 0000000..1de3d23 --- /dev/null +++ b/releases/backwards-compatibility.rst @@ -0,0 +1,83 @@ +Backwards Compatibility and the Behat Public API +================================================ + +Behat follows Semantic Versioning. For minor or patch releases, we aim to keep things stable: + +* CLI arguments and options will stay the same. We may add new ones, but existing ones will continue to work as they do + now. +* Configuration options will not change or be removed. New options may be added, and their default values will match + the previous behavior. +* Machine-readable output (like JSON or JUnit) will keep the same fields and data types. We might add new fields or + change how text is formatted (like adding or removing whitespace), but the structure will remain compatible. +* Any changes to the public API (interfaces, classes, and behavior) will be backwards-compatible with the previous + version. +* Your code (step definitions, hooks, transformations) will run the same way between versions - including + that we will trigger hooks in the same order. +* Behat's event dispatcher will fire the same events in the same order. We might add new events in between, but + existing ones will stay. + +The only time we might break this is to fix a critical bug or a security issue that cannot be resolved any other way. + +Note that from version 4.0 onwards, we do not guarantee the exact format of human-readable output (like the ``progress`` +or ``pretty`` formatters). These are intended for people to read, so we may improve them over time. + +What counts as Behat's "Public API"? +------------------------------------ + +Starting with version 3.30.0, all interfaces, classes, and methods in Behat are **internal by default**. We follow the +`phpstan backwards compatibility convention`_, which means code is only part of our public API if it is explicitly +marked with the ``@api`` tag. + +* In Behat 4.0 and later, our compatibility promise only applies to code marked with ``@api``. Anything else may change + in any release. +* In Behat 3.x, we maintain compatibility for the entire codebase. However, if you are using code that is not + marked ``@api``, we recommend updating your code or asking us to make it public. + +.. note:: + + We are happy to consider making more of the Behat codebase public. If you need an ``@api`` tag added, please let + us know! We will look at your use case and see how it affects the long-term maintenance of Behat. + + Please open an issue (or even better a Pull Request) with details on what you would like to use and why. + +Classes +~~~~~~~ + +* Only (non-final) classes with ``@api`` in their PHPDoc can be extended. +* Objects can only be created via ``new`` if the PHPDoc of the + public constructor is directly tagged with ``@api``. In all other cases + (even if the class PHPDoc has ``@api``), instances of the class should + only be created by / retrieved from Behat's service container. +* Methods can only be called if there is an ``@api`` tag in the PHPDoc + of the method, declaring class, or declaring interface. +* Constants can only be accessed if there is an ``@api`` tag in the + PHPDoc of the constant, declaring class, or declaring interface. + +Interfaces +~~~~~~~~~~ + +* Interfaces with ``@api`` in their PHPDoc can be implemented and extended. +* All methods from interfaces with ``@api`` in their PHPDoc can be called. + +Traits +~~~~~~ + +* No Behat traits can be used. + + +Other tips for extension authors +-------------------------------- + +Our compatibility promise covers changes to existing code, but we will still add new features like CLI arguments, +config options, or methods. + +To avoid conflicts with future versions of Behat, we recommend following these practices: + +* Do not use the ``Behat`` namespace for your own code. +* Only add configuration options within your extension's own namespace. +* While you can add new CLI commands or flags, it's safer to use configuration files or Behat's ``--profile`` feature. + This avoids naming conflicts with future Behat versions. +* If you extend a Behat class (marked ``@api``), try to avoid adding new public methods. This protects you if Behat adds + a method with the same name in the future. + +.. _`phpstan backwards compatibility convention`: https://phpstan.org/developing-extensions/backward-compatibility-promise diff --git a/releases/upgrading-to-4.0.rst b/releases/upgrading-to-4.0.rst new file mode 100644 index 0000000..1c8e22a --- /dev/null +++ b/releases/upgrading-to-4.0.rst @@ -0,0 +1,107 @@ +Upgrading to Behat 4.0 +====================== + +We want to make upgrading to Behat 4.0 as smooth as possible. While there are some breaking changes, we've tried to +keep them to a minimum. + +If you are an end-user (meaning you use Behat to run tests but haven't written custom extensions), most of these changes +won't affect you. In many cases, you can use automated tools to handle the upgrade for you. Follow this guide to get +started. + +Upgrading for users +-------------------- + +For most projects, these are the main changes: + +* **PHP Configuration:** We now use PHP for configuration. YAML files are no longer supported. Behat will look for + ``behat.php`` or ``behat.dist.php`` in your current directory. +* **PHP Attributes:** We've replaced PHPDoc annotations (like ``@Given`` or ``@BeforeScenario``) with native PHP + Attributes. +* **Cleanup:** All previously deprecated features and code have been removed. +* **New Parser Mode:** We now default to a newer parser compatibility mode + (:doc:`GHERKIN_32 `). + +Step-by-step preparation +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Before** you switch to Behat 4.0, we recommend taking these steps: + +1. **Update Behat 3:** Make sure you are using the latest version of Behat 3.x. +2. **Convert Config:** If you use YAML, run ``vendor/bin/behat --convert-config`` to `convert it to PHP`_. Review the + results to make sure everything looks correct. +3. **Check File Location:** If your config file is in a ``config/`` folder, move it to your project root or use the + ``--config`` flag when running Behat. +4. **Update Extensions:** Make sure any extensions you use are referenced by their full class name (e.g. + ``Behat\MinkExtension\ServiceContainer\MinkExtension::class`` not ``Behat\MinkExtension```). The conversion tool + usually handles this. +5. **Convert Annotations:** Use `Rector`_ with the ``->withAttributeSets(behat: true)`` rule to automatically change + `Behat annotations`_ into PHP Attributes. +6. **Check Deprecations:** Run your tests with ``--fail-on-deprecations`` and fix any warnings that appear. +7. **Test the New Parser:** Enable the :doc:`GHERKIN_32 parser mode ` and see if your + tests still run correctly. If you have issues, you can fix your feature files or use + ``GherkinCompatibilityMode::LEGACY`` in your config. This mode will be removed in the future. + +Ready to upgrade? +~~~~~~~~~~~~~~~~~ + +Once you've completed the steps above, update your ``composer.json`` to start using Behat 4.0! + +.. caution:: + While we are in the alpha phase, we recommend using: + ``{"require": {"behat/behat": "4.0.0-alpha1@alpha"}}``. + +.. note:: + Don't forget to update your third-party extensions to versions that support Behat 4.0. If you find one that hasn't + been updated yet, consider helping out by submitting a Pull Request! The community's help makes the transition faster + for everyone. + + +Upgrading for extension authors +------------------------------- + +It's possible to support both Behat 3.x and 4.x at the same time (for example, by using +``{"require": {"behat/behat": "^3.x || ^4.x"}}``). + +If your project uses Behat to test itself, first follow the "Upgrading for users" steps above. + +Here are the key changes for all extension authors: + +* **Strict Types:** All interfaces and classes now use strict types for parameters, properties, and return values. As a + minimum, you will need to add return types to any methods that implement Behat interfaces or extend Behat classes. + `Rector`_ can automate this for you with the ``AddReturnTypeBasedOnParentClassMethodRector`` (included in the + ``typeDeclarations`` set). +* **Public API:** We are now stricter about what is considered public API. This helps us maintain a solid + :doc:`backwards compatibility promise `. If your extension needs to use code that + isn't marked public yet, please let us know. +* **Full Class Names:** Users can no longer use "short names" for extensions (like ``Behat\MinkExtension``). They must + now use the fully-qualified class name of your ``Extension`` class. Please update your documentation to reflect this. +* **Deprecations:** If your extension needs to report deprecations, we recommend using + ``Behat\Testwork\Deprecation\DeprecationCollector::trigger()`` (available since 3.30.0) instead of ``trigger_error``. + This ensures they are correctly handled by Behat's deprecation flags regardless of the user's runtime environment. +* **Event Changes:** The ``ScenarioLikeTested`` base event class has been removed. ``ScenarioTested`` and + ``BackgroundTested`` are now separate. This may affect you if you maintain a formatter extension. + +There are several other changes that might affect a minority of extension authors. See the full +`CHANGELOG`_ for details. + +Planned changes before the final 4.0.0 release +---------------------------------------------- + +We plan to make two more significant changes before the final 4.0.0 release: + +* **Parameter Matching:** We are reviewing how steps behave when the number of function parameters doesn't match the + step definition. This will likely trigger a deprecation or a failure. You can follow the progress in `#1691`_. +* **PHPUnit Assertions:** Support for rendering PHPUnit assertion failures will move to a standalone extension. While + tests will still pass or fail, the output will be less detailed without the extension. We no longer recommend using + PHPUnit for assertions within Behat steps, as the PHPUnit project has confirmed this is not supported. See + `#1746`_ for details. + +We may make additional changes based on feedback from the community as more people begin to upgrade. + +.. _`convert it to PHP`: https://docs.behat.org/en/v3.x/user_guide/configuration/yaml_configuration.html#converting-your-configuration +.. _`Rector`: https://getrector.com/documentation +.. _`Behat annotations`: https://docs.behat.org/en/v3.x/user_guide/annotations.html#existing-code +.. _`AddReturnTypeBasedOnParentClassMethodRector`: https://getrector.com/rule-detail/add-return-type-declaration-based-on-parent-class-method-rector +.. _`CHANGELOG`: https://github.com/Behat/Behat/blob/4.x/CHANGELOG.md +.. _`#1691`: https://github.com/Behat/Behat/issues/1691 +.. _`#1746`: https://github.com/Behat/Behat/issues/1746 diff --git a/user_guide/annotations.rst b/user_guide/annotations.rst deleted file mode 100644 index 2abc910..0000000 --- a/user_guide/annotations.rst +++ /dev/null @@ -1,118 +0,0 @@ -Annotations -=========== - -Historically Behat used doc-block annotations instead of attributes to define steps, hooks and -transformations in PHP contexts. These annotations are still available for now, and you can use them instead -of PHP attributes in your projects - however they will likely be deprecated and removed in the future. - -Step Annotations ----------------- - -Here is an example of how you can define your steps using annotations: - -.. code-block:: php - - // features/bootstrap/FeatureContext.php - - use Behat\Behat\Context\Context; - - class FeatureContext implements Context - { - /* - * @Given we have some context - */ - public function prepareContext() - { - // do something - } - - /* - * @When an :event occurs - */ - public function onEvent(string $event) - { - // do something - } - - /* - * @Then something should be done - */ - public function checkOutcomes() - { - // do something - } - } - -The pattern that you would include as an argument to the step attribute should be listed here -after the annotation, separated by a space - -Hook Annotations ----------------- - -Here is an example of how you can define your hooks using annotations: - -.. code-block:: php - - // features/bootstrap/FeatureContext.php - - use Behat\Behat\Context\Context; - use Behat\Testwork\Hook\Scope\BeforeSuiteScope; - use Behat\Behat\Hook\Scope\AfterScenarioScope; - - class FeatureContext implements Context - { - /* - * @BeforeSuite - */ - public static function prepare(BeforeSuiteScope $scope) - { - } - - /* - * @AfterScenario @database - */ - public function cleanDB(AfterScenarioScope $scope) - { - } - } - -Transformation Annotations --------------------------- - -Here is an example of how you can define your transformations using annotations: - -.. code-block:: php - - // features/bootstrap/FeatureContext.php - - use Behat\Behat\Context\Context; - - class FeatureContext implements Context - { - /* - * @Transform /^(\d+)$/ - */ - public function castStringToNumber($string) - { - return intval($string); - } - } - -Existing code -------------- - -Even though annotations are still available, they will probably be deprecated and eventually removed in the future. -Therefore, we do not recommend using annotations for new projects. If your current project uses annotations, we -recommend that you refactor your code to use PHP attributes instead. This can be done manually but you should be able -to use the search and replace capabilities of your IDE to do this in a more automated way. - -Alternatively you may want to use a tool like `Rector`_ which can do automated refactoring of your code. Rector 2.0 -includes a rule that allows you to automatically convert any doc-block annotations to the corresponding attributes. -To use it for your Behat contexts, add the following option to your Rector configuration: - -.. code-block:: php - - ->withAttributesSets(behat: true) - -.. _`Rector`: https://github.com/rectorphp/rector - diff --git a/user_guide/configuration.rst b/user_guide/configuration.rst index b5db886..0873aef 100644 --- a/user_guide/configuration.rst +++ b/user_guide/configuration.rst @@ -9,24 +9,15 @@ profiles. configuration/suites.rst configuration/printing_paths.rst - configuration/yaml_configuration.rst ``behat.php`` ------------- -All configuration happens inside a single configuration file in the ``PHP`` or the ``YAML`` -format. By default, Behat loads the configuration from the first file matching: +All configuration happens inside a single PHP configuration file. By default, Behat loads +the configuration from your current working directory from the first file matching: -#. ``behat.yaml`` or ``behat.yml`` -#. ``behat.yaml.dist`` or ``behat.yml.dist`` -#. ``behat.dist.yaml`` or ``behat.dist.yml`` #. ``behat.php`` #. ``behat.dist.php`` -#. ``config/behat.yaml`` or ``config/behat.yml`` -#. ``config/behat.yaml.dist`` or ``config/behat.yml.dist`` -#. ``config/behat.dist.yaml`` or ``config/behat.dist.yml`` -#. ``config/behat.php`` -#. ``config/behat.dist.php`` You can also tell Behat where your config file is with the ``--config`` option: @@ -34,10 +25,15 @@ You can also tell Behat where your config file is with the ``--config`` option: $ behat --config custom-config.php -All configuration parameters in that file are defined under a profile name root -(``default:`` for example). A profile is just a custom name you can use to -quickly switch testing configuration by using the ``--profile`` option when -executing your feature suite. +.. note:: + + From Behat 4.0, we no longer support the old YAML config format. You can + automatically convert this to PHP before you upgrade - see + :doc:`the 4.0 upgrade guide `. + +All configuration parameters in that file are defined under a profile. A profile is just +a custom name you can use to quickly switch testing configuration by using the +``--profile`` option when executing your feature suite. The default profile is always ``default``. All other profiles inherit parameters from the ``default`` profile. If you only need one profile, define @@ -428,12 +424,13 @@ Extensions can be configured like this: use Behat\Config\Config; use Behat\Config\Profile; use Behat\Config\Formatter\PrettyFormatter; + use Behat\MinkExtension\ServiceContainer\MinkExtension; return new Config() ->withProfile( new Profile('default') >withExtension( - new Extension('Behat\MinkExtension', [ + new Extension(MinkExtension::class, [ 'base_url' => 'http://www.example.com', 'selenium2' => null, ]) diff --git a/user_guide/configuration/suites.rst b/user_guide/configuration/suites.rst index 724044f..00aa704 100644 --- a/user_guide/configuration/suites.rst +++ b/user_guide/configuration/suites.rst @@ -8,7 +8,7 @@ concrete features together with the information on how to test them. 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: +really powerful and ``behat.php`` makes them that much more powerful: .. code-block:: php @@ -161,9 +161,9 @@ This will cause Behat to: .. note:: - ``%paths.base%`` is a special variable in ``behat.yml`` that refers - to the folder in which ``behat.yml`` is stored. When using it, or - any other percent-encased variable, it has to be put in quotes. + ``%paths.base%`` is a special placeholder in Behat configuration that + refers to the directory containing the currently active config file. + By default this will be the working directory where you are running Behat. Path-based suites are an easy way to test highly-modular applications where features are delivered by highly decoupled components. With suites diff --git a/user_guide/configuration/yaml_configuration.rst b/user_guide/configuration/yaml_configuration.rst deleted file mode 100644 index 6cb6e9e..0000000 --- a/user_guide/configuration/yaml_configuration.rst +++ /dev/null @@ -1,66 +0,0 @@ -Yaml configuration -================== - -Currently the preferred way to define the configuration for your Behat project -is by using one or more files with PHP configuration. - -But historically this configuration could also be expressed in files in the Yaml -format. This possibility is still available for now, and you can use it instead -of PHP configuration in your projects - however it will likely be deprecated and -removed in the future. - -Here is an example of how some configuration could look using a Yaml file: - -.. code-block:: yaml - - imports: - - imported.yaml - - default: - formatters: - progress: ~ - junit: false - suites: - my_suite: - contexts: - - MyContext - paths: - - "one.feature" - filters: - tags: "@run" - extensions: - MyCustomExtension: ~ - -Converting your configuration ------------------------------ - -If your project uses the legacy Yaml format for your configuration, you can easily -convert them to the PHP format by using the built in config converter. - -To use it, just run: - -.. code-block:: bash - - vendor/bin/behat --convert-config - -This will load the default config file loaded by your project and convert it from the -Yaml format to the PHP format. It will also convert any config files that are imported -by this main file. It will then remove the old Yaml files. - -We recommend carefully reviewing the generated config, particularly if you are using extensions, -custom formatters, or have complex configuration files. - -If you want to convert any other config file which is not your default config file (for -example a config file used in the CI environment), just load it with the ``-c`` -(or ``--config``) option like this: - -.. code-block:: bash - - vendor/bin/behat --convert-config -c ci-behat.yml - -This will load the ``ci-behat.yml`` config file and convert it to the PHP format. - -.. note:: - - Behat needs to be able to load this config file before converting it, so it must be - a valid Behat config file. diff --git a/user_guide/initialize.rst b/user_guide/initialize.rst index 4552c6e..034dc24 100644 --- a/user_guide/initialize.rst +++ b/user_guide/initialize.rst @@ -45,5 +45,5 @@ Suite Initialisation Suites are a core part of Behat. Any feature of Behat knows about them and can give you a hand with them. For example, if you defined -your suites in ``behat.yml`` before running ``--init``, it will actually +your suites in ``behat.php`` before running ``--init``, it will actually create the folders and suites you configured, instead of the default ones.