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

[Question] Pre-filter cases #258

Closed
eddiebergman opened this issue Feb 19, 2022 · 4 comments
Closed

[Question] Pre-filter cases #258

eddiebergman opened this issue Feb 19, 2022 · 4 comments

Comments

@eddiebergman
Copy link
Contributor

eddiebergman commented Feb 19, 2022

Hi @smarie,
I was looking through the documentation and couldn't find any way to pre-filter cases into some kind of iterable that can then be passed to parametrize_with_cases("x", cases=...). My use case is generally to have cases in a cases.py file that is shared throughout the test module.

# x/y/z folder
__init__.py
cases.py  # Contains cases with labels "A" and "B" and some have "banana" too
test_base.py  # Should test cases "A" and "B"
test_A.py  # Should test cases "A"
test_B.py  # Should test cases "B"

This is useful for testing hierarchies where A and B inherit from Base so much of their setup is the same and makes sense to be done in the same file cases.py, instead of splitting theme out into cases_A.py and cases_B.py.

Is there some way to do the following:

# test_A.py
import x.y.z.cases as cases  # Has cases for both A and B
cases_with_tag_A = something(cases)

@parametrize_with_cases("x", cases=cases_with_tag_A filter=~ft.has_tag("banana"))
def test_A_prop(x): ...

@parametrize_with_cases("x", cases=cases_with_tag_A, has_tag="banana")
def test_A_prop_that_has_bananas(x): ...

I'm aware I could just use a filter on each test but there are other tags and the filters tend to get repetitive and I am prone to forgetting them. I could also use a partial but this kind of obscures things and doesn't allow additional filtering, i.e. has_tag=["A", "banana"].

Suggestions on how to about this or how this could be implemented would be greatly appreciated :)

Best,
Eddie

@smarie
Copy link
Owner

smarie commented Feb 21, 2022

Hi @eddiebergman , thanks for this suggestion !

I guess that get_all_cases could do the trick, however you currently have to pass it some function as the first argument, in order for it to find the host module.

Maybe we could transform it so that it accepts a module instead ? Otherwise for now you can just pass a fake function

from pytest_cases import get_all_cases

def dummy:
    pass

my_cases = get_all_cases(dummy, ....)  # use your glob and filter here


@parametrize_with_cases("a", cases=my_cases)
def test_foo(a):
    ...

Let me know if this works for you.

@eddiebergman
Copy link
Contributor Author

eddiebergman commented Feb 21, 2022

Ahh I never thought about the dummy function approach, I thought it might do some introspection into the arguments of the function. Does this introspection occur?

An ideal interface as far as I could imagine doesn't rely on an actual function being defined? I don't see the reason for the function needing to be passed other than to allow for the argument cases="." or cases=AUTO in which it looks for the cases_x.py file. Is this correct?

In this case, perhaps get_all_cases can be made to optionally accept a function definition and raise an error if cases="." or cases=AUTO?

# Wherever it is defined
def get_all_cases(f: Optional[Function] = None, cases=..., ...other args)
    if cases in [".", AUTO] and f is None:
        raise ValueError(...)
        
    ... continue as normal and handle logic accordingly

# Some test_file.py
cases = [SomeModule, case_1, case_2, ClassOfCases]
my_cases = get_all_cases(cases=cases, filter=...)

@parametrize_with_cases("x", cases=my_cases)
def test_something(x):
    ...

Perhaps a simpler implementation is just a seperate function filter_cases which does a filter over cases as above?

@smarie
Copy link
Owner

smarie commented Feb 21, 2022

Yes I think that it was to grab the module, so that relative module names (not only "." but ".xyz", either alone or in an iterable) and AUTO mode is supported.

It would indeed be preferable to improve get_all_cases so that it can receive a function OR a module (name ?) , and so that this argument can be optional (default None).

@smarie
Copy link
Owner

smarie commented Mar 21, 2022

Closed in #260

@smarie smarie closed this as completed Mar 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants