Last active
June 22, 2018 04:01
-
-
Save Lucretiel/952eddbe2d343fdcf38cf95e8e146db9 to your computer and use it in GitHub Desktop.
Call a pytest test once for each value in a fixture list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import itertools | |
import functools | |
def keyed_product(**iterables): | |
''' | |
Same as itertools.product, but returns key-value dicts. Basically, given | |
a dict of key => list, return every possible combination of all the | |
values in the lists, and their associated keys. | |
Example: | |
keyed_product(x=[1,2], y=[3,4]) yields: [ | |
{x: 1, y: 3}, | |
{x: 1, y: 4}, | |
{x: 2, y: 3}, | |
{x: 2, y: 4}, | |
] | |
''' | |
ordered_keys = tuple(iterables.keys()) | |
combinations = itertools.product(*(iterables[key]) for key in ordered_keys) | |
return (dict(zip(ordered_keys, product)) for product in combinations) | |
def spread_fixtures(*fixture_names): | |
''' | |
For a given set of fixture names, call the decorated test function once | |
per each combination of those fixtures. The fixtures should be lists or | |
tuples. The test cases are called in a simple for loop. | |
''' | |
fixture_names = tuple(fixture_names) | |
def spread_fixtures_decorator(test_func): | |
@functools.wraps(test_func) | |
def spread_fixtures_wrapper(**kwargs): | |
# Check that the fixtures we're spreading are collections. | |
for fixture_name in fixture_names: | |
fixture_list = kwargs[fixture_name] | |
# For now we just require lists or tuples. Can grow later. | |
if not isinstance(fixture_list, (list, tuple)): | |
raise RuntimeError( | |
"Fixture '{}' supplied {!r} instead of a list or tuple" | |
.format(fixture_name, fixture_list)) | |
# Loop over every possible combination of fixtures | |
for combo_kwargs in keyed_product(**{name: kwargs[name] for name in fixture_names}): | |
try: | |
test_func(**kwargs, **combo_kwargs) | |
except: | |
print("Combination failed: {}".format(combo_kwargs)) | |
raise | |
return spread_fixtures_wrapper | |
return spread_fixtures_decorator | |
# EXAMPLE | |
@pytest.fixture | |
def aws(): | |
return AWS() | |
@pytest.fixture | |
def cname(aws): | |
return aws.get_cnames() # this should return a list | |
@spread_fixtures('cname') | |
def test(aws, cname): | |
pass | |
# spread_cnames will cause the test function to be called once for each | |
# cname, with a simple for loop. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment