|
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
|
@@ -521,9 +555,22 @@ def ids(d):
|
521 | 555 | @pytest.mark.parametrize("arg", ({1: 2}, {3, 4}), ids=ids)
|
522 | 556 | def test(arg):
|
523 | 557 | assert arg
|
| 558 | +
|
| 559 | + @pytest.mark.parametrize("arg", (1, 2.0, True), ids=ids) |
| 560 | + def test_int(arg): |
| 561 | + assert arg |
524 | 562 | """
|
525 | 563 | )
|
526 |
| - assert testdir.runpytest().ret == 0 |
| 564 | + result = testdir.runpytest("-vv", "-s") |
| 565 | + result.stdout.fnmatch_lines( |
| 566 | + [ |
| 567 | + "test_parametrize_ids_returns_non_string.py::test[arg0] PASSED", |
| 568 | + "test_parametrize_ids_returns_non_string.py::test[arg1] PASSED", |
| 569 | + "test_parametrize_ids_returns_non_string.py::test_int[1] PASSED", |
| 570 | + "test_parametrize_ids_returns_non_string.py::test_int[2.0] PASSED", |
| 571 | + "test_parametrize_ids_returns_non_string.py::test_int[True] PASSED", |
| 572 | + ] |
| 573 | + ) |
527 | 574 |
|
528 | 575 | def test_idmaker_with_ids(self):
|
529 | 576 | from _pytest.python import idmaker
|
@@ -1173,20 +1220,21 @@ def test_temp(temp):
|
1173 | 1220 | result.stdout.fnmatch_lines(["* 1 skipped *"])
|
1174 | 1221 |
|
1175 | 1222 | def test_parametrized_ids_invalid_type(self, testdir):
|
1176 |
| - """Tests parametrized with ids as non-strings (#1857).""" |
| 1223 | + """Test error with non-strings/non-ints, without generator (#1857).""" |
1177 | 1224 | testdir.makepyfile(
|
1178 | 1225 | """
|
1179 | 1226 | import pytest
|
1180 | 1227 |
|
1181 |
| - @pytest.mark.parametrize("x, expected", [(10, 20), (40, 80)], ids=(None, 2)) |
| 1228 | + @pytest.mark.parametrize("x, expected", [(1, 2), (3, 4), (5, 6)], ids=(None, 2, type)) |
1182 | 1229 | def test_ids_numbers(x,expected):
|
1183 | 1230 | assert x * 2 == expected
|
1184 | 1231 | """
|
1185 | 1232 | )
|
1186 | 1233 | result = testdir.runpytest()
|
1187 | 1234 | result.stdout.fnmatch_lines(
|
1188 | 1235 | [
|
1189 |
| - "*In test_ids_numbers: ids must be list of strings, found: 2 (type: *'int'>)*" |
| 1236 | + "In test_ids_numbers: ids must be list of string/float/int/bool," |
| 1237 | + " found: <class 'type'> (type: <class 'type'>) at index 2" |
1190 | 1238 | ]
|
1191 | 1239 | )
|
1192 | 1240 |
|
@@ -1784,3 +1832,39 @@ def test_foo(a):
|
1784 | 1832 | )
|
1785 | 1833 | result = testdir.runpytest()
|
1786 | 1834 | result.assert_outcomes(passed=1)
|
| 1835 | + |
| 1836 | + def test_parametrize_iterator(self, testdir): |
| 1837 | + testdir.makepyfile( |
| 1838 | + """ |
| 1839 | + import itertools |
| 1840 | + import pytest |
| 1841 | +
|
| 1842 | + id_parametrize = pytest.mark.parametrize( |
| 1843 | + ids=("param%d" % i for i in itertools.count() |
| 1844 | + )) |
| 1845 | +
|
| 1846 | + @id_parametrize('y', ['a', 'b']) |
| 1847 | + def test1(y): |
| 1848 | + pass |
| 1849 | +
|
| 1850 | + @id_parametrize('y', ['a', 'b']) |
| 1851 | + def test2(y): |
| 1852 | + pass |
| 1853 | +
|
| 1854 | + @pytest.mark.parametrize("a, b", [(1, 2), (3, 4)], ids=itertools.count()) |
| 1855 | + def test_converted_to_str(a, b): |
| 1856 | + pass |
| 1857 | + """ |
| 1858 | + ) |
| 1859 | + result = testdir.runpytest("-vv", "-s") |
| 1860 | + result.stdout.fnmatch_lines_random( # random for py35. |
| 1861 | + [ |
| 1862 | + "test_parametrize_iterator.py::test1[param0] PASSED", |
| 1863 | + "test_parametrize_iterator.py::test1[param1] PASSED", |
| 1864 | + "test_parametrize_iterator.py::test2[param2] PASSED", |
| 1865 | + "test_parametrize_iterator.py::test2[param3] PASSED", |
| 1866 | + "test_parametrize_iterator.py::test_converted_to_str[0] PASSED", |
| 1867 | + "test_parametrize_iterator.py::test_converted_to_str[1] PASSED", |
| 1868 | + "*= 6 passed in *", |
| 1869 | + ] |
| 1870 | + ) |
0 commit comments