3

I have a parametrized pytest test and use tuples as expected values.

If I run the tests, these values are not displayed and auto-generated ones (expected0...expectedN) are shown in the report.

Is it possible to have tuple values displayed in the output?

Test sample:

@pytest.mark.parametrize('test_input, expected',
                         [
                             ('12:00 AM', (0, 0)),
                             ('12:01 AM', (0, 1)),
                             ('11:59 AM', (11, 58))
                         ])
def test_params(test_input, expected):
    assert time_calculator.convert_12h_to_24(test_input) == expected

Output:

test_time_converter.py::test_params[12:00 AM-expected0] PASSED
test_time_converter.py::test_params[12:01 AM-expected1] PASSED
test_time_converter.py::test_params[11:59 AM-expected2] FAILED
DV82XL
  • 5,350
  • 5
  • 30
  • 59
algot
  • 2,428
  • 3
  • 19
  • 23
  • 2
    Maybe have a look at this: https://stackoverflow.com/a/37591040/8763097 . This answer shows how to custom format a parameter. You'll probably need to change the line `item.name = '{func}[{params}]'.format(func=item.name.split('[')[0], params=format_string.format(**params))` to accomodate outputting a tuple as a string. – PeptideWitch Oct 20 '21 at 22:46
  • yes, it helped but code looks little overcomplicated I thought pytest could format it by itself – algot Oct 21 '21 at 15:03

1 Answers1

2

Applying this answer, you can customize the ids attribute:

PARAMS = [
    ('12:00 AM', (0, 0)),
    ('12:01 AM', (0, 1)),
    ('11:59 AM', (11, 58))
]

def get_ids(params):
    return [f'{a}-{b}' for a, b in params]

@pytest.mark.parametrize('test_input, expected', PARAMS, ids=get_ids(PARAMS))
def test_params_format(test_input, expected):
    assert expected != (11, 58)

Another option, though not quite as elegant, is to define the tuples as strings and make them indirect parameters. This calls a simple fixture in conftest.py that can eval the strings back into tuples before they are passed to the test function.

@pytest.mark.parametrize(
    'test_input, expected',
    [
        ('12:00 AM', '(0, 0)'),
        ('12:01 AM', '(0, 1)'),
        ('11:59 AM', '(11, 58)')
    ],
    indirect=["expected"])
def test_params(test_input, expected):
    assert expected != (11, 58)

conftest.py:

from ast import literal_eval

@pytest.fixture
def expected(request):
    return literal_eval(request.param)

literal_eval is more secure than eval. See here.

Output (both solutions):

test_print_tuples.py::test_params[12:00 AM-(0, 0)] PASSED
test_print_tuples.py::test_params[12:01 AM-(0, 1)] PASSED 
test_print_tuples.py::test_params[11:59 AM-(11, 58)] FAILED
DV82XL
  • 5,350
  • 5
  • 30
  • 59