Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add parameterized scenario decorators #50

Merged
merged 4 commits into from
May 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
asynctest==0.13.0
baby-steps==1.2.3
bump2version==1.0.1
codecov==2.1.12
codecov==2.1.13
coverage==7.0.5
flake8==5.0.4
isort==5.11.4
Expand Down
104 changes: 104 additions & 0 deletions tests/core/test_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import sys
from functools import partial
from os import linesep
from typing import Any, Dict, List, Type, cast

import pytest
from baby_steps import then, when

from vedro import Scenario, params


def get_scenarios(key: str, globals_: Dict[str, Any]) -> List[Type[Scenario]]:
return [scn for name, scn in globals_.items() if name.startswith(key)]


def labeled(key, value):
def wrapped(fn):
setattr(fn, key, value)
return fn
return wrapped


label = partial(labeled, "__label__")
tag = partial(labeled, "__tag__")


def test_single_param():
with when:
class SingleParamScenario(Scenario):
@params("Bob")
def __init__(self, user):
self.user = user

with then:
scenarios = get_scenarios("SingleParamScenario", globals())
assert len(scenarios) == 1
assert issubclass(scenarios[0], Scenario)


def test_multiple_params():
with when:
class MultipleParamsScenario(Scenario):
@params("Bob")
@params("Alice")
def __init__(self, user):
self.user = user

with then:
scenarios = get_scenarios("MultipleParamsScenario", globals())
assert len(scenarios) == 2
assert issubclass(scenarios[0], Scenario)
assert issubclass(scenarios[1], Scenario)


# pytest.mark.skipif does not work as expected
# Also global "if sys.version_info >= (3, 9)" does not work as expected with pytest
# (SyntaxError: invalid syntax)
if sys.version_info < (3, 9):
params_decorator = cast(Any, params)
else:
params_decorator = cast(Any, params)
params_decorator_py39 = linesep.join([
"def params_decorator(decorators, args, kwargs):",
" return params[decorators](*args, **kwargs)",
])
code_object = compile(params_decorator_py39, "<string>", "exec")
exec(code_object)


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_proxy_param():
print("test_proxy_param")
with when:
class ProxyParamScenario(Scenario):
@params_decorator((label("label"), tag("tag")), ("Bob",), {})
def __init__(self, user):
self.user = user

with then:
scenarios = get_scenarios("ProxyParamScenario", globals())
assert len(scenarios) == 1

assert issubclass(scenarios[0], Scenario)
assert getattr(scenarios[0], "__label__") == "label"
assert getattr(scenarios[0], "__tag__") == "tag"


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_proxy_params():
with when:
class ProxyParamsScenario(Scenario):
@params_decorator((label("label1"),), ("Bob",), {})
@params_decorator((label("label2"),), ("Alice",), {})
def __init__(self, user):
self.user = user

with then:
scenarios = get_scenarios("ProxyParamsScenario", globals())
assert len(scenarios) == 2

assert issubclass(scenarios[0], Scenario)
assert getattr(scenarios[0], "__label__") == "label1"
assert issubclass(scenarios[1], Scenario)
assert getattr(scenarios[1], "__label__") == "label2"
19 changes: 18 additions & 1 deletion tests/plugins/skipper/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from os import chdir
from pathlib import Path
from time import monotonic_ns
from typing import Callable, Iterable, List, Optional, Tuple
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Type

import pytest
from niltype import Nil, Nilable

from vedro import Scenario
from vedro.core import ArgumentParser, Dispatcher, VirtualScenario
Expand Down Expand Up @@ -106,3 +107,19 @@ def touch(path: Path) -> Path:

def get_skipped(scenarios: Iterable[VirtualScenario]) -> List[VirtualScenario]:
return [scn for scn in scenarios if scn.is_skipped()]


def get_scenarios(key: str, globals_: Dict[str, Any]) -> List[Type[Scenario]]:
return [scn for name, scn in globals_.items() if name.startswith(key)]


def get_only_attr(scenario: Type[Scenario]) -> bool:
return getattr(scenario, "__vedro__only__", False)


def get_skip_attr(scenario: Type[Scenario]) -> bool:
return getattr(scenario, "__vedro__skipped__", False)


def get_skip_reason_attr(scenario: Type[Scenario]) -> Nilable[str]:
return getattr(scenario, "__vedro__skip_reason__", Nil)
6 changes: 4 additions & 2 deletions tests/plugins/skipper/test_only_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from vedro import Scenario
from vedro.plugins.skipper import only

from ._utils import get_only_attr


def test_only():
with when:
Expand All @@ -13,7 +15,7 @@ class _Scenario(Scenario):

with then:
assert issubclass(_Scenario, Scenario)
assert getattr(_Scenario, "__vedro__only__") is True
assert get_only_attr(_Scenario) is True


def test_only_called():
Expand All @@ -24,7 +26,7 @@ class _Scenario(Scenario):

with then:
assert issubclass(_Scenario, Scenario)
assert getattr(_Scenario, "__vedro__only__") is True
assert get_only_attr(_Scenario) is True


def test_only_not_subclass():
Expand Down
159 changes: 159 additions & 0 deletions tests/plugins/skipper/test_only_skip_templated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import sys
from os import linesep
from typing import Any, cast

import pytest
from baby_steps import then, when

from vedro import Scenario, params
from vedro.plugins.skipper import only, skip

from ._utils import get_only_attr, get_scenarios, get_skip_attr

# pytest.mark.skipif does not work as expected
# Also global "if sys.version_info >= (3, 9)" does not work as expected with pytest
# (SyntaxError: invalid syntax)
if sys.version_info < (3, 9):
params_decorator = cast(Any, params)
else:
params_decorator = cast(Any, params)
params_decorator_py39 = linesep.join([
"def params_decorator(decorator = None):",
" return params[decorator]() if decorator else params()",
])
code_object = compile(params_decorator_py39, "<string>", "exec")
exec(code_object)


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_template_only_empty():
with when:
class OnlyEmptyScenario(Scenario):
@params_decorator(only)
@params_decorator()
def __init__(self):
pass

with then:
scenarios = get_scenarios("OnlyEmptyScenario", globals())
assert len(scenarios) == 2
assert get_only_attr(scenarios[0]) is True
assert get_only_attr(scenarios[1]) is False


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_only_template_only_empty():
with when:
@only
class TemplateOnlyEmptyScenario(Scenario):
@params_decorator(only)
@params_decorator()
def __init__(self):
pass

with then:
scenarios = get_scenarios("TemplateOnlyEmptyScenario", globals())
assert len(scenarios) == 2
assert get_only_attr(scenarios[0]) is True
assert get_only_attr(scenarios[1]) is False


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_only_template_only_only():
with when:
@only
class TemplateOnlyOnlyScenario(Scenario):
@params_decorator(only)
@params_decorator(only)
def __init__(self):
pass

with then:
scenarios = get_scenarios("TemplateOnlyOnlyScenario", globals())
assert len(scenarios) == 2
assert get_only_attr(scenarios[0]) is True
assert get_only_attr(scenarios[1]) is True


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_only_template_only_skip():
with when:
@only
class TemplateOnlySkipScenario(Scenario):
@params_decorator(only)
@params_decorator(skip)
def __init__(self):
pass

with then:
scenarios = get_scenarios("TemplateOnlySkipScenario", globals())
assert len(scenarios) == 2
assert get_only_attr(scenarios[0]) is True
assert get_only_attr(scenarios[1]) is False


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_template_skip_empty():
with when:
class SkipEmptyScenario(Scenario):
@params_decorator(skip)
@params_decorator()
def __init__(self):
pass

with then:
scenarios = get_scenarios("SkipEmptyScenario", globals())
assert len(scenarios) == 2
assert get_skip_attr(scenarios[0]) is True
assert get_skip_attr(scenarios[1]) is False


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_skip_template_skip_empty():
with when:
@skip
class TemplateSkipEmptyScenario(Scenario):
@params_decorator(skip)
@params_decorator()
def __init__(self):
pass

with then:
scenarios = get_scenarios("TemplateSkipEmptyScenario", globals())
assert len(scenarios) == 2
assert get_skip_attr(scenarios[0]) is True
assert get_skip_attr(scenarios[1]) is False


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_skip_template_skip_skip():
with when:
@skip
class TemplateSkipSkipScenario(Scenario):
@params_decorator(skip)
@params_decorator(skip)
def __init__(self):
pass

with then:
scenarios = get_scenarios("TemplateSkipSkipScenario", globals())
assert len(scenarios) == 2
assert get_skip_attr(scenarios[0]) is True
assert get_skip_attr(scenarios[1]) is True


@pytest.mark.skipif(sys.version_info < (3, 9), reason="requires python3.9 or higher")
def test_skip_template_skip_only():
with when:
@skip
class TemplateSkipOnlyScenario(Scenario):
@params_decorator(skip)
@params_decorator(only)
def __init__(self):
pass

with then:
scenarios = get_scenarios("TemplateSkipOnlyScenario", globals())
assert len(scenarios) == 2
assert get_skip_attr(scenarios[0]) is True
assert get_skip_attr(scenarios[1]) is False
14 changes: 8 additions & 6 deletions tests/plugins/skipper/test_skip_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from vedro import Scenario
from vedro.plugins.skipper import skip

from ._utils import get_skip_attr, get_skip_reason_attr


def test_skip():
with when:
Expand All @@ -14,8 +16,8 @@ class _Scenario(Scenario):

with then:
assert issubclass(_Scenario, Scenario)
assert getattr(_Scenario, "__vedro__skipped__") is True
assert getattr(_Scenario, "__vedro__skip_reason__", Nil) is Nil
assert get_skip_attr(_Scenario) is True
assert get_skip_reason_attr(_Scenario) is Nil


def test_skip_called():
Expand All @@ -26,8 +28,8 @@ class _Scenario(Scenario):

with then:
assert issubclass(_Scenario, Scenario)
assert getattr(_Scenario, "__vedro__skipped__") is True
assert getattr(_Scenario, "__vedro__skip_reason__", Nil) is Nil
assert get_skip_attr(_Scenario) is True
assert get_skip_reason_attr(_Scenario) is Nil


def test_skip_called_with_reason():
Expand All @@ -41,8 +43,8 @@ class _Scenario(Scenario):

with then:
assert issubclass(_Scenario, Scenario)
assert getattr(_Scenario, "__vedro__skipped__") is True
assert getattr(_Scenario, "__vedro__skip_reason__") == reason
assert get_skip_attr(_Scenario) is True
assert get_skip_reason_attr(_Scenario) == reason


def test_skip_not_subclass():
Expand Down
Loading