Refactor params, use Step when possible

This commit is contained in:
Alessio Bogon 2022-07-27 21:02:47 +02:00
parent 5f74bcc6db
commit 0e08d87074
3 changed files with 26 additions and 33 deletions

View File

@ -127,10 +127,8 @@ def _find_step_fixturedef(
fixturemanager: FixtureManager, item: Function, step: Step
) -> Sequence[FixtureDef[Any]] | None:
"""Find step fixturedef."""
with patch_argumented_step_functions(
name=step.name, type_=step.type, fixturemanager=fixturemanager, nodeid=item.nodeid
):
bdd_name = get_step_fixture_name(name=step.name, type_=step.type)
with patch_argumented_step_functions(step=step, fixturemanager=fixturemanager, nodeid=item.nodeid):
bdd_name = get_step_fixture_name(step=step)
return fixturemanager.getfixturedefs(bdd_name, item.nodeid)

View File

@ -16,7 +16,7 @@ import contextlib
import logging
import os
import re
from typing import TYPE_CHECKING, Callable, cast
from typing import TYPE_CHECKING, Callable, Iterator, cast
import pytest
from _pytest.fixtures import FixtureDef, FixtureManager, FixtureRequest, call_fixture_func
@ -42,9 +42,7 @@ PYTHON_REPLACE_REGEX = re.compile(r"\W")
ALPHA_REGEX = re.compile(r"^\d+_*")
def iter_argumented_step_function(
name: str, type_: str, fixturemanager: FixtureManager, nodeid: str
) -> Iterable[FixtureDef[Any]]:
def iter_argumented_step_function(step: Step, fixturemanager: FixtureManager, nodeid: str) -> Iterable[FixtureDef[Any]]:
"""Iterate over argumented step functions."""
# happens to be that _arg2fixturedefs is changed during the iteration so we use a copy
fixture_def_by_name = list(fixturemanager._arg2fixturedefs.items())
@ -54,26 +52,24 @@ def iter_argumented_step_function(
if step_func_context is None:
continue
if step_func_context.type != type_:
if step_func_context.type != step.type:
continue
match = step_func_context.parser.is_matching(name)
match = step_func_context.parser.is_matching(step.name)
if not match:
continue
if fixturedef not in fixturemanager.getfixturedefs(fixturename, nodeid):
if fixturedef not in (fixturemanager.getfixturedefs(fixturename, nodeid) or []):
continue
yield fixturedef
@contextlib.contextmanager
def patch_argumented_step_functions(name: str, type_, fixturemanager, nodeid: str | None = None) -> None:
bdd_name = get_step_fixture_name(name, type_)
def patch_argumented_step_functions(step: Step, fixturemanager: FixtureManager, nodeid: str) -> Iterator[None]:
bdd_name = get_step_fixture_name(step=step)
fixturedefs = list(
iter_argumented_step_function(name=name, type_=type_, fixturemanager=fixturemanager, nodeid=nodeid)
)
fixturedefs = list(iter_argumented_step_function(step=step, fixturemanager=fixturemanager, nodeid=nodeid))
# Sort the fixture definitions by their "path", so that the `bdd_name` fixture will
# respect the fixture scope
@ -98,13 +94,11 @@ def patch_argumented_step_functions(name: str, type_, fixturemanager, nodeid: st
def get_argumented_step_function(request, step: Step) -> StepFunctionContext | None:
"""Find argumented step fixture name."""
bdd_name = get_step_fixture_name(name=step.name, type_=step.type)
bdd_name = get_step_fixture_name(step=step)
with patch_argumented_step_functions(
name=step.name, type_=step.type, fixturemanager=request._fixturemanager, nodeid=request.node.nodeid
):
with patch_argumented_step_functions(step=step, fixturemanager=request._fixturemanager, nodeid=request.node.nodeid):
try:
return request.getfixturevalue(bdd_name)
return cast(StepFunctionContext, request.getfixturevalue(bdd_name))
except pytest.FixtureLookupError:
return None
@ -130,7 +124,11 @@ def _execute_step_function(
args = get_args(context.step_func)
try:
for arg, value in context.parser.parse_arguments(step.name).items():
parsed_args = context.parser.parse_arguments(step.name)
assert parsed_args is not None, (
f"Unexpected `NoneType` returned from " f"parse_arguments(...) in parser: {context.parser!r}"
)
for arg, value in parsed_args.items():
if arg in converters:
value = converters[arg](value)
kwargs[arg] = value

View File

@ -45,6 +45,7 @@ import pytest
from _pytest.fixtures import FixtureDef, FixtureRequest
from typing_extensions import Literal
from .parser import Step
from .parsers import StepParser, get_parser
from .types import GIVEN, THEN, WHEN
from .utils import get_caller_module_locals
@ -67,15 +68,9 @@ class StepFunctionContext:
target_fixture: str | None = None
def get_step_fixture_name(name: str, type_: str) -> str:
"""Get step fixture name.
:param name: string
:param type: step type
:return: step fixture name
:rtype: string
"""
return f"{StepNamePrefix.step_impl}_{type_}_{name}"
def get_step_fixture_name(step: Step) -> str:
"""Get step fixture name"""
return f"{StepNamePrefix.step_impl}_{step.type}_{step.name}"
def given(
@ -149,7 +144,7 @@ def _step_decorator(
step_name: str | StepParser,
converters: dict[str, Callable] | None = None,
target_fixture: str | None = None,
) -> Callable:
) -> Callable[[TCallable], TCallable]:
"""Step decorator for the type and the name.
:param str step_type: Step type (GIVEN, WHEN or THEN).
@ -211,7 +206,9 @@ def inject_fixture(request: FixtureRequest, arg: str, value: Any) -> None:
def fin() -> None:
request._fixturemanager._arg2fixturedefs[arg].remove(fd)
request._fixture_defs[arg] = old_fd
if old_fd is not None:
request._fixture_defs[arg] = old_fd
if add_fixturename:
request._pyfuncitem._fixtureinfo.names_closure.remove(arg)