28
28
from .compat import getfixturedefs , inject_fixture
29
29
from .feature import get_feature , get_features
30
30
from .steps import StepFunctionContext , get_step_fixture_name
31
- from .utils import CONFIG_STACK , get_args , get_caller_module_locals , get_caller_module_path
31
+ from .utils import CONFIG_STACK , get_args , get_caller_module_locals , get_caller_module_path , identity
32
32
33
33
if TYPE_CHECKING :
34
34
from _pytest .mark .structures import ParameterSet
41
41
42
42
logger = logging .getLogger (__name__ )
43
43
44
-
45
44
PYTHON_REPLACE_REGEX = re .compile (r"\W" )
46
45
ALPHA_REGEX = re .compile (r"^\d+_*" )
47
46
47
+ STEP_ARGUMENT_DATATABLE = "datatable"
48
+ STEP_ARGUMENT_DOCSTRING = "docstring"
49
+ STEP_ARGUMENTS_RESERVED_NAMES = {STEP_ARGUMENT_DATATABLE , STEP_ARGUMENT_DOCSTRING }
50
+
48
51
49
52
def find_fixturedefs_for_step (step : Step , fixturemanager : FixtureManager , node : Node ) -> Iterable [FixtureDef [Any ]]:
50
53
"""Find the fixture defs that can parse a step."""
@@ -172,6 +175,27 @@ def get_step_function(request: FixtureRequest, step: Step) -> StepFunctionContex
172
175
return None
173
176
174
177
178
+ def parse_step_arguments (step : Step , context : StepFunctionContext ) -> dict [str , object ] | None :
179
+ """Parse step arguments."""
180
+ parsed_args = context .parser .parse_arguments (step .name )
181
+
182
+ assert parsed_args is not None , (
183
+ f"Unexpected `NoneType` returned from " f"parse_arguments(...) in parser: { context .parser !r} "
184
+ )
185
+
186
+ reserved_args = set (parsed_args .keys ()) & STEP_ARGUMENTS_RESERVED_NAMES
187
+ if reserved_args :
188
+ reserved_arguments_str = ", " .join (repr (arg ) for arg in reserved_args )
189
+ raise exceptions .StepImplementationError (
190
+ f"Step { step .name !r} defines argument names that are reserved: { reserved_arguments_str } . "
191
+ "Please use different names."
192
+ )
193
+
194
+ converted_args = {key : (context .converters .get (key , identity )(value )) for key , value in parsed_args .items ()}
195
+
196
+ return converted_args
197
+
198
+
175
199
def _execute_step_function (
176
200
request : FixtureRequest , scenario : Scenario , step : Step , context : StepFunctionContext
177
201
) -> None :
@@ -185,30 +209,17 @@ def _execute_step_function(
185
209
"step_func" : context .step_func ,
186
210
"step_func_args" : {},
187
211
}
188
-
189
212
request .config .hook .pytest_bdd_before_step (** kw )
190
-
191
- # Get the step argument values.
192
- converters = context .converters
193
- kwargs = {}
194
213
args = get_args (context .step_func )
195
214
196
215
try :
197
- parsed_args = context .parser .parse_arguments (step .name )
198
- assert parsed_args is not None , (
199
- f"Unexpected `NoneType` returned from " f"parse_arguments(...) in parser: { context .parser !r} "
200
- )
201
-
202
- for arg , value in parsed_args .items ():
203
- if arg in converters :
204
- value = converters [arg ](value )
205
- kwargs [arg ] = value
216
+ kwargs = parse_step_arguments (step = step , context = context )
206
217
207
218
if step .datatable is not None :
208
- kwargs ["datatable" ] = step .datatable .raw ()
219
+ kwargs [STEP_ARGUMENT_DATATABLE ] = step .datatable .raw ()
209
220
210
221
if step .docstring is not None :
211
- kwargs ["docstring" ] = step .docstring
222
+ kwargs [STEP_ARGUMENT_DOCSTRING ] = step .docstring
212
223
213
224
kwargs = {arg : kwargs [arg ] if arg in kwargs else request .getfixturevalue (arg ) for arg in args }
214
225
0 commit comments