|
9 | 9 | import pytest
|
10 | 10 | from _pytest import fixtures
|
11 | 11 | from _pytest import python
|
| 12 | +from _pytest.outcomes import fail |
12 | 13 |
|
13 | 14 |
|
14 | 15 | class TestMetafunc:
|
@@ -61,6 +62,39 @@ def func(x, y):
|
61 | 62 | pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
62 | 63 | pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
|
63 | 64 |
|
| 65 | + with pytest.raises( |
| 66 | + TypeError, match="^ids must be a callable, sequence or generator$" |
| 67 | + ): |
| 68 | + metafunc.parametrize("y", [5, 6], ids=42) |
| 69 | + |
| 70 | + def test_parametrize_error_iterator(self): |
| 71 | + def func(x): |
| 72 | + raise NotImplementedError() |
| 73 | + |
| 74 | + class Exc(Exception): |
| 75 | + def __repr__(self): |
| 76 | + return "Exc(from_gen)" |
| 77 | + |
| 78 | + def gen(): |
| 79 | + yield 0 |
| 80 | + yield None |
| 81 | + yield Exc() |
| 82 | + |
| 83 | + metafunc = self.Metafunc(func) |
| 84 | + metafunc.parametrize("x", [1, 2], ids=gen()) |
| 85 | + assert [(x.funcargs, x.id) for x in metafunc._calls] == [ |
| 86 | + ({"x": 1}, "0"), |
| 87 | + ({"x": 2}, "2"), |
| 88 | + ] |
| 89 | + with pytest.raises( |
| 90 | + fail.Exception, |
| 91 | + match=( |
| 92 | + r"In func: ids must be list of string/float/int/bool, found:" |
| 93 | + r" Exc\(from_gen\) \(type: <class .*Exc'>\) at index 2" |
| 94 | + ), |
| 95 | + ): |
| 96 | + metafunc.parametrize("x", [1, 2, 3], ids=gen()) |
| 97 | + |
64 | 98 | def test_parametrize_bad_scope(self, testdir):
|
65 | 99 | def func(x):
|
66 | 100 | pass
|
@@ -534,9 +568,22 @@ def ids(d):
|
534 | 568 | @pytest.mark.parametrize("arg", ({1: 2}, {3, 4}), ids=ids)
|
535 | 569 | def test(arg):
|
536 | 570 | assert arg
|
| 571 | +
|
| 572 | + @pytest.mark.parametrize("arg", (1, 2.0, True), ids=ids) |
| 573 | + def test_int(arg): |
| 574 | + assert arg |
537 | 575 | """
|
538 | 576 | )
|
539 |
| - assert testdir.runpytest().ret == 0 |
| 577 | + result = testdir.runpytest("-vv", "-s") |
| 578 | + result.stdout.fnmatch_lines( |
| 579 | + [ |
| 580 | + "test_parametrize_ids_returns_non_string.py::test[arg0] PASSED", |
| 581 | + "test_parametrize_ids_returns_non_string.py::test[arg1] PASSED", |
| 582 | + "test_parametrize_ids_returns_non_string.py::test_int[1] PASSED", |
| 583 | + "test_parametrize_ids_returns_non_string.py::test_int[2.0] PASSED", |
| 584 | + "test_parametrize_ids_returns_non_string.py::test_int[True] PASSED", |
| 585 | + ] |
| 586 | + ) |
540 | 587 |
|
541 | 588 | def test_idmaker_with_ids(self):
|
542 | 589 | from _pytest.python import idmaker
|
@@ -1186,20 +1233,21 @@ def test_temp(temp):
|
1186 | 1233 | result.stdout.fnmatch_lines(["* 1 skipped *"])
|
1187 | 1234 |
|
1188 | 1235 | def test_parametrized_ids_invalid_type(self, testdir):
|
1189 |
| - """Tests parametrized with ids as non-strings (#1857).""" |
| 1236 | + """Test error with non-strings/non-ints, without generator (#1857).""" |
1190 | 1237 | testdir.makepyfile(
|
1191 | 1238 | """
|
1192 | 1239 | import pytest
|
1193 | 1240 |
|
1194 |
| - @pytest.mark.parametrize("x, expected", [(10, 20), (40, 80)], ids=(None, 2)) |
| 1241 | + @pytest.mark.parametrize("x, expected", [(1, 2), (3, 4), (5, 6)], ids=(None, 2, type)) |
1195 | 1242 | def test_ids_numbers(x,expected):
|
1196 | 1243 | assert x * 2 == expected
|
1197 | 1244 | """
|
1198 | 1245 | )
|
1199 | 1246 | result = testdir.runpytest()
|
1200 | 1247 | result.stdout.fnmatch_lines(
|
1201 | 1248 | [
|
1202 |
| - "*In test_ids_numbers: ids must be list of strings, found: 2 (type: *'int'>)*" |
| 1249 | + "In test_ids_numbers: ids must be list of string/float/int/bool," |
| 1250 | + " found: <class 'type'> (type: <class 'type'>) at index 2" |
1203 | 1251 | ]
|
1204 | 1252 | )
|
1205 | 1253 |
|
@@ -1776,3 +1824,39 @@ def test_foo(a):
|
1776 | 1824 | )
|
1777 | 1825 | result = testdir.runpytest()
|
1778 | 1826 | result.assert_outcomes(passed=1)
|
| 1827 | + |
| 1828 | + def test_parametrize_iterator(self, testdir): |
| 1829 | + testdir.makepyfile( |
| 1830 | + """ |
| 1831 | + import itertools |
| 1832 | + import pytest |
| 1833 | +
|
| 1834 | + id_parametrize = pytest.mark.parametrize( |
| 1835 | + ids=("param%d" % i for i in itertools.count()) |
| 1836 | + ) |
| 1837 | +
|
| 1838 | + @id_parametrize('y', ['a', 'b']) |
| 1839 | + def test1(y): |
| 1840 | + pass |
| 1841 | +
|
| 1842 | + @id_parametrize('y', ['a', 'b']) |
| 1843 | + def test2(y): |
| 1844 | + pass |
| 1845 | +
|
| 1846 | + @pytest.mark.parametrize("a, b", [(1, 2), (3, 4)], ids=itertools.count()) |
| 1847 | + def test_converted_to_str(a, b): |
| 1848 | + pass |
| 1849 | + """ |
| 1850 | + ) |
| 1851 | + result = testdir.runpytest("-vv", "-s") |
| 1852 | + result.stdout.fnmatch_lines_random( # random for py35. |
| 1853 | + [ |
| 1854 | + "test_parametrize_iterator.py::test1[param0] PASSED", |
| 1855 | + "test_parametrize_iterator.py::test1[param1] PASSED", |
| 1856 | + "test_parametrize_iterator.py::test2[param2] PASSED", |
| 1857 | + "test_parametrize_iterator.py::test2[param3] PASSED", |
| 1858 | + "test_parametrize_iterator.py::test_converted_to_str[0] PASSED", |
| 1859 | + "test_parametrize_iterator.py::test_converted_to_str[1] PASSED", |
| 1860 | + "*= 6 passed in *", |
| 1861 | + ] |
| 1862 | + ) |
0 commit comments