diff --git a/CHANGES.rst b/CHANGES.rst index e7fc26f6..d3952941 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -65,14 +65,14 @@ Unreleased - Improved fixture injection by adding seamless fixtures on plugin/module collection 2.1.4 ----------- +----- - Add support for Python 3.12 in CI - Add support for pytest 8 - Switch to the official Gherkin package: https://pypi.org/project/ci-environment/ - Fix other compatibility issues 2.1.0 ----------- +----- - Add validation for legacy cucumber.json output - Migrated to Pydantic 2 - Add tests for PyPy @@ -99,8 +99,7 @@ Unreleased - hook 2.0.0 ----------- - +----- - Reviewed StructBdd step collection; no more ``as_test`` / ``as_test_decorator`` Step methods are needed directly used - Drop python 3.7 - Move StructBDD model to Pydantic @@ -119,13 +118,11 @@ Unreleased - Remove legacy feature parser (and surplus features of it) - Remove outdated migration script - 1.2.3 ----------- +----- - Features could be autoloaded by --feature-autoload cli option - Remove possibility to manually register imported steps; They are registered automatically - 1.2.2 ----- - Add possibility to register imported steps @@ -152,7 +149,6 @@ Unreleased 1.0.0 ----- - - Default step parameter parser is switched to cfparse. String step name is compiled to cfparse - Step functions could get compiled instances of parse, cfparse and re.compile directly - Drop pytest 4 @@ -212,7 +208,6 @@ This release introduces breaking changes, please refer to the `Migration from 4. 4.0.0 ##### - This release introduces breaking changes, please refer to the `Migration from 3.x.x`. - Strict Gherkin option is removed (``@scenario()`` does not accept the ``strict_gherkin`` parameter). (olegpidsadnyi) @@ -227,13 +222,11 @@ This release introduces breaking changes, please refer to the `Migration from 3. 3.4.0 ##### - - Parse multiline steps according to the gherkin specification #365. 3.3.0 ##### - - Drop support for pytest < 4.3. - Fix a Python 4.0 bug. - Fix ``pytest --generate-missing`` functionality being broken. @@ -243,24 +236,20 @@ This release introduces breaking changes, please refer to the `Migration from 3. 3.2.1 ##### - - Fix regression introduced in 3.2.0 where pytest-bdd would break in presence of test items that are not functions. 3.2.0 ##### - - Fix Python 3.8 support - Remove code that rewrites code. This should help with the maintenance of this project and make debugging easier. 3.1.1 ##### - - Allow unicode string in ``@given()`` step names when using python2. This makes the transition of projects from python 2 to 3 easier. 3.1.0 ##### - - Drop support for pytest < 3.3.2. - Step definitions generated by ``$ pytest-bdd generate`` will now raise ``NotImplementedError`` by default. - ``@given(...)`` no longer accepts regex objects. It was deprecated long ago. @@ -269,30 +258,25 @@ This release introduces breaking changes, please refer to the `Migration from 3. 3.0.2 ##### - - Add compatibility with pytest 4.2 (sliwinski-milosz) #288. 3.0.1 ##### - - Minimal supported version of `pytest` is now 2.9.0 as lower versions do not support `bool` type ini options (sliwinski-milosz) #260 - Fix RemovedInPytest4Warning warnings (sliwinski-milosz) #261. 3.0.0 ##### - - Fixtures `pytestbdd_feature_base_dir` and `pytestbdd_strict_gherkin` have been removed. Check the `Migration of your tests from versions 2.x.x `_ for more information (sliwinski-milosz) #255 - Fix step definitions not being found when using parsers or converters after a change in pytest (youtux) #257 2.21.0 ###### - - Gherkin terminal reporter expanded format (pauk-slon) 2.20.0 ###### - - Added support for But steps (olegpidsadnyi) - Fixed compatibility with pytest 3.3.2 (olegpidsadnyi) - MInimal required version of pytest is now 2.8.1 since it doesn't support earlier versions (olegpidsadnyi) @@ -300,38 +284,31 @@ This release introduces breaking changes, please refer to the `Migration from 3. 2.19.0 ###### - - Added --cucumber-json-expanded option for explicit selection of expanded format (mjholtkamp) - Step names are filled in when --cucumber-json-expanded is used (mjholtkamp) 2.18.2 ###### - - Fix check for out section steps definitions for no strict gherkin feature 2.18.1 ###### - - Relay fixture results to recursive call of 'get_features' (coddingtonbear) 2.18.0 ###### - - Add gherkin terminal reporter (spinus + thedrow) 2.17.2 ###### - - Fix scenario lines containing an ``@`` being parsed as a tag. (The-Compiler) 2.17.1 ###### - - Add support for pytest 3.0 2.17.0 ###### - - Fix FixtureDef signature for newer pytest versions (The-Compiler) - Better error explanation for the steps defined outside of scenarios (olegpidsadnyi) - Add a ``pytest_bdd_apply_tag`` hook to customize handling of tags (The-Compiler) @@ -341,159 +318,129 @@ This release introduces breaking changes, please refer to the `Migration from 3. 2.16.1 ###### - - Cleaned up hooks of the plugin (olegpidsadnyi) - Fixed report serialization (olegpidsadnyi) 2.16.0 ###### - - Fixed deprecation warnings with pytest 2.8 (The-Compiler) - Fixed deprecation warnings with Python 3.5 (The-Compiler) 2.15.0 ###### - - Add examples data in the scenario report (bubenkoff) 2.14.5 ###### - - Properly parse feature description (bubenkoff) 2.14.3 ###### - - Avoid potentially random collection order for xdist compartibility (bubenkoff) 2.14.1 ###### - - Pass additional arguments to parsers (bubenkoff) 2.14.0 ###### - - Add validation check which prevents having multiple features in a single feature file (bubenkoff) 2.13.1 ###### - - Allow mixing feature example table with scenario example table (bubenkoff, olegpidsadnyi) 2.13.0 ###### - - Feature example table (bubenkoff, sureshvv) 2.12.2 ###### - - Make it possible to relax strict Gherkin scenario validation (bubenkoff) 2.11.3 ###### - - Fix minimal `six` version (bubenkoff, dustinfarris) 2.11.1 ###### - - Mention step type on step definition not found errors and in code generation (bubenkoff, lrowe) 2.11.0 ###### - - Prefix step definition fixture names to avoid name collisions (bubenkoff, lrowe) 2.10.0 ###### - - Make feature and scenario tags to be fully compartible with pytest markers (bubenkoff, kevinastone) 2.9.1 ##### - - Fixed FeatureError string representation to correctly support python3 (bubenkoff, lrowe) 2.9.0 ##### - - Added possibility to inject fixtures from given keywords (bubenkoff) 2.8.0 ##### - - Added hook before the step is executed with evaluated parameters (olegpidsadnyi) 2.7.2 ##### - - Correct base feature path lookup for python3 (bubenkoff) 2.7.1 ##### - - Allow to pass ``scope`` for ``given`` steps (bubenkoff, sureshvv) 2.7.0 ##### - - Implemented `scenarios` shortcut to automatically bind scenarios to tests (bubenkoff) 2.6.2 ##### - - Parse comments only in the beginning of words (santagada) 2.6.1 ##### - - Correctly handle `pytest-bdd` command called without the subcommand under python3 (bubenkoff, spinus) - Pluggable parsers for step definitions (bubenkoff, spinus) 2.5.3 ##### - - Add after scenario hook, document both before and after scenario hooks (bubenkoff) 2.5.2 ##### - - Fix code generation steps ordering (bubenkoff) 2.5.1 ##### - - Fix error report serialization (olegpidsadnyi) 2.5.0 ##### - - Fix multiline steps in the Background section (bubenkoff, arpe) - Code cleanup (olegpidsadnyi) 2.4.5 ##### - - Fix unicode issue with scenario name (bubenkoff, aohontsev) 2.4.3 ##### - - Fix unicode regex argumented steps issue (bubenkoff, aohontsev) - Fix steps timings in the json reporting (bubenkoff) 2.4.2 ##### - - Recursion is fixed for the --generate-missing and the --feature parameters (bubenkoff) 2.4.1 ##### - - Better reporting of a not found scenario (bubenkoff) - Simple test code generation implemented (bubenkoff) - Correct timing values for cucumber json reporting (bubenkoff) @@ -501,51 +448,42 @@ This release introduces breaking changes, please refer to the `Migration from 3. 2.4.0 ##### - - Background support added (bubenkoff) - Fixed double collection of the conftest files if scenario decorator is used (ropez, bubenkoff) 2.3.3 ##### - - Added timings to the cucumber json report (bubenkoff) 2.3.2 ##### - - Fixed incorrect error message using e.argname instead of step.name (hvdklauw) 2.3.1 ##### - - Implemented cucumber tags support (bubenkoff) - Implemented cucumber json formatter (bubenkoff, albertjan) - Added 'trace' keyword (bubenkoff) 2.1.2 ##### - - Latest pytest compartibility fixes (bubenkoff) 2.1.1 ##### - - Bugfixes (bubenkoff) 2.1.0 ##### - - Implemented multiline steps (bubenkoff) 2.0.1 ##### - - Allow more than one parameter per step (bubenkoff) - Allow empty example values (bubenkoff) 2.0.0 ##### - - Pure pytest parametrization for scenario outlines (bubenkoff) - Argumented steps now support converters (transformations) (bubenkoff) - scenario supports only decorator form (bubenkoff) @@ -553,69 +491,56 @@ This release introduces breaking changes, please refer to the `Migration from 3. 1.0.0 ##### - - Implemented scenario outlines (bubenkoff) 0.6.11 ###### - - Fixed step arguments conflict with the fixtures having the same name (olegpidsadnyi) 0.6.9 ##### - - Implemented support of Gherkin "Feature:" (olegpidsadnyi) 0.6.8 ##### - - Implemented several hooks to allow reporting/error handling (bubenkoff) 0.6.6 ##### - - Fixes to unnecessary mentioning of pytest-bdd package files in py.test log with -v (bubenkoff) 0.6.5 ##### - -- Compartibility with recent pytest (bubenkoff) +- Compatibility with recent pytest (bubenkoff) 0.6.4 ##### - - More unicode fixes (amakhnach) 0.6.3 ##### - - Added unicode support for feature files. Removed buggy module replacement for scenario. (amakhnach) 0.6.2 ##### - - Removed unnecessary mention of pytest-bdd package files in py.test log with -v (bubenkoff) 0.6.1 ##### - - Step arguments in whens when there are no given arguments used. (amakhnach, bubenkoff) 0.6.0 ##### - - Added step arguments support. (curzona, olegpidsadnyi, bubenkoff) - Added checking of the step type order. (markon, olegpidsadnyi) 0.5.2 ##### - - Added extra info into output when FeatureError exception raises. (amakhnach) 0.5.0 ##### - - Added parametrization to scenarios - Coveralls.io integration - Test coverage improvement/fixes @@ -623,20 +548,16 @@ This release introduces breaking changes, please refer to the `Migration from 3. 0.4.7 ##### - - Fixed Python 3.3 support 0.4.6 ##### - - Fixed a bug when py.test --fixtures showed incorrect filenames for the steps. 0.4.5 ##### - - Fixed a bug with the reuse of the fixture by given steps being evaluated multiple times. 0.4.3 ##### - - Update the license file and PYPI related documentation. diff --git a/docs/features.rst b/docs/features.rst index 6dc87305..6ba98525 100644 --- a/docs/features.rst +++ b/docs/features.rst @@ -1,135 +1,167 @@ -.. NOTE:: Features below are part of end-to-end test suite; You always could find most specific - use cases of **pytest-bdd-ng** by investigation of its regression - test suite https://github.com/elchupanebrej/pytest-bdd-ng/tree/default/tests - -Tutrorial/Launch.feature -"""""""""""""""""""""""" - -.. include:: ../features/Tutrorial/Launch.feature - :code: gherkin - -Feature/Localization.feature -"""""""""""""""""""""""""""" - -.. include:: ../features/Feature/Localization.feature - :code: gherkin - -Feature/Description.feature -""""""""""""""""""""""""""" - -.. include:: ../features/Feature/Description.feature - :code: gherkin - -Feature/Tag conversion.feature -"""""""""""""""""""""""""""""" - -.. include:: ../features/Feature/Tag conversion.feature - :code: gherkin - -Feature/Tag.feature -""""""""""""""""""" - -.. include:: ../features/Feature/Tag.feature - :code: gherkin - -Step/Doc string.feature -""""""""""""""""""""""" - -.. include:: ../features/Step/Doc string.feature - :code: gherkin - -Step/Data table.feature -""""""""""""""""""""""" - -.. include:: ../features/Step/Data table.feature - :code: gherkin - -Step/Step definition bounding.feature -""""""""""""""""""""""""""""""""""""" - -.. include:: ../features/Step/Step definition bounding.feature - :code: gherkin - -Step definition/Target fixtures specification.feature -""""""""""""""""""""""""""""""""""""""""""""""""""""" - -.. include:: ../features/Step definition/Target fixtures specification.feature - :code: gherkin - -Step definition/Pytest fixtures substitution.feature -"""""""""""""""""""""""""""""""""""""""""""""""""""" - -.. include:: ../features/Step definition/Pytest fixtures substitution.feature - :code: gherkin - -Scenario/Description.feature -"""""""""""""""""""""""""""" - -.. include:: ../features/Scenario/Description.feature - :code: gherkin - -Scenario/Tag.feature -"""""""""""""""""""" - -.. include:: ../features/Scenario/Tag.feature - :code: gherkin - -Feature/Load/Scenario search from base url.feature -################################################## - -.. include:: ../features/Feature/Load/Scenario search from base url.feature - :code: gherkin - -Feature/Load/Autoload.feature -############################# - -.. include:: ../features/Feature/Load/Autoload.feature - :code: gherkin - -Feature/Load/Scenario function loader.feature -############################################# - -.. include:: ../features/Feature/Load/Scenario function loader.feature - :code: gherkin - -Feature/Load/Scenario search from base directory.feature -######################################################## - -.. include:: ../features/Feature/Load/Scenario search from base directory.feature - :code: gherkin - -Step definition/Parameters/Defaults.feature -########################################### - -.. include:: ../features/Step definition/Parameters/Defaults.feature - :code: gherkin - -Step definition/Parameters/Injection as fixtures.feature -######################################################## - -.. include:: ../features/Step definition/Parameters/Injection as fixtures.feature - :code: gherkin - -Step definition/Parameters/Conversion.feature -############################################# - -.. include:: ../features/Step definition/Parameters/Conversion.feature - :code: gherkin - -Step definition/Parameters/Parsing by custom parser.feature -########################################################### - -.. include:: ../features/Step definition/Parameters/Parsing by custom parser.feature - :code: gherkin - -Step definition/Parameters/Parsing.feature -########################################## - -.. include:: ../features/Step definition/Parameters/Parsing.feature - :code: gherkin - -Scenario/Outline/Examples Tag.feature -##################################### - -.. include:: ../features/Scenario/Outline/Examples Tag.feature - :code: gherkin +Features +======== + +.. NOTE:: Features below are part of end-to-end test suite; You always could find most specific + use cases of **pytest-bdd-ng** by investigation of its regression + test suite https://github.com/elchupanebrej/pytest-bdd-ng/tree/default/tests + + + +Tutrorial +--------- + +Launch.feature +############## + +.. include:: ../features/Tutrorial/Launch.feature + :code: gherkin + +Tutorial +-------- + +Step definition +--------------- + +Pytest fixtures substitution.feature +#################################### + +.. include:: ../features/Step definition/Pytest fixtures substitution.feature + :code: gherkin + +Target fixtures specification.feature +##################################### + +.. include:: ../features/Step definition/Target fixtures specification.feature + :code: gherkin + +Parameters +########## + +Conversion.feature +!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Step definition/Parameters/Conversion.feature + :code: gherkin + +Defaults.feature +!!!!!!!!!!!!!!!! + +.. include:: ../features/Step definition/Parameters/Defaults.feature + :code: gherkin + +Injection as fixtures.feature +!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Step definition/Parameters/Injection as fixtures.feature + :code: gherkin + +Parsing by custom parser.feature +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Step definition/Parameters/Parsing by custom parser.feature + :code: gherkin + +Parsing.feature +!!!!!!!!!!!!!!! + +.. include:: ../features/Step definition/Parameters/Parsing.feature + :code: gherkin + +Step +---- + +Data table.feature +################## + +.. include:: ../features/Step/Data table.feature + :code: gherkin + +Doc string.feature +################## + +.. include:: ../features/Step/Doc string.feature + :code: gherkin + +Step definition bounding.feature +################################ + +.. include:: ../features/Step/Step definition bounding.feature + :code: gherkin + +Scenario +-------- + +Description.feature +################### + +.. include:: ../features/Scenario/Description.feature + :code: gherkin + +Tag.feature +########### + +.. include:: ../features/Scenario/Tag.feature + :code: gherkin + +Outline +####### + +Examples Tag.feature +!!!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Scenario/Outline/Examples Tag.feature + :code: gherkin + +Feature +------- + +Description.feature +################### + +.. include:: ../features/Feature/Description.feature + :code: gherkin + +Localization.feature +#################### + +.. include:: ../features/Feature/Localization.feature + :code: gherkin + +Tag conversion.feature +###################### + +.. include:: ../features/Feature/Tag conversion.feature + :code: gherkin + +Tag.feature +########### + +.. include:: ../features/Feature/Tag.feature + :code: gherkin + +Load +#### + +Autoload.feature +!!!!!!!!!!!!!!!! + +.. include:: ../features/Feature/Load/Autoload.feature + :code: gherkin + +Scenario function loader.feature +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Feature/Load/Scenario function loader.feature + :code: gherkin + +Scenario search from base directory.feature +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Feature/Load/Scenario search from base directory.feature + :code: gherkin + +Scenario search from base url.feature +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. include:: ../features/Feature/Load/Scenario search from base url.feature + :code: gherkin diff --git a/features/Feature/Localization.feature b/features/Feature/Localization.feature index aed9944c..f563dc60 100644 --- a/features/Feature/Localization.feature +++ b/features/Feature/Localization.feature @@ -1,5 +1,6 @@ Feature: Scenarios tags could be localized - pytest-bdd-ng supports all localizations which Gherkin does: https://cucumber.io/docs/gherkin/languages/ + pytest-bdd-ng supports all localizations which + Gherkin does: https://cucumber.io/docs/gherkin/languages/ Scenario: Given File "Localized.feature" with content: diff --git a/features/Scenario/Description.feature b/features/Scenario/Description.feature index 38e58885..e6f4b0d8 100644 --- a/features/Scenario/Description.feature +++ b/features/Scenario/Description.feature @@ -1,7 +1,9 @@ Feature: Descriptions - Free-form descriptions can be placed underneath Feature, Example/Scenario, Background, Scenario Outline and Rule. + Free-form descriptions can be placed + underneath Feature, Example/Scenario, Background, Scenario Outline and Rule. You can write anything you like, as long as no line starts with a keyword. - Descriptions can be in the form of Markdown - formatters including the official HTML formatter support this. + Descriptions can be in the form of Markdown - formatters including + the official HTML formatter support this. Scenario: Given File "Description.feature" with content: diff --git a/features/Step definition/Parameters/Conversion.feature b/features/Step definition/Parameters/Conversion.feature index c2afb355..9399e7ff 100644 --- a/features/Step definition/Parameters/Conversion.feature +++ b/features/Step definition/Parameters/Conversion.feature @@ -30,7 +30,8 @@ Feature: Step definitions parameters conversion | 1| Rule: for anonymous groups - Step definitions parameters could not have a name, so we have to name them before conversion + Step definitions parameters could not have a name, so + we have to name them before conversion Scenario: Given File "conftest.py" with content: @@ -42,7 +43,11 @@ Feature: Step definitions parameters conversion class Item(Enum): CUCUMBER = 'cucumber' - @given(parse(r"I have a (\w+)"), anonymous_group_names=('item',), converters=dict(item=Item)) + @given( + parse(r"I have a (\w+)"), + anonymous_group_names=('item',), + converters=dict(item=Item) + ) def i_have_item(item): assert item == Item.CUCUMBER """ @@ -60,12 +65,19 @@ Feature: Step definitions parameters conversion from cucumber_expressions.expression import CucumberExpression from cucumber_expressions.parameter_type_registry import ParameterTypeRegistry - parse = partial(CucumberExpression, parameter_type_registry = ParameterTypeRegistry()) + parse = partial( + CucumberExpression, + parameter_type_registry = ParameterTypeRegistry() + ) class Item(Enum): CUCUMBER = 'cucumber' - @given(parse(r"I have a {word}"), anonymous_group_names=('item',), converters=dict(item=Item)) + @given( + parse(r"I have a {word}"), + anonymous_group_names=('item',), + converters=dict(item=Item) + ) def i_have_item(item): assert item == Item.CUCUMBER """ diff --git a/features/Step definition/Parameters/Defaults.feature b/features/Step definition/Parameters/Defaults.feature index 52fee817..3f1e632e 100644 --- a/features/Step definition/Parameters/Defaults.feature +++ b/features/Step definition/Parameters/Defaults.feature @@ -27,7 +27,11 @@ Feature: Step definitions parameters could have default values return [Freshness.FRESH, Freshness.ROTTEN, Freshness.FRESH, Freshness.SALTED] @given("I have a pickle", param_defaults=dict(freshness=Freshness.SALTED)) - @given(parse(r"I have a ((?P\w+)\s)?cucumber"), converters=dict(freshness=Freshness), param_defaults=dict(freshness=Freshness.FRESH)) + @given( + parse(r"I have a ((?P\w+)\s)?cucumber"), + converters=dict(freshness=Freshness), + param_defaults=dict(freshness=Freshness.FRESH) + ) def i_have_cucumber(freshness, oracle_freshness): assert freshness == oracle_freshness.pop(0) """ diff --git a/features/Step definition/Parameters/Injection as fixtures.feature b/features/Step definition/Parameters/Injection as fixtures.feature index c5a34df8..be5ec090 100644 --- a/features/Step definition/Parameters/Injection as fixtures.feature +++ b/features/Step definition/Parameters/Injection as fixtures.feature @@ -1,8 +1,9 @@ Feature: Step definitions parameters injection as fixtures - Step arguments are injected into step context and could be used - as normal fixtures with the names equal to the names of the arguments by default. + Step arguments are injected into step context and could be used as normal + fixtures with the names equal to the names of the arguments by default. - Step's argument are accessible as a fixture in other step function just by mentioning it as an argument + Step's argument are accessible as a fixture in other step function just + by mentioning it as an argument If the name of the step argument clashes with existing fixture, it will be overridden by step's argument value. @@ -16,7 +17,10 @@ Feature: Step definitions parameters injection as fixtures from pytest_bdd import given, then @given("I have a pickle", param_defaults=dict(freshness='salted')) - @given(parse(r"I have a ((?P\w+)\s)?cucumber"), param_defaults=dict(freshness='fresh')) + @given( + parse(r"I have a ((?P\w+)\s)?cucumber"), + param_defaults=dict(freshness='fresh') + ) def i_have_cucumber(freshness): ... @@ -65,8 +69,18 @@ Feature: Step definitions parameters injection as fixtures from re import compile as parse from pytest_bdd import given, then - @given("I have a pickle", param_defaults=dict(freshness='salted'), params_fixtures_mapping={...:None}, target_fixtures=['cuke_taste']) - @given(parse(r"I have a ((?P\w+)\s)?cucumber"), param_defaults=dict(freshness='fresh'), params_fixtures_mapping=False, target_fixture='cuke_taste') + @given( + "I have a pickle", + param_defaults=dict(freshness='salted'), + params_fixtures_mapping={...:None}, + target_fixtures=['cuke_taste'] + ) + @given( + parse(r"I have a ((?P\w+)\s)?cucumber"), + param_defaults=dict(freshness='fresh'), + params_fixtures_mapping=False, + target_fixture='cuke_taste' + ) def i_have_cucumber(freshness): assert freshness is not None yield freshness @@ -105,8 +119,16 @@ Feature: Step definitions parameters injection as fixtures from re import compile as parse from pytest_bdd import given, then - @given("I have a pickle", param_defaults=dict(freshness='salted'), params_fixtures_mapping={"freshness":"cuke_taste"}) - @given(parse(r"I have a ((?P\w+)\s)?cucumber"), param_defaults=dict(freshness='fresh'), params_fixtures_mapping={"freshness":"cuke_taste"}) + @given( + "I have a pickle", + param_defaults=dict(freshness='salted'), + params_fixtures_mapping={"freshness":"cuke_taste"} + ) + @given( + parse(r"I have a ((?P\w+)\s)?cucumber"), + param_defaults=dict(freshness='fresh'), + params_fixtures_mapping={"freshness":"cuke_taste"} + ) def i_have_cucumber(cuke_taste, freshness): assert cuke_taste is not None assert freshness == cuke_taste @@ -146,7 +168,11 @@ Feature: Step definitions parameters injection as fixtures """python from pytest_bdd import given - @given("I have an old pickle", param_defaults=dict(freshness='salted', age='old'), params_fixtures_mapping={"freshness"}) + @given( + "I have an old pickle", + param_defaults=dict(freshness='salted', age='old'), + params_fixtures_mapping={"freshness"} + ) def i_have_cucumber(age, freshness): assert age == 'old' assert freshness == 'salted' diff --git a/features/Step definition/Parameters/Parsing by custom parser.feature b/features/Step definition/Parameters/Parsing by custom parser.feature index 5a447a46..20c2262c 100644 --- a/features/Step definition/Parameters/Parsing by custom parser.feature +++ b/features/Step definition/Parameters/Parsing by custom parser.feature @@ -14,7 +14,11 @@ Feature: Step definitions parameters parsing by custom parser class Parser(parsers.StepParser): def __init__(self, name, *args,**kwargs): self.name = name - self.regex = re.compile(re.sub("%(.+)%", r"(?P<\1>.+)", name), *args, **kwargs) + self.regex = re.compile( + re.sub("%(.+)%", r"(?P<\1>.+)", name), + *args, + **kwargs + ) def parse_arguments(self, request, name, **kwargs): __doc__ = "Parse step arguments" @@ -31,7 +35,11 @@ Feature: Step definitions parameters parsing by custom parser def __str__(self): return self.name - @given(Parser("there are %start% cucumbers"), target_fixture="start_cucumbers", converters=dict(start=int)) + @given( + Parser("there are %start% cucumbers"), + target_fixture="start_cucumbers", + converters=dict(start=int) + ) def start_cucumbers(start): assert start == 10 """ diff --git a/features/Step definition/Parameters/Parsing.feature b/features/Step definition/Parameters/Parsing.feature index 14faab04..a794127b 100644 --- a/features/Step definition/Parameters/Parsing.feature +++ b/features/Step definition/Parameters/Parsing.feature @@ -22,8 +22,9 @@ Feature: Step definitions parameters parsing """ Scenario: Heuristic parser guesses a type and builds particular parser to be applied - Tries to select right parser between string, cucumber_expression, cfparse and re. Any object that supports `__str__` - interface and does not support parser interface will be wrapped with this parser + Tries to select right parser between string, cucumber_expression, cfparse and re. + Any object that supports `__str__` interface and does not support parser interface + will be wrapped with this parser Given File "conftest.py" with content: """python @@ -40,12 +41,19 @@ Feature: Step definitions parameters parsing assert wallet == 'wallet' # cucumber expressions parser - @given("I have {int} Euro", anonymous_group_names=('euro',), converters=dict(euro=int)) + @given("I have {int} Euro", + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_have(euro, values): assert euro == values.pop(0) # parse parser - @when("I pay {} Euro", anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + "I pay {} Euro", + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_pay(euro, values): assert euro == values.pop(0) @@ -55,7 +63,11 @@ Feature: Step definitions parameters parsing assert euro == values.pop(0) # regular expression parser - @then(r"I should have (\d+) Euro", anonymous_group_names=('euro',), converters=dict(euro=int)) + @then( + r"I should have (\d+) Euro", + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_should_have(euro, values): assert euro == values.pop(0) """ @@ -98,11 +110,19 @@ Feature: Step definitions parameters parsing def i_pay(euro, values): assert euro == values.pop(0) - @when(parse("I lose {} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse("I lose {} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_pay(euro, values): assert euro == values.pop(0) - @then(parse(r"I should have {:d} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @then( + parse(r"I should have {:d} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_should_have(euro, values): assert euro == values.pop(0) """ @@ -145,11 +165,19 @@ Feature: Step definitions parameters parsing def i_pay(euro, values): assert euro == values.pop(0) - @when(parse("I lose {} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse("I lose {} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_pay(euro, values): assert euro == values.pop(0) - @then(parse(r"I should have {:d} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @then( + parse(r"I should have {:d} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_should_have(euro, values): assert euro == values.pop(0) @@ -161,7 +189,8 @@ Feature: Step definitions parameters parsing Scenario: by "cucumber-expressions" https://github.com/cucumber/cucumber-expressions - Cucumber Expressions is an alternative to Regular Expressions with a more intuitive syntax. + Cucumber Expressions is an alternative to Regular Expressions + with a more intuitive syntax. And File "conftest.py" with content: """python @@ -171,7 +200,10 @@ Feature: Step definitions parameters parsing from cucumber_expressions.parameter_type_registry import ParameterTypeRegistry from cucumber_expressions.expression import CucumberExpression - parse = partial(CucumberExpression, parameter_type_registry = ParameterTypeRegistry()) + parse = partial( + CucumberExpression, + parameter_type_registry = ParameterTypeRegistry() + ) @pytest.fixture def values(): @@ -181,19 +213,35 @@ Feature: Step definitions parameters parsing def i_have_wallet(wallet): assert wallet == 'wallet' - @given(parse("I have {int} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @given( + parse("I have {int} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_have(euro, values): assert euro == values.pop(0) - @when(parse("I pay {} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse("I pay {} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_pay(euro, values, request): assert euro == values.pop(0) - @when(parse(r"I lose {int} Dollar/Euro(s)"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse(r"I lose {int} Dollar/Euro(s)"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_lose(euro, values): assert euro == values.pop(0) - @then(parse("I should have {int} Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @then( + parse("I should have {int} Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_should_have(euro, values): assert euro == values.pop(0) """ @@ -204,7 +252,8 @@ Feature: Step definitions parameters parsing Scenario: by "cucumber-regular-expressions" https://github.com/cucumber/cucumber-expressions - Cucumber Expressions is an alternative to Regular Expressions with a more intuitive syntax. + Cucumber Expressions is an alternative + to Regular Expressions with a more intuitive syntax. And File "conftest.py" with content: """python @@ -213,9 +262,14 @@ Feature: Step definitions parameters parsing from functools import partial from cucumber_expressions.parameter_type_registry import ParameterTypeRegistry - from cucumber_expressions.regular_expression import RegularExpression as CucumberRegularExpression + from cucumber_expressions.regular_expression import ( + RegularExpression as CucumberRegularExpression + ) - parse = partial(CucumberRegularExpression, parameter_type_registry = ParameterTypeRegistry()) + parse = partial( + CucumberRegularExpression, + parameter_type_registry = ParameterTypeRegistry() + ) @pytest.fixture def values(): @@ -225,19 +279,35 @@ Feature: Step definitions parameters parsing def i_have_wallet(wallet): assert wallet == 'wallet' - @given(parse(r"I have (\d+) Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @given( + parse(r"I have (\d+) Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_have(euro, values): assert euro == values.pop(0) - @when(parse("I pay (.*) Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse("I pay (.*) Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_pay(euro, values, request): assert euro == values.pop(0) - @when(parse(r"I lose (.+) Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse(r"I lose (.+) Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_lose(euro, values): assert euro == values.pop(0) - @then(parse(r"I should have (\d+) Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @then( + parse(r"I should have (\d+) Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_should_have(euro, values): assert euro == values.pop(0) """ @@ -250,7 +320,8 @@ Feature: Step definitions parameters parsing This uses full regular expressions to parse the clause text. You will need to use named groups "(?P...)" to define the variables pulled from the text and passed to your "step()" function. - Type conversion can only be done via "converters" step decorator argument (see example in according feature). + Type conversion can only be done via "converters" step decorator + argument (see example in according feature). Given File "conftest.py" with content: """python @@ -270,11 +341,18 @@ Feature: Step definitions parameters parsing def i_have(euro, values): assert euro == values.pop(0) - @when(parse(r"I pay (\d+) Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when( + parse(r"I pay (\d+) Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_pay(euro, values): assert euro == values.pop(0) - @when(parse(r"I lose (.+) Euro"), anonymous_group_names=('euro',), converters=dict(euro=int)) + @when(parse(r"I lose (.+) Euro"), + anonymous_group_names=('euro',), + converters=dict(euro=int) + ) def i_lose(euro, values): assert euro == values.pop(0) diff --git a/src/pytest_bdd/script/bdd_tree_to_rst.py b/src/pytest_bdd/script/bdd_tree_to_rst.py index 3662bc43..0ea09aa4 100644 --- a/src/pytest_bdd/script/bdd_tree_to_rst.py +++ b/src/pytest_bdd/script/bdd_tree_to_rst.py @@ -15,7 +15,7 @@ from docopt import docopt -SECTION_SYMBOLS = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" +SECTION_SYMBOLS = "-#!\"$%&'()*+,./:;<=>?@[\\]^_`{|}~=" def convert(features_path: Path, output_file_path: Path): @@ -32,16 +32,28 @@ def convert(features_path: Path, output_file_path: Path): content += dedent( # language=rst """\ + Features + ======== + .. NOTE:: Features below are part of end-to-end test suite; You always could find most specific use cases of **pytest-bdd-ng** by investigation of its regression test suite https://github.com/elchupanebrej/pytest-bdd-ng/tree/default/tests - """ ) while processable_paths: processable_path = processable_paths.popleft() + processable_rel_path = processable_path.relative_to(features_path) + content += dedent( + # language=rst + f"""\ + {processable_rel_path.name} + {SECTION_SYMBOLS[len(processable_rel_path.parts) - 1] * len(processable_rel_path.name)} + + """ + ) + gherkin_file_paths = chain(processable_path.glob("*.gherkin"), processable_path.glob("*.feature")) struct_bdd_file_paths = processable_path.glob("*.bdd.yaml") @@ -52,8 +64,8 @@ def convert(features_path: Path, output_file_path: Path): content += dedent( # language=rst f"""\ - {rel_path.as_posix()} - {SECTION_SYMBOLS[len(rel_path.parts)-1]*len(str(rel_path))} + {rel_path.name} + {SECTION_SYMBOLS[len(rel_path.parts)-1]*len(rel_path.name)} .. include:: {(output_path_rel_to_features_path / path.relative_to(features_path)).as_posix()} :code: gherkin @@ -75,7 +87,7 @@ def convert(features_path: Path, output_file_path: Path): """ ) - processable_paths.extend(sub_processable_paths) + processable_paths.extendleft(sub_processable_paths) return content.rstrip("\n") + "\n" diff --git a/tests/doc/test_doc.py b/tests/doc/test_doc.py index c66fa568..b00adeb7 100644 --- a/tests/doc/test_doc.py +++ b/tests/doc/test_doc.py @@ -31,21 +31,29 @@ def test_doc_generation(testdir: "Testdir"): output = convert(features_path.resolve(), output_path.resolve()) assert output == dedent( # language=rst - '''\ + """\ + Features + ======== + .. NOTE:: Features below are part of end-to-end test suite; You always could find most specific use cases of **pytest-bdd-ng** by investigation of its regression test suite https://github.com/elchupanebrej/pytest-bdd-ng/tree/default/tests + + simple.gherkin - !!!!!!!!!!!!!! + -------------- .. include:: features/simple.gherkin :code: gherkin - extra/other_simple.gherkin - """""""""""""""""""""""""" + extra + ----- + + other_simple.gherkin + #################### .. include:: features/extra/other_simple.gherkin :code: gherkin - ''' + """ )