I have created a 'dynamic' list of parameters which I pass to parametrize.
OPTIONS = ['a', 'b', 'c']
def get_unique_pairs():
    unique_list = []
    for first in OPTIONS:
        for second OPTIONS:
            if first == second:
                continue
            unique_list.append({'first':first, 'second':second))
    return unique_list
def some_func()
    unique_pairs = get_unique_pairs()
    result = []
    for pair in unique_pair:
        if test(pair):
           continue
        else:
           result.append(pair)
    return pair
@pytest.mark.parametrize('param', some_fnc())
def test_fnc(param):
    first = param['first']
    second = param['second']
The input I wish to pass to test_fnc is [('a','b'),('a','c')...('c','b')] where the first and second elements are never the same. There is some additional logic I am using to further remove specific pairs.
When I run the test I get the output:
::test_fnc[param0] PASSED
::test_fnc[param1] PASSED
::test_fnc[param2] PASSED
I have two issues:
param0), and I'd like to continue using dictionaries to pass data to the test.Repeating a test Each test collected by pytest will be run count times. If you want to override default tests executions order, you can use --repeat-scope command line option with one of the next values: session , module , class or function (default). It behaves like a scope of the pytest fixture.
pytest. fixture() allows one to parametrize fixture functions.
The @pytest. mark. parametrize() decorator lets you parameterize arguments of the testing function independent of fixtures you created.
I would write it like this:
import pytest
import itertools
OPTIONS = ['a', 'b', 'c']
@pytest.mark.parametrize(
    'param',
    itertools.permutations(OPTIONS, 2),
    ids=lambda pair: "first={}, second={}".format(*pair)
)
def test_fn(param):
    first, second = param
    assert first != second
Result:
> pytest --verbose 
================================ test session starts =================================
platform linux2 -- Python 2.7.12, pytest-3.6.1, py-1.5.3, pluggy-0.6.0 -- /usr/bin/python
cachedir: .pytest_cache
rootdir: /home/paulos/work/lixo/tests, inifile:
collected 6 items
test_foo.py::test_fn[first=a, second=b] PASSED                                     [ 16%]
test_foo.py::test_fn[first=a, second=c] PASSED                                     [ 33%]
test_foo.py::test_fn[first=b, second=a] PASSED                                     [ 50%]
test_foo.py::test_fn[first=b, second=c] PASSED                                     [ 66%]
test_foo.py::test_fn[first=c, second=a] PASSED                                     [ 83%]
test_foo.py::test_fn[first=c, second=b] PASSED                                     [100%]
================================ 6 passed in 0.03 seconds ================================
[update]
I think this answer is the solution I will use. Every day is a school day! (Out of curiosity is there a way I could be the 'param' into something like 'first, second' so to have test_foo(param) be test_foo(first, second). I'm not sure that actually helps anything... but I am curious – F. Elliot
If you don't mind a test_fn[a-b] instead of  test_fn[a, b]:
@pytest.mark.parametrize(
    'first,second',
    itertools.permutations(OPTIONS, 2),
)
def test_fn(first, second):
    assert first != second
In practice we don't really run tests with --verbose anyway, so most of the time the output will be just a dot for each test. 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With