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

Try supporting yield functions for setup/teardown. #1

Merged
merged 8 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
13 changes: 13 additions & 0 deletions examples/test_yield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest


def setup_and_teardown():
print('\nsetup')
yield 42
print('\nteardown')


@pytest.mark.param_scope(setup_and_teardown, None)
@pytest.mark.parametrize('x', ['a', 'b', 'c'])
def test_yield(x, param_scope):
assert param_scope == 42
okken marked this conversation as resolved.
Show resolved Hide resolved
25 changes: 24 additions & 1 deletion src/pytest_param_scope/plugin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from __future__ import annotations
import types
from typing import Generator
import pytest
from dataclasses import dataclass
from typing import Callable, Any
Expand All @@ -14,6 +16,7 @@ def pytest_configure(config):
class ParamScopeData():
test_name: str | None = None
teardown_func: Callable | None = None
teardown_gen: Generator[Any, None, None] | None = None
ready_for_teardown: bool = False
setup_value: Any = None
exception: Exception | None = None
Expand Down Expand Up @@ -44,7 +47,17 @@ def param_scope(request):

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure how to comment on un-diffed areas in a PR review! But anyways, a few lines above this where the if m: clause appears, the case of excess teardown could be handled earlier there, rather than handling it on the line comment below.

if setup_func:
try:
__data.setup_value = setup_func()
# setup could be a func, or could be a generator
setup_value = setup_func()
if isinstance(setup_value, types.GeneratorType):
# if generator, call next() once for setup section
new_value = next(setup_value)
__data.setup_value = new_value
# and save it for teardown
__data.teardown_gen = setup_value
else:
# otherwise, just save the value
__data.setup_value = setup_value
except Exception as e:
__data.exception = e
raise e
Expand All @@ -58,8 +71,18 @@ def param_scope(request):
yield __data.setup_value

if __data.ready_for_teardown:
teardown_gen = __data.teardown_gen
teardown_func = __data.teardown_func

__data = ParamScopeData() # reset for next one

if teardown_gen:
try:
next(teardown_gen)
except StopIteration:
pass # this is expected

# should we disallow both a teardown from gen and a teardown?
if teardown_func:
teardown_func()

okken marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
14 changes: 14 additions & 0 deletions tests/test_yield.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

def test_error_during_setup(pytester):
okken marked this conversation as resolved.
Show resolved Hide resolved
pytester.copy_example("examples/test_yield.py")
result = pytester.runpytest('test_yield.py::test_yield', '-v', '-s')
result.assert_outcomes(passed=3)
result.stdout.re_match_lines(
[
".*test_yield.a.*",
"setup",
".*test_yield.b.*",
".*test_yield.c.*",
"teardown",
]
)
okken marked this conversation as resolved.
Show resolved Hide resolved