Skip to content

Commit 8fe17df

Browse files
committed
Fix making datatable and docstring available as kwargs
1 parent 42f7560 commit 8fe17df

File tree

4 files changed

+121
-5
lines changed

4 files changed

+121
-5
lines changed

README.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,9 @@ Leading indentation are stripped.
615615

616616
For example, the Gherkin docstring:
617617

618+
618619
.. code-block:: gherkin
620+
619621
"""
620622
This is a sample docstring.
621623
It spans multiple lines.
@@ -625,6 +627,7 @@ For example, the Gherkin docstring:
625627
Will be returned as:
626628

627629
.. code-block:: python
630+
628631
"This is a sample docstring.\nIt spans multiple lines."
629632
630633
@@ -645,7 +648,7 @@ Full example:
645648
646649
And a step provides a docstring with lower indentation
647650
"""
648-
This is a when docstring
651+
This is a docstring
649652
"""
650653
651654
And this step has no docstring
@@ -661,21 +664,22 @@ Full example:
661664
662665
from pytest_bdd import given, then
663666
667+
664668
@given("some steps will have docstrings")
665669
def _():
666670
pass
667671
668672
@then("a step has a docstring")
669673
def _(docstring):
670-
assert docstring == "This is a given docstring\non two lines"
674+
assert docstring == "This is a docstring\non two lines"
671675
672676
@then("a step provides a docstring with lower indentation")
673677
def _(docstring):
674-
assert docstring == "This is a when docstring"
678+
assert docstring == "This is a docstring"
675679
676680
@then("this step has a greater indentation")
677681
def _(docstring):
678-
assert docstring == "This is a when docstring"
682+
assert docstring == "This is a docstring"
679683
680684
@then("this step has no docstring")
681685
def _():

src/pytest_bdd/scenario.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from __future__ import annotations
1515

1616
import contextlib
17+
import inspect
1718
import logging
1819
import os
1920
import re
@@ -191,6 +192,7 @@ def _execute_step_function(
191192
converters = context.converters
192193
kwargs = {}
193194
args = get_args(context.step_func)
195+
signature = inspect.signature(context.step_func) # Get function signature
194196

195197
try:
196198
parsed_args = context.parser.parse_arguments(step.name)
@@ -209,7 +211,13 @@ def _execute_step_function(
209211
value = converters[arg](value)
210212
kwargs[arg] = value
211213

212-
kwargs = {arg: kwargs[arg] if arg in kwargs else request.getfixturevalue(arg) for arg in args}
214+
step_func_explicit_args = {arg: kwargs[arg] if arg in kwargs else request.getfixturevalue(arg) for arg in args}
215+
216+
if any(param.kind == param.VAR_KEYWORD for param in signature.parameters.values()):
217+
kwargs = {**kwargs, **step_func_explicit_args}
218+
else:
219+
kwargs = step_func_explicit_args
220+
213221
kw["step_func_args"] = kwargs
214222

215223
request.config.hook.pytest_bdd_before_step_call(**kw)

tests/datatable/test_datatable.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,62 @@ def test_datatable():
154154
result = pytester.runpytest("-s")
155155
result.assert_outcomes(failed=1)
156156
result.stdout.fnmatch_lines(["*fixture 'datatable' not found*"])
157+
158+
159+
def test_steps_with_datatable_missing_argument_in_step(pytester):
160+
pytester.makefile(
161+
".feature",
162+
missing_datatable_arg=textwrap.dedent(
163+
"""\
164+
Feature: Missing datatable
165+
166+
Scenario: Datatable arg is missing for a step definition
167+
Given this step has a datatable
168+
| name | email | age |
169+
| John | [email protected] | 30 |
170+
171+
When this step has a datatable but no datatable argument
172+
| name | email | age |
173+
| John | [email protected] | 30 |
174+
175+
Then the test passes
176+
"""
177+
),
178+
)
179+
pytester.makeconftest(
180+
textwrap.dedent(
181+
"""\
182+
from pytest_bdd import given, when, then
183+
184+
185+
@given("this step has a datatable")
186+
def _(datatable):
187+
print(datatable)
188+
189+
190+
@when("this step has a datatable but no datatable argument")
191+
def _():
192+
pass
193+
194+
195+
@then("the test passes")
196+
def _():
197+
pass
198+
199+
"""
200+
)
201+
)
202+
203+
pytester.makepyfile(
204+
textwrap.dedent(
205+
"""\
206+
from pytest_bdd import scenario
207+
208+
@scenario("missing_datatable_arg.feature", "Datatable arg is missing for a step definition")
209+
def test_datatable():
210+
pass
211+
"""
212+
)
213+
)
214+
result = pytester.runpytest("-s")
215+
result.assert_outcomes(passed=1)

tests/steps/test_docstring.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,51 @@ def test_docstring():
140140
result.stdout.fnmatch_lines(["*fixture 'docstring' not found*"])
141141

142142

143+
def test_steps_with_docstring_in_kwargs(pytester):
144+
pytester.makefile(
145+
".feature",
146+
docstring_kwarg=textwrap.dedent(
147+
'''\
148+
Feature: Docstring in kwargs
149+
150+
Scenario: Docstring is in step kwargs
151+
Given this step has a docstring
152+
"""
153+
This is a given docstring
154+
"""
155+
'''
156+
),
157+
)
158+
pytester.makeconftest(
159+
textwrap.dedent(
160+
"""\
161+
from pytest_bdd import given
162+
163+
164+
@given("this step has a docstring")
165+
def _(**kwargs):
166+
print(kwargs['docstring'])
167+
168+
169+
"""
170+
)
171+
)
172+
173+
pytester.makepyfile(
174+
textwrap.dedent(
175+
"""\
176+
from pytest_bdd import scenario
177+
178+
@scenario("docstring_kwarg.feature", "Docstring is in step kwargs")
179+
def test_docstring():
180+
pass
181+
"""
182+
)
183+
)
184+
result = pytester.runpytest("-s")
185+
result.assert_outcomes(passed=1)
186+
187+
143188
def test_steps_with_docstring_missing_argument_in_step_def(pytester):
144189
pytester.makefile(
145190
".feature",

0 commit comments

Comments
 (0)