pytest: pytest.mark.parametrize string-based parameter list doesn't handle single element tuples

Originally reported by: David Haney (BitBucket: david_haney, GitHub: david_haney)


When specifying a @pytest.mark.parametrize element composed of a one-element tuple, I’m unable to use the string-based argument list, for example:

@pytest.mark.parametrize("arg", scenarios)
def test(arg):
    print(arg)
    assert(arg == "a") # this assert always fails

arg ends up being the tuple instead of the first item in the tuple (as I would expected based on tuples with more than one item. I also tried:

@pytest.mark.parametrize("arg,", scenarios)

but that also associated the entire tuple with arg instead of the first element. I reverted back to the older model of specifying the arguments as a tuple:

@pytest.mark.parametrize("arg,", scenarios)

Finally I switched back to the older style of using a tuple to specify the parameter list:

@pytest.mark.parametrize(("arg",), scenarios)

This version worked. This seems to imply that there is either a bug/limitation in the new string-based parameter specification, or that there is still a use-case for the tuple-based parameter specification. It would be helpful if either the string-based implementation could be updated to handle this situation, or if the documentation could be updated to note when the tuple-based parameter specification is still needed.


About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Comments: 17 (15 by maintainers)

Most upvoted comments

IMO this is the desired behavior:

import pytest

scenarios = [('a',)]

@pytest.mark.parametrize(("arg",), scenarios)
def test_tuple(arg):
    assert arg == 'a'

@pytest.mark.parametrize("arg", scenarios)
def test_string(arg):
    assert arg == ('a',)

@pytest.mark.parametrize("arg,", scenarios)
def test_stringtuple(arg):
    assert arg == 'a'

Out of these, test_stringtuple fails.

@donfiguerres if there was, you would see it in here.

I think the OP means that these two tests should be equivalent:

import pytest

scenarios = [('a',)]

@pytest.mark.parametrize(("arg",), scenarios)
def test_foo_1(arg):
    assert arg == 'a'

@pytest.mark.parametrize("arg", scenarios)
def test_foo_2(arg):
    assert arg == 'a'  
test_foo.py::test_foo_1[a] FAILED
test_foo.py::test_foo_2[arg0] PASSED

================================== FAILURES ===================================
________________________________ test_foo_1[a] ________________________________

arg = 'a'

    @pytest.mark.parametrize(("arg",), scenarios)
    def test_foo_1(arg):
>       assert arg == ('a',)
E       assert 'a' == ('a',)

test_foo.py:7: AssertionError
===================== 1 failed, 1 passed in 0.02 seconds ======================

When you use more than one argument, both tests work as expected:

import pytest

scenarios = [('a', 'b')]

@pytest.mark.parametrize(("arg","arg2"), scenarios)
def test_bar_1(arg, arg2):
    assert arg == 'a'
    assert arg2 == 'b'

@pytest.mark.parametrize("arg,arg2", scenarios)
def test_bar_2(arg, arg2):
    assert arg == 'a'
    assert arg2 == 'b'  
test_foo.py::test_bar_1[a-b] PASSED
test_foo.py::test_bar_2[a-b] PASSED

I would expect both forms to work even if used with a single argument, so this seems like a bug to me… 😅