1# -*- coding: utf-8 -*-
2import re
3import sys
4import attr
5import _pytest._code
6import py
7import pytest
8from _pytest import python, fixtures
9
10import hypothesis
11from hypothesis import strategies
12
13PY3 = sys.version_info >= (3, 0)
14
15
16class TestMetafunc(object):
17
18    def Metafunc(self, func, config=None):
19        # the unit tests of this class check if things work correctly
20        # on the funcarg level, so we don't need a full blown
21        # initiliazation
22        class FixtureInfo(object):
23            name2fixturedefs = None
24
25            def __init__(self, names):
26                self.names_closure = names
27
28        @attr.s
29        class DefinitionMock(object):
30            obj = attr.ib()
31
32        names = fixtures.getfuncargnames(func)
33        fixtureinfo = FixtureInfo(names)
34        definition = DefinitionMock(func)
35        return python.Metafunc(definition, fixtureinfo, config)
36
37    def test_no_funcargs(self, testdir):
38
39        def function():
40            pass
41
42        metafunc = self.Metafunc(function)
43        assert not metafunc.fixturenames
44        repr(metafunc._calls)
45
46    def test_function_basic(self):
47
48        def func(arg1, arg2="qwe"):
49            pass
50
51        metafunc = self.Metafunc(func)
52        assert len(metafunc.fixturenames) == 1
53        assert "arg1" in metafunc.fixturenames
54        assert metafunc.function is func
55        assert metafunc.cls is None
56
57    def test_addcall_no_args(self):
58
59        def func(arg1):
60            pass
61
62        metafunc = self.Metafunc(func)
63        metafunc.addcall()
64        assert len(metafunc._calls) == 1
65        call = metafunc._calls[0]
66        assert call.id == "0"
67        assert not hasattr(call, "param")
68
69    def test_addcall_id(self):
70
71        def func(arg1):
72            pass
73
74        metafunc = self.Metafunc(func)
75        pytest.raises(ValueError, "metafunc.addcall(id=None)")
76
77        metafunc.addcall(id=1)
78        pytest.raises(ValueError, "metafunc.addcall(id=1)")
79        pytest.raises(ValueError, "metafunc.addcall(id='1')")
80        metafunc.addcall(id=2)
81        assert len(metafunc._calls) == 2
82        assert metafunc._calls[0].id == "1"
83        assert metafunc._calls[1].id == "2"
84
85    def test_addcall_param(self):
86
87        def func(arg1):
88            pass
89
90        metafunc = self.Metafunc(func)
91
92        class obj(object):
93            pass
94
95        metafunc.addcall(param=obj)
96        metafunc.addcall(param=obj)
97        metafunc.addcall(param=1)
98        assert len(metafunc._calls) == 3
99        assert metafunc._calls[0].getparam("arg1") == obj
100        assert metafunc._calls[1].getparam("arg1") == obj
101        assert metafunc._calls[2].getparam("arg1") == 1
102
103    def test_addcall_funcargs(self):
104
105        def func(x):
106            pass
107
108        metafunc = self.Metafunc(func)
109
110        class obj(object):
111            pass
112
113        metafunc.addcall(funcargs={"x": 2})
114        metafunc.addcall(funcargs={"x": 3})
115        pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})")
116        assert len(metafunc._calls) == 2
117        assert metafunc._calls[0].funcargs == {"x": 2}
118        assert metafunc._calls[1].funcargs == {"x": 3}
119        assert not hasattr(metafunc._calls[1], "param")
120
121    def test_parametrize_error(self):
122
123        def func(x, y):
124            pass
125
126        metafunc = self.Metafunc(func)
127        metafunc.parametrize("x", [1, 2])
128        pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6]))
129        pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6]))
130        metafunc.parametrize("y", [1, 2])
131        pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
132        pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
133
134    def test_parametrize_bad_scope(self, testdir):
135
136        def func(x):
137            pass
138
139        metafunc = self.Metafunc(func)
140        try:
141            metafunc.parametrize("x", [1], scope="doggy")
142        except ValueError as ve:
143            assert "has an unsupported scope value 'doggy'" in str(ve)
144
145    def test_parametrize_and_id(self):
146
147        def func(x, y):
148            pass
149
150        metafunc = self.Metafunc(func)
151
152        metafunc.parametrize("x", [1, 2], ids=["basic", "advanced"])
153        metafunc.parametrize("y", ["abc", "def"])
154        ids = [x.id for x in metafunc._calls]
155        assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"]
156
157    def test_parametrize_and_id_unicode(self):
158        """Allow unicode strings for "ids" parameter in Python 2 (##1905)"""
159
160        def func(x):
161            pass
162
163        metafunc = self.Metafunc(func)
164        metafunc.parametrize("x", [1, 2], ids=[u"basic", u"advanced"])
165        ids = [x.id for x in metafunc._calls]
166        assert ids == [u"basic", u"advanced"]
167
168    def test_parametrize_with_wrong_number_of_ids(self, testdir):
169
170        def func(x, y):
171            pass
172
173        metafunc = self.Metafunc(func)
174
175        pytest.raises(
176            ValueError, lambda: metafunc.parametrize("x", [1, 2], ids=["basic"])
177        )
178
179        pytest.raises(
180            ValueError,
181            lambda: metafunc.parametrize(
182                ("x", "y"), [("abc", "def"), ("ghi", "jkl")], ids=["one"]
183            ),
184        )
185
186    @pytest.mark.issue510
187    def test_parametrize_empty_list(self):
188
189        def func(y):
190            pass
191
192        class MockConfig(object):
193
194            def getini(self, name):
195                return ""
196
197            @property
198            def hook(self):
199                return self
200
201            def pytest_make_parametrize_id(self, **kw):
202                pass
203
204        metafunc = self.Metafunc(func, MockConfig())
205        metafunc.parametrize("y", [])
206        assert "skip" == metafunc._calls[0].marks[0].name
207
208    def test_parametrize_with_userobjects(self):
209
210        def func(x, y):
211            pass
212
213        metafunc = self.Metafunc(func)
214
215        class A(object):
216            pass
217
218        metafunc.parametrize("x", [A(), A()])
219        metafunc.parametrize("y", list("ab"))
220        assert metafunc._calls[0].id == "x0-a"
221        assert metafunc._calls[1].id == "x0-b"
222        assert metafunc._calls[2].id == "x1-a"
223        assert metafunc._calls[3].id == "x1-b"
224
225    @hypothesis.given(strategies.text() | strategies.binary())
226    @hypothesis.settings(
227        deadline=400.0
228    )  # very close to std deadline and CI boxes are not reliable in CPU power
229    def test_idval_hypothesis(self, value):
230        from _pytest.python import _idval
231
232        escaped = _idval(value, "a", 6, None)
233        assert isinstance(escaped, str)
234        if PY3:
235            escaped.encode("ascii")
236        else:
237            escaped.decode("ascii")
238
239    def test_unicode_idval(self):
240        """This tests that Unicode strings outside the ASCII character set get
241        escaped, using byte escapes if they're in that range or unicode
242        escapes if they're not.
243
244        """
245        from _pytest.python import _idval
246
247        values = [
248            (u"", ""),
249            (u"ascii", "ascii"),
250            (u"ação", "a\\xe7\\xe3o"),
251            (u"josé@blah.com", "jos\\xe9@blah.com"),
252            (
253                u"δοκ.ιμή@παράδειγμα.δοκιμή",
254                "\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3"
255                "\\u03bc\\u03b1.\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae",
256            ),
257        ]
258        for val, expected in values:
259            assert _idval(val, "a", 6, None) == expected
260
261    def test_bytes_idval(self):
262        """unittest for the expected behavior to obtain ids for parametrized
263        bytes values:
264        - python2: non-ascii strings are considered bytes and formatted using
265        "binary escape", where any byte < 127 is escaped into its hex form.
266        - python3: bytes objects are always escaped using "binary escape".
267        """
268        from _pytest.python import _idval
269
270        values = [
271            (b"", ""),
272            (b"\xc3\xb4\xff\xe4", "\\xc3\\xb4\\xff\\xe4"),
273            (b"ascii", "ascii"),
274            (u"αρά".encode("utf-8"), "\\xce\\xb1\\xcf\\x81\\xce\\xac"),
275        ]
276        for val, expected in values:
277            assert _idval(val, "a", 6, None) == expected
278
279    def test_class_or_function_idval(self):
280        """unittest for the expected behavior to obtain ids for parametrized
281        values that are classes or functions: their __name__.
282        """
283        from _pytest.python import _idval
284
285        class TestClass(object):
286            pass
287
288        def test_function():
289            pass
290
291        values = [(TestClass, "TestClass"), (test_function, "test_function")]
292        for val, expected in values:
293            assert _idval(val, "a", 6, None) == expected
294
295    @pytest.mark.issue250
296    def test_idmaker_autoname(self):
297        from _pytest.python import idmaker
298
299        result = idmaker(
300            ("a", "b"), [pytest.param("string", 1.0), pytest.param("st-ring", 2.0)]
301        )
302        assert result == ["string-1.0", "st-ring-2.0"]
303
304        result = idmaker(
305            ("a", "b"), [pytest.param(object(), 1.0), pytest.param(object(), object())]
306        )
307        assert result == ["a0-1.0", "a1-b1"]
308        # unicode mixing, issue250
309        result = idmaker(
310            (py.builtin._totext("a"), "b"), [pytest.param({}, b"\xc3\xb4")]
311        )
312        assert result == ["a0-\\xc3\\xb4"]
313
314    def test_idmaker_with_bytes_regex(self):
315        from _pytest.python import idmaker
316
317        result = idmaker(("a"), [pytest.param(re.compile(b"foo"), 1.0)])
318        assert result == ["foo"]
319
320    def test_idmaker_native_strings(self):
321        from _pytest.python import idmaker
322
323        totext = py.builtin._totext
324        result = idmaker(
325            ("a", "b"),
326            [
327                pytest.param(1.0, -1.1),
328                pytest.param(2, -202),
329                pytest.param("three", "three hundred"),
330                pytest.param(True, False),
331                pytest.param(None, None),
332                pytest.param(re.compile("foo"), re.compile("bar")),
333                pytest.param(str, int),
334                pytest.param(list("six"), [66, 66]),
335                pytest.param({7}, set("seven")),
336                pytest.param(tuple("eight"), (8, -8, 8)),
337                pytest.param(b"\xc3\xb4", b"name"),
338                pytest.param(b"\xc3\xb4", totext("other")),
339            ],
340        )
341        assert (
342            result
343            == [
344                "1.0--1.1",
345                "2--202",
346                "three-three hundred",
347                "True-False",
348                "None-None",
349                "foo-bar",
350                "str-int",
351                "a7-b7",
352                "a8-b8",
353                "a9-b9",
354                "\\xc3\\xb4-name",
355                "\\xc3\\xb4-other",
356            ]
357        )
358
359    def test_idmaker_enum(self):
360        from _pytest.python import idmaker
361
362        enum = pytest.importorskip("enum")
363        e = enum.Enum("Foo", "one, two")
364        result = idmaker(("a", "b"), [pytest.param(e.one, e.two)])
365        assert result == ["Foo.one-Foo.two"]
366
367    @pytest.mark.issue351
368    def test_idmaker_idfn(self):
369        from _pytest.python import idmaker
370
371        def ids(val):
372            if isinstance(val, Exception):
373                return repr(val)
374
375        result = idmaker(
376            ("a", "b"),
377            [
378                pytest.param(10.0, IndexError()),
379                pytest.param(20, KeyError()),
380                pytest.param("three", [1, 2, 3]),
381            ],
382            idfn=ids,
383        )
384        assert result == ["10.0-IndexError()", "20-KeyError()", "three-b2"]
385
386    @pytest.mark.issue351
387    def test_idmaker_idfn_unique_names(self):
388        from _pytest.python import idmaker
389
390        def ids(val):
391            return "a"
392
393        result = idmaker(
394            ("a", "b"),
395            [
396                pytest.param(10.0, IndexError()),
397                pytest.param(20, KeyError()),
398                pytest.param("three", [1, 2, 3]),
399            ],
400            idfn=ids,
401        )
402        assert result == ["a-a0", "a-a1", "a-a2"]
403
404    @pytest.mark.issue351
405    def test_idmaker_idfn_exception(self):
406        from _pytest.python import idmaker
407        from _pytest.recwarn import WarningsRecorder
408
409        class BadIdsException(Exception):
410            pass
411
412        def ids(val):
413            raise BadIdsException("ids raised")
414
415        rec = WarningsRecorder()
416        with rec:
417            idmaker(
418                ("a", "b"),
419                [
420                    pytest.param(10.0, IndexError()),
421                    pytest.param(20, KeyError()),
422                    pytest.param("three", [1, 2, 3]),
423                ],
424                idfn=ids,
425            )
426
427        assert (
428            [str(i.message) for i in rec.list]
429            == [
430                "Raised while trying to determine id of parameter a at position 0."
431                "\nUpdate your code as this will raise an error in pytest-4.0.",
432                "Raised while trying to determine id of parameter b at position 0."
433                "\nUpdate your code as this will raise an error in pytest-4.0.",
434                "Raised while trying to determine id of parameter a at position 1."
435                "\nUpdate your code as this will raise an error in pytest-4.0.",
436                "Raised while trying to determine id of parameter b at position 1."
437                "\nUpdate your code as this will raise an error in pytest-4.0.",
438                "Raised while trying to determine id of parameter a at position 2."
439                "\nUpdate your code as this will raise an error in pytest-4.0.",
440                "Raised while trying to determine id of parameter b at position 2."
441                "\nUpdate your code as this will raise an error in pytest-4.0.",
442            ]
443        )
444
445    def test_parametrize_ids_exception(self, testdir):
446        """
447        :param testdir: the instance of Testdir class, a temporary
448        test directory.
449        """
450        testdir.makepyfile(
451            """
452                import pytest
453
454                def ids(arg):
455                    raise Exception("bad ids")
456
457                @pytest.mark.parametrize("arg", ["a", "b"], ids=ids)
458                def test_foo(arg):
459                    pass
460            """
461        )
462        with pytest.warns(DeprecationWarning):
463            result = testdir.runpytest("--collect-only")
464        result.stdout.fnmatch_lines(
465            [
466                "<Module 'test_parametrize_ids_exception.py'>",
467                "  <Function 'test_foo[a]'>",
468                "  <Function 'test_foo[b]'>",
469            ]
470        )
471
472    def test_idmaker_with_ids(self):
473        from _pytest.python import idmaker
474
475        result = idmaker(
476            ("a", "b"), [pytest.param(1, 2), pytest.param(3, 4)], ids=["a", None]
477        )
478        assert result == ["a", "3-4"]
479
480    def test_idmaker_with_paramset_id(self):
481        from _pytest.python import idmaker
482
483        result = idmaker(
484            ("a", "b"),
485            [pytest.param(1, 2, id="me"), pytest.param(3, 4, id="you")],
486            ids=["a", None],
487        )
488        assert result == ["me", "you"]
489
490    def test_idmaker_with_ids_unique_names(self):
491        from _pytest.python import idmaker
492
493        result = idmaker(
494            ("a"), map(pytest.param, [1, 2, 3, 4, 5]), ids=["a", "a", "b", "c", "b"]
495        )
496        assert result == ["a0", "a1", "b0", "c", "b1"]
497
498    def test_addcall_and_parametrize(self):
499
500        def func(x, y):
501            pass
502
503        metafunc = self.Metafunc(func)
504        metafunc.addcall({"x": 1})
505        metafunc.parametrize("y", [2, 3])
506        assert len(metafunc._calls) == 2
507        assert metafunc._calls[0].funcargs == {"x": 1, "y": 2}
508        assert metafunc._calls[1].funcargs == {"x": 1, "y": 3}
509        assert metafunc._calls[0].id == "0-2"
510        assert metafunc._calls[1].id == "0-3"
511
512    @pytest.mark.issue714
513    def test_parametrize_indirect(self):
514
515        def func(x, y):
516            pass
517
518        metafunc = self.Metafunc(func)
519        metafunc.parametrize("x", [1], indirect=True)
520        metafunc.parametrize("y", [2, 3], indirect=True)
521        assert len(metafunc._calls) == 2
522        assert metafunc._calls[0].funcargs == {}
523        assert metafunc._calls[1].funcargs == {}
524        assert metafunc._calls[0].params == dict(x=1, y=2)
525        assert metafunc._calls[1].params == dict(x=1, y=3)
526
527    @pytest.mark.issue714
528    def test_parametrize_indirect_list(self):
529
530        def func(x, y):
531            pass
532
533        metafunc = self.Metafunc(func)
534        metafunc.parametrize("x, y", [("a", "b")], indirect=["x"])
535        assert metafunc._calls[0].funcargs == dict(y="b")
536        assert metafunc._calls[0].params == dict(x="a")
537
538    @pytest.mark.issue714
539    def test_parametrize_indirect_list_all(self):
540
541        def func(x, y):
542            pass
543
544        metafunc = self.Metafunc(func)
545        metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "y"])
546        assert metafunc._calls[0].funcargs == {}
547        assert metafunc._calls[0].params == dict(x="a", y="b")
548
549    @pytest.mark.issue714
550    def test_parametrize_indirect_list_empty(self):
551
552        def func(x, y):
553            pass
554
555        metafunc = self.Metafunc(func)
556        metafunc.parametrize("x, y", [("a", "b")], indirect=[])
557        assert metafunc._calls[0].funcargs == dict(x="a", y="b")
558        assert metafunc._calls[0].params == {}
559
560    @pytest.mark.issue714
561    def test_parametrize_indirect_list_functional(self, testdir):
562        """
563        Test parametrization with 'indirect' parameter applied on
564        particular arguments. As y is is direct, its value should
565        be used directly rather than being passed to the fixture
566        y.
567
568        :param testdir: the instance of Testdir class, a temporary
569        test directory.
570        """
571        testdir.makepyfile(
572            """
573            import pytest
574            @pytest.fixture(scope='function')
575            def x(request):
576                return request.param * 3
577            @pytest.fixture(scope='function')
578            def y(request):
579                return request.param * 2
580            @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
581            def test_simple(x,y):
582                assert len(x) == 3
583                assert len(y) == 1
584        """
585        )
586        result = testdir.runpytest("-v")
587        result.stdout.fnmatch_lines(["*test_simple*a-b*", "*1 passed*"])
588
589    @pytest.mark.issue714
590    def test_parametrize_indirect_list_error(self, testdir):
591
592        def func(x, y):
593            pass
594
595        metafunc = self.Metafunc(func)
596        with pytest.raises(ValueError):
597            metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "z"])
598
599    @pytest.mark.issue714
600    def test_parametrize_uses_no_fixture_error_indirect_false(self, testdir):
601        """The 'uses no fixture' error tells the user at collection time
602        that the parametrize data they've set up doesn't correspond to the
603        fixtures in their test function, rather than silently ignoring this
604        and letting the test potentially pass.
605        """
606        testdir.makepyfile(
607            """
608            import pytest
609
610            @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=False)
611            def test_simple(x):
612                assert len(x) == 3
613        """
614        )
615        result = testdir.runpytest("--collect-only")
616        result.stdout.fnmatch_lines(["*uses no argument 'y'*"])
617
618    @pytest.mark.issue714
619    def test_parametrize_uses_no_fixture_error_indirect_true(self, testdir):
620        testdir.makepyfile(
621            """
622            import pytest
623            @pytest.fixture(scope='function')
624            def x(request):
625                return request.param * 3
626            @pytest.fixture(scope='function')
627            def y(request):
628                return request.param * 2
629
630            @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=True)
631            def test_simple(x):
632                assert len(x) == 3
633        """
634        )
635        result = testdir.runpytest("--collect-only")
636        result.stdout.fnmatch_lines(["*uses no fixture 'y'*"])
637
638    @pytest.mark.issue714
639    def test_parametrize_indirect_uses_no_fixture_error_indirect_string(self, testdir):
640        testdir.makepyfile(
641            """
642            import pytest
643            @pytest.fixture(scope='function')
644            def x(request):
645                return request.param * 3
646
647            @pytest.mark.parametrize('x, y', [('a', 'b')], indirect='y')
648            def test_simple(x):
649                assert len(x) == 3
650        """
651        )
652        result = testdir.runpytest("--collect-only")
653        result.stdout.fnmatch_lines(["*uses no fixture 'y'*"])
654
655    @pytest.mark.issue714
656    def test_parametrize_indirect_uses_no_fixture_error_indirect_list(self, testdir):
657        testdir.makepyfile(
658            """
659            import pytest
660            @pytest.fixture(scope='function')
661            def x(request):
662                return request.param * 3
663
664            @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['y'])
665            def test_simple(x):
666                assert len(x) == 3
667        """
668        )
669        result = testdir.runpytest("--collect-only")
670        result.stdout.fnmatch_lines(["*uses no fixture 'y'*"])
671
672    @pytest.mark.issue714
673    def test_parametrize_argument_not_in_indirect_list(self, testdir):
674        testdir.makepyfile(
675            """
676            import pytest
677            @pytest.fixture(scope='function')
678            def x(request):
679                return request.param * 3
680
681            @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
682            def test_simple(x):
683                assert len(x) == 3
684        """
685        )
686        result = testdir.runpytest("--collect-only")
687        result.stdout.fnmatch_lines(["*uses no argument 'y'*"])
688
689    def test_parametrize_gives_indicative_error_on_function_with_default_argument(
690        self, testdir
691    ):
692        testdir.makepyfile(
693            """
694            import pytest
695
696            @pytest.mark.parametrize('x, y', [('a', 'b')])
697            def test_simple(x, y=1):
698                assert len(x) == 1
699        """
700        )
701        result = testdir.runpytest("--collect-only")
702        result.stdout.fnmatch_lines(
703            ["*already takes an argument 'y' with a default value"]
704        )
705
706    def test_addcalls_and_parametrize_indirect(self):
707
708        def func(x, y):
709            pass
710
711        metafunc = self.Metafunc(func)
712        metafunc.addcall(param="123")
713        metafunc.parametrize("x", [1], indirect=True)
714        metafunc.parametrize("y", [2, 3], indirect=True)
715        assert len(metafunc._calls) == 2
716        assert metafunc._calls[0].funcargs == {}
717        assert metafunc._calls[1].funcargs == {}
718        assert metafunc._calls[0].params == dict(x=1, y=2)
719        assert metafunc._calls[1].params == dict(x=1, y=3)
720
721    def test_parametrize_functional(self, testdir):
722        testdir.makepyfile(
723            """
724            import pytest
725            def pytest_generate_tests(metafunc):
726                metafunc.parametrize('x', [1,2], indirect=True)
727                metafunc.parametrize('y', [2])
728            @pytest.fixture
729            def x(request):
730                return request.param * 10
731
732            def test_simple(x,y):
733                assert x in (10,20)
734                assert y == 2
735        """
736        )
737        result = testdir.runpytest("-v")
738        result.stdout.fnmatch_lines(
739            ["*test_simple*1-2*", "*test_simple*2-2*", "*2 passed*"]
740        )
741
742    def test_parametrize_onearg(self):
743        metafunc = self.Metafunc(lambda x: None)
744        metafunc.parametrize("x", [1, 2])
745        assert len(metafunc._calls) == 2
746        assert metafunc._calls[0].funcargs == dict(x=1)
747        assert metafunc._calls[0].id == "1"
748        assert metafunc._calls[1].funcargs == dict(x=2)
749        assert metafunc._calls[1].id == "2"
750
751    def test_parametrize_onearg_indirect(self):
752        metafunc = self.Metafunc(lambda x: None)
753        metafunc.parametrize("x", [1, 2], indirect=True)
754        assert metafunc._calls[0].params == dict(x=1)
755        assert metafunc._calls[0].id == "1"
756        assert metafunc._calls[1].params == dict(x=2)
757        assert metafunc._calls[1].id == "2"
758
759    def test_parametrize_twoargs(self):
760        metafunc = self.Metafunc(lambda x, y: None)
761        metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)])
762        assert len(metafunc._calls) == 2
763        assert metafunc._calls[0].funcargs == dict(x=1, y=2)
764        assert metafunc._calls[0].id == "1-2"
765        assert metafunc._calls[1].funcargs == dict(x=3, y=4)
766        assert metafunc._calls[1].id == "3-4"
767
768    def test_parametrize_multiple_times(self, testdir):
769        testdir.makepyfile(
770            """
771            import pytest
772            pytestmark = pytest.mark.parametrize("x", [1,2])
773            def test_func(x):
774                assert 0, x
775            class TestClass(object):
776                pytestmark = pytest.mark.parametrize("y", [3,4])
777                def test_meth(self, x, y):
778                    assert 0, x
779        """
780        )
781        result = testdir.runpytest()
782        assert result.ret == 1
783        result.assert_outcomes(failed=6)
784
785    def test_parametrize_CSV(self, testdir):
786        testdir.makepyfile(
787            """
788            import pytest
789            @pytest.mark.parametrize("x, y,", [(1,2), (2,3)])
790            def test_func(x, y):
791                assert x+1 == y
792        """
793        )
794        reprec = testdir.inline_run()
795        reprec.assertoutcome(passed=2)
796
797    def test_parametrize_class_scenarios(self, testdir):
798        testdir.makepyfile(
799            """
800        # same as doc/en/example/parametrize scenario example
801        def pytest_generate_tests(metafunc):
802            idlist = []
803            argvalues = []
804            for scenario in metafunc.cls.scenarios:
805                idlist.append(scenario[0])
806                items = scenario[1].items()
807                argnames = [x[0] for x in items]
808                argvalues.append(([x[1] for x in items]))
809            metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
810
811        class Test(object):
812               scenarios = [['1', {'arg': {1: 2}, "arg2": "value2"}],
813                            ['2', {'arg':'value2', "arg2": "value2"}]]
814
815               def test_1(self, arg, arg2):
816                  pass
817
818               def test_2(self, arg2, arg):
819                  pass
820
821               def test_3(self, arg, arg2):
822                  pass
823        """
824        )
825        result = testdir.runpytest("-v")
826        assert result.ret == 0
827        result.stdout.fnmatch_lines(
828            """
829            *test_1*1*
830            *test_2*1*
831            *test_3*1*
832            *test_1*2*
833            *test_2*2*
834            *test_3*2*
835            *6 passed*
836        """
837        )
838
839    def test_format_args(self):
840
841        def function1():
842            pass
843
844        assert fixtures._format_args(function1) == "()"
845
846        def function2(arg1):
847            pass
848
849        assert fixtures._format_args(function2) == "(arg1)"
850
851        def function3(arg1, arg2="qwe"):
852            pass
853
854        assert fixtures._format_args(function3) == "(arg1, arg2='qwe')"
855
856        def function4(arg1, *args, **kwargs):
857            pass
858
859        assert fixtures._format_args(function4) == "(arg1, *args, **kwargs)"
860
861
862class TestMetafuncFunctional(object):
863
864    def test_attributes(self, testdir):
865        p = testdir.makepyfile(
866            """
867            # assumes that generate/provide runs in the same process
868            import sys, pytest
869            def pytest_generate_tests(metafunc):
870                metafunc.addcall(param=metafunc)
871
872            @pytest.fixture
873            def metafunc(request):
874                assert request._pyfuncitem._genid == "0"
875                return request.param
876
877            def test_function(metafunc, pytestconfig):
878                assert metafunc.config == pytestconfig
879                assert metafunc.module.__name__ == __name__
880                assert metafunc.function == test_function
881                assert metafunc.cls is None
882
883            class TestClass(object):
884                def test_method(self, metafunc, pytestconfig):
885                    assert metafunc.config == pytestconfig
886                    assert metafunc.module.__name__ == __name__
887                    if sys.version_info > (3, 0):
888                        unbound = TestClass.test_method
889                    else:
890                        unbound = TestClass.test_method.im_func
891                    # XXX actually have an unbound test function here?
892                    assert metafunc.function == unbound
893                    assert metafunc.cls == TestClass
894        """
895        )
896        result = testdir.runpytest(p, "-v")
897        result.assert_outcomes(passed=2)
898
899    def test_addcall_with_two_funcargs_generators(self, testdir):
900        testdir.makeconftest(
901            """
902            def pytest_generate_tests(metafunc):
903                assert "arg1" in metafunc.fixturenames
904                metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
905        """
906        )
907        p = testdir.makepyfile(
908            """
909            def pytest_generate_tests(metafunc):
910                metafunc.addcall(funcargs=dict(arg1=1, arg2=1))
911
912            class TestClass(object):
913                def test_myfunc(self, arg1, arg2):
914                    assert arg1 == arg2
915        """
916        )
917        result = testdir.runpytest("-v", p)
918        result.stdout.fnmatch_lines(
919            ["*test_myfunc*0*PASS*", "*test_myfunc*1*FAIL*", "*1 failed, 1 passed*"]
920        )
921
922    def test_two_functions(self, testdir):
923        p = testdir.makepyfile(
924            """
925            def pytest_generate_tests(metafunc):
926                metafunc.addcall(param=10)
927                metafunc.addcall(param=20)
928
929            import pytest
930            @pytest.fixture
931            def arg1(request):
932                return request.param
933
934            def test_func1(arg1):
935                assert arg1 == 10
936            def test_func2(arg1):
937                assert arg1 in (10, 20)
938        """
939        )
940        result = testdir.runpytest("-v", p)
941        result.stdout.fnmatch_lines(
942            [
943                "*test_func1*0*PASS*",
944                "*test_func1*1*FAIL*",
945                "*test_func2*PASS*",
946                "*1 failed, 3 passed*",
947            ]
948        )
949
950    def test_noself_in_method(self, testdir):
951        p = testdir.makepyfile(
952            """
953            def pytest_generate_tests(metafunc):
954                assert 'xyz' not in metafunc.fixturenames
955
956            class TestHello(object):
957                def test_hello(xyz):
958                    pass
959        """
960        )
961        result = testdir.runpytest(p)
962        result.assert_outcomes(passed=1)
963
964    def test_generate_plugin_and_module(self, testdir):
965        testdir.makeconftest(
966            """
967            def pytest_generate_tests(metafunc):
968                assert "arg1" in metafunc.fixturenames
969                metafunc.addcall(id="world", param=(2,100))
970        """
971        )
972        p = testdir.makepyfile(
973            """
974            def pytest_generate_tests(metafunc):
975                metafunc.addcall(param=(1,1), id="hello")
976
977            import pytest
978            @pytest.fixture
979            def arg1(request):
980                return request.param[0]
981            @pytest.fixture
982            def arg2(request):
983                return request.param[1]
984
985            class TestClass(object):
986                def test_myfunc(self, arg1, arg2):
987                    assert arg1 == arg2
988        """
989        )
990        result = testdir.runpytest("-v", p)
991        result.stdout.fnmatch_lines(
992            [
993                "*test_myfunc*hello*PASS*",
994                "*test_myfunc*world*FAIL*",
995                "*1 failed, 1 passed*",
996            ]
997        )
998
999    def test_generate_tests_in_class(self, testdir):
1000        p = testdir.makepyfile(
1001            """
1002            class TestClass(object):
1003                def pytest_generate_tests(self, metafunc):
1004                    metafunc.addcall(funcargs={'hello': 'world'}, id="hello")
1005
1006                def test_myfunc(self, hello):
1007                    assert hello == "world"
1008        """
1009        )
1010        result = testdir.runpytest("-v", p)
1011        result.stdout.fnmatch_lines(["*test_myfunc*hello*PASS*", "*1 passed*"])
1012
1013    def test_two_functions_not_same_instance(self, testdir):
1014        p = testdir.makepyfile(
1015            """
1016            def pytest_generate_tests(metafunc):
1017                metafunc.addcall({'arg1': 10})
1018                metafunc.addcall({'arg1': 20})
1019
1020            class TestClass(object):
1021                def test_func(self, arg1):
1022                    assert not hasattr(self, 'x')
1023                    self.x = 1
1024        """
1025        )
1026        result = testdir.runpytest("-v", p)
1027        result.stdout.fnmatch_lines(
1028            ["*test_func*0*PASS*", "*test_func*1*PASS*", "*2 pass*"]
1029        )
1030
1031    def test_issue28_setup_method_in_generate_tests(self, testdir):
1032        p = testdir.makepyfile(
1033            """
1034            def pytest_generate_tests(metafunc):
1035                metafunc.addcall({'arg1': 1})
1036
1037            class TestClass(object):
1038                def test_method(self, arg1):
1039                    assert arg1 == self.val
1040                def setup_method(self, func):
1041                    self.val = 1
1042            """
1043        )
1044        result = testdir.runpytest(p)
1045        result.assert_outcomes(passed=1)
1046
1047    def test_parametrize_functional2(self, testdir):
1048        testdir.makepyfile(
1049            """
1050            def pytest_generate_tests(metafunc):
1051                metafunc.parametrize("arg1", [1,2])
1052                metafunc.parametrize("arg2", [4,5])
1053            def test_hello(arg1, arg2):
1054                assert 0, (arg1, arg2)
1055        """
1056        )
1057        result = testdir.runpytest()
1058        result.stdout.fnmatch_lines(
1059            ["*(1, 4)*", "*(1, 5)*", "*(2, 4)*", "*(2, 5)*", "*4 failed*"]
1060        )
1061
1062    def test_parametrize_and_inner_getfixturevalue(self, testdir):
1063        p = testdir.makepyfile(
1064            """
1065            def pytest_generate_tests(metafunc):
1066                metafunc.parametrize("arg1", [1], indirect=True)
1067                metafunc.parametrize("arg2", [10], indirect=True)
1068
1069            import pytest
1070            @pytest.fixture
1071            def arg1(request):
1072                x = request.getfixturevalue("arg2")
1073                return x + request.param
1074
1075            @pytest.fixture
1076            def arg2(request):
1077                return request.param
1078
1079            def test_func1(arg1, arg2):
1080                assert arg1 == 11
1081        """
1082        )
1083        result = testdir.runpytest("-v", p)
1084        result.stdout.fnmatch_lines(["*test_func1*1*PASS*", "*1 passed*"])
1085
1086    def test_parametrize_on_setup_arg(self, testdir):
1087        p = testdir.makepyfile(
1088            """
1089            def pytest_generate_tests(metafunc):
1090                assert "arg1" in metafunc.fixturenames
1091                metafunc.parametrize("arg1", [1], indirect=True)
1092
1093            import pytest
1094            @pytest.fixture
1095            def arg1(request):
1096                return request.param
1097
1098            @pytest.fixture
1099            def arg2(request, arg1):
1100                return 10 * arg1
1101
1102            def test_func(arg2):
1103                assert arg2 == 10
1104        """
1105        )
1106        result = testdir.runpytest("-v", p)
1107        result.stdout.fnmatch_lines(["*test_func*1*PASS*", "*1 passed*"])
1108
1109    def test_parametrize_with_ids(self, testdir):
1110        testdir.makeini(
1111            """
1112            [pytest]
1113            console_output_style=classic
1114        """
1115        )
1116        testdir.makepyfile(
1117            """
1118            import pytest
1119            def pytest_generate_tests(metafunc):
1120                metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
1121                                     ids=["basic", "advanced"])
1122
1123            def test_function(a, b):
1124                assert a == b
1125        """
1126        )
1127        result = testdir.runpytest("-v")
1128        assert result.ret == 1
1129        result.stdout.fnmatch_lines_random(
1130            ["*test_function*basic*PASSED", "*test_function*advanced*FAILED"]
1131        )
1132
1133    def test_parametrize_without_ids(self, testdir):
1134        testdir.makepyfile(
1135            """
1136            import pytest
1137            def pytest_generate_tests(metafunc):
1138                metafunc.parametrize(("a", "b"),
1139                                     [(1,object()), (1.3,object())])
1140
1141            def test_function(a, b):
1142                assert 1
1143        """
1144        )
1145        result = testdir.runpytest("-v")
1146        result.stdout.fnmatch_lines(
1147            """
1148            *test_function*1-b0*
1149            *test_function*1.3-b1*
1150        """
1151        )
1152
1153    def test_parametrize_with_None_in_ids(self, testdir):
1154        testdir.makepyfile(
1155            """
1156            import pytest
1157            def pytest_generate_tests(metafunc):
1158                metafunc.parametrize(("a", "b"), [(1,1), (1,1), (1,2)],
1159                                     ids=["basic", None, "advanced"])
1160
1161            def test_function(a, b):
1162                assert a == b
1163        """
1164        )
1165        result = testdir.runpytest("-v")
1166        assert result.ret == 1
1167        result.stdout.fnmatch_lines_random(
1168            [
1169                "*test_function*basic*PASSED*",
1170                "*test_function*1-1*PASSED*",
1171                "*test_function*advanced*FAILED*",
1172            ]
1173        )
1174
1175    def test_fixture_parametrized_empty_ids(self, testdir):
1176        """Fixtures parametrized with empty ids cause an internal error (#1849)."""
1177        testdir.makepyfile(
1178            """
1179            import pytest
1180
1181            @pytest.fixture(scope="module", ids=[], params=[])
1182            def temp(request):
1183               return request.param
1184
1185            def test_temp(temp):
1186                 pass
1187        """
1188        )
1189        result = testdir.runpytest()
1190        result.stdout.fnmatch_lines(["* 1 skipped *"])
1191
1192    def test_parametrized_empty_ids(self, testdir):
1193        """Tests parametrized with empty ids cause an internal error (#1849)."""
1194        testdir.makepyfile(
1195            """
1196            import pytest
1197
1198            @pytest.mark.parametrize('temp', [], ids=list())
1199            def test_temp(temp):
1200                 pass
1201        """
1202        )
1203        result = testdir.runpytest()
1204        result.stdout.fnmatch_lines(["* 1 skipped *"])
1205
1206    def test_parametrized_ids_invalid_type(self, testdir):
1207        """Tests parametrized with ids as non-strings (#1857)."""
1208        testdir.makepyfile(
1209            """
1210            import pytest
1211
1212            @pytest.mark.parametrize("x, expected", [(10, 20), (40, 80)], ids=(None, 2))
1213            def test_ids_numbers(x,expected):
1214                assert x * 2 == expected
1215        """
1216        )
1217        result = testdir.runpytest()
1218        result.stdout.fnmatch_lines(
1219            ["*ids must be list of strings, found: 2 (type: int)*"]
1220        )
1221
1222    def test_parametrize_with_identical_ids_get_unique_names(self, testdir):
1223        testdir.makepyfile(
1224            """
1225            import pytest
1226            def pytest_generate_tests(metafunc):
1227                metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
1228                                     ids=["a", "a"])
1229
1230            def test_function(a, b):
1231                assert a == b
1232        """
1233        )
1234        result = testdir.runpytest("-v")
1235        assert result.ret == 1
1236        result.stdout.fnmatch_lines_random(
1237            ["*test_function*a0*PASSED*", "*test_function*a1*FAILED*"]
1238        )
1239
1240    @pytest.mark.parametrize(("scope", "length"), [("module", 2), ("function", 4)])
1241    def test_parametrize_scope_overrides(self, testdir, scope, length):
1242        testdir.makepyfile(
1243            """
1244            import pytest
1245            values = []
1246            def pytest_generate_tests(metafunc):
1247                if "arg" in metafunc.funcargnames:
1248                    metafunc.parametrize("arg", [1,2], indirect=True,
1249                                         scope=%r)
1250            @pytest.fixture
1251            def arg(request):
1252                values.append(request.param)
1253                return request.param
1254            def test_hello(arg):
1255                assert arg in (1,2)
1256            def test_world(arg):
1257                assert arg in (1,2)
1258            def test_checklength():
1259                assert len(values) == %d
1260        """
1261            % (scope, length)
1262        )
1263        reprec = testdir.inline_run()
1264        reprec.assertoutcome(passed=5)
1265
1266    def test_parametrize_issue323(self, testdir):
1267        testdir.makepyfile(
1268            """
1269            import pytest
1270
1271            @pytest.fixture(scope='module', params=range(966))
1272            def foo(request):
1273                return request.param
1274
1275            def test_it(foo):
1276                pass
1277            def test_it2(foo):
1278                pass
1279        """
1280        )
1281        reprec = testdir.inline_run("--collect-only")
1282        assert not reprec.getcalls("pytest_internalerror")
1283
1284    def test_usefixtures_seen_in_generate_tests(self, testdir):
1285        testdir.makepyfile(
1286            """
1287            import pytest
1288            def pytest_generate_tests(metafunc):
1289                assert "abc" in metafunc.fixturenames
1290                metafunc.parametrize("abc", [1])
1291
1292            @pytest.mark.usefixtures("abc")
1293            def test_function():
1294                pass
1295        """
1296        )
1297        reprec = testdir.runpytest()
1298        reprec.assert_outcomes(passed=1)
1299
1300    def test_generate_tests_only_done_in_subdir(self, testdir):
1301        sub1 = testdir.mkpydir("sub1")
1302        sub2 = testdir.mkpydir("sub2")
1303        sub1.join("conftest.py").write(
1304            _pytest._code.Source(
1305                """
1306            def pytest_generate_tests(metafunc):
1307                assert metafunc.function.__name__ == "test_1"
1308        """
1309            )
1310        )
1311        sub2.join("conftest.py").write(
1312            _pytest._code.Source(
1313                """
1314            def pytest_generate_tests(metafunc):
1315                assert metafunc.function.__name__ == "test_2"
1316        """
1317            )
1318        )
1319        sub1.join("test_in_sub1.py").write("def test_1(): pass")
1320        sub2.join("test_in_sub2.py").write("def test_2(): pass")
1321        result = testdir.runpytest("--keep-duplicates", "-v", "-s", sub1, sub2, sub1)
1322        result.assert_outcomes(passed=3)
1323
1324    def test_generate_same_function_names_issue403(self, testdir):
1325        testdir.makepyfile(
1326            """
1327            import pytest
1328
1329            def make_tests():
1330                @pytest.mark.parametrize("x", range(2))
1331                def test_foo(x):
1332                    pass
1333                return test_foo
1334
1335            test_x = make_tests()
1336            test_y = make_tests()
1337        """
1338        )
1339        reprec = testdir.runpytest()
1340        reprec.assert_outcomes(passed=4)
1341
1342    @pytest.mark.issue463
1343    @pytest.mark.parametrize("attr", ["parametrise", "parameterize", "parameterise"])
1344    def test_parametrize_misspelling(self, testdir, attr):
1345        testdir.makepyfile(
1346            """
1347            import pytest
1348
1349            @pytest.mark.{}("x", range(2))
1350            def test_foo(x):
1351                pass
1352        """.format(
1353                attr
1354            )
1355        )
1356        reprec = testdir.inline_run("--collectonly")
1357        failures = reprec.getfailures()
1358        assert len(failures) == 1
1359        expectederror = "MarkerError: test_foo has '{}', spelling should be 'parametrize'".format(
1360            attr
1361        )
1362        assert expectederror in failures[0].longrepr.reprcrash.message
1363
1364
1365class TestMetafuncFunctionalAuto(object):
1366    """
1367    Tests related to automatically find out the correct scope for parametrized tests (#1832).
1368    """
1369
1370    def test_parametrize_auto_scope(self, testdir):
1371        testdir.makepyfile(
1372            """
1373            import pytest
1374
1375            @pytest.fixture(scope='session', autouse=True)
1376            def fixture():
1377                return 1
1378
1379            @pytest.mark.parametrize('animal', ["dog", "cat"])
1380            def test_1(animal):
1381                assert animal in ('dog', 'cat')
1382
1383            @pytest.mark.parametrize('animal', ['fish'])
1384            def test_2(animal):
1385                assert animal == 'fish'
1386
1387        """
1388        )
1389        result = testdir.runpytest()
1390        result.stdout.fnmatch_lines(["* 3 passed *"])
1391
1392    def test_parametrize_auto_scope_indirect(self, testdir):
1393        testdir.makepyfile(
1394            """
1395            import pytest
1396
1397            @pytest.fixture(scope='session')
1398            def echo(request):
1399                return request.param
1400
1401            @pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=['echo'])
1402            def test_1(animal, echo):
1403                assert animal in ('dog', 'cat')
1404                assert echo in (1, 2, 3)
1405
1406            @pytest.mark.parametrize('animal, echo', [('fish', 3)], indirect=['echo'])
1407            def test_2(animal, echo):
1408                assert animal == 'fish'
1409                assert echo in (1, 2, 3)
1410        """
1411        )
1412        result = testdir.runpytest()
1413        result.stdout.fnmatch_lines(["* 3 passed *"])
1414
1415    def test_parametrize_auto_scope_override_fixture(self, testdir):
1416        testdir.makepyfile(
1417            """
1418            import pytest
1419
1420            @pytest.fixture(scope='session', autouse=True)
1421            def animal():
1422                return 'fox'
1423
1424            @pytest.mark.parametrize('animal', ["dog", "cat"])
1425            def test_1(animal):
1426                assert animal in ('dog', 'cat')
1427        """
1428        )
1429        result = testdir.runpytest()
1430        result.stdout.fnmatch_lines(["* 2 passed *"])
1431
1432    def test_parametrize_all_indirects(self, testdir):
1433        testdir.makepyfile(
1434            """
1435            import pytest
1436
1437            @pytest.fixture()
1438            def animal(request):
1439                return request.param
1440
1441            @pytest.fixture(scope='session')
1442            def echo(request):
1443                return request.param
1444
1445            @pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=True)
1446            def test_1(animal, echo):
1447                assert animal in ('dog', 'cat')
1448                assert echo in (1, 2, 3)
1449
1450            @pytest.mark.parametrize('animal, echo', [("fish", 3)], indirect=True)
1451            def test_2(animal, echo):
1452                assert animal == 'fish'
1453                assert echo in (1, 2, 3)
1454        """
1455        )
1456        result = testdir.runpytest()
1457        result.stdout.fnmatch_lines(["* 3 passed *"])
1458
1459    def test_parametrize_issue634(self, testdir):
1460        testdir.makepyfile(
1461            """
1462            import pytest
1463
1464            @pytest.fixture(scope='module')
1465            def foo(request):
1466                print('preparing foo-%d' % request.param)
1467                return 'foo-%d' % request.param
1468
1469            def test_one(foo):
1470                pass
1471
1472            def test_two(foo):
1473                pass
1474
1475            test_two.test_with = (2, 3)
1476
1477            def pytest_generate_tests(metafunc):
1478                params = (1, 2, 3, 4)
1479                if not 'foo' in metafunc.fixturenames:
1480                    return
1481
1482                test_with = getattr(metafunc.function, 'test_with', None)
1483                if test_with:
1484                    params = test_with
1485                metafunc.parametrize('foo', params, indirect=True)
1486        """
1487        )
1488        result = testdir.runpytest("-s")
1489        output = result.stdout.str()
1490        assert output.count("preparing foo-2") == 1
1491        assert output.count("preparing foo-3") == 1
1492
1493
1494@pytest.mark.filterwarnings("ignore:Applying marks directly to parameters")
1495@pytest.mark.issue308
1496class TestMarkersWithParametrization(object):
1497
1498    def test_simple_mark(self, testdir):
1499        s = """
1500            import pytest
1501
1502            @pytest.mark.foo
1503            @pytest.mark.parametrize(("n", "expected"), [
1504                (1, 2),
1505                pytest.mark.bar((1, 3)),
1506                (2, 3),
1507            ])
1508            def test_increment(n, expected):
1509                assert n + 1 == expected
1510        """
1511        items = testdir.getitems(s)
1512        assert len(items) == 3
1513        for item in items:
1514            assert "foo" in item.keywords
1515        assert "bar" not in items[0].keywords
1516        assert "bar" in items[1].keywords
1517        assert "bar" not in items[2].keywords
1518
1519    def test_select_based_on_mark(self, testdir):
1520        s = """
1521            import pytest
1522
1523            @pytest.mark.parametrize(("n", "expected"), [
1524                (1, 2),
1525                pytest.mark.foo((2, 3)),
1526                (3, 4),
1527            ])
1528            def test_increment(n, expected):
1529                assert n + 1 == expected
1530        """
1531        testdir.makepyfile(s)
1532        rec = testdir.inline_run("-m", "foo")
1533        passed, skipped, fail = rec.listoutcomes()
1534        assert len(passed) == 1
1535        assert len(skipped) == 0
1536        assert len(fail) == 0
1537
1538    @pytest.mark.xfail(reason="is this important to support??")
1539    def test_nested_marks(self, testdir):
1540        s = """
1541            import pytest
1542            mastermark = pytest.mark.foo(pytest.mark.bar)
1543
1544            @pytest.mark.parametrize(("n", "expected"), [
1545                (1, 2),
1546                mastermark((1, 3)),
1547                (2, 3),
1548            ])
1549            def test_increment(n, expected):
1550                assert n + 1 == expected
1551        """
1552        items = testdir.getitems(s)
1553        assert len(items) == 3
1554        for mark in ["foo", "bar"]:
1555            assert mark not in items[0].keywords
1556            assert mark in items[1].keywords
1557            assert mark not in items[2].keywords
1558
1559    def test_simple_xfail(self, testdir):
1560        s = """
1561            import pytest
1562
1563            @pytest.mark.parametrize(("n", "expected"), [
1564                (1, 2),
1565                pytest.mark.xfail((1, 3)),
1566                (2, 3),
1567            ])
1568            def test_increment(n, expected):
1569                assert n + 1 == expected
1570        """
1571        testdir.makepyfile(s)
1572        reprec = testdir.inline_run()
1573        # xfail is skip??
1574        reprec.assertoutcome(passed=2, skipped=1)
1575
1576    def test_simple_xfail_single_argname(self, testdir):
1577        s = """
1578            import pytest
1579
1580            @pytest.mark.parametrize("n", [
1581                2,
1582                pytest.mark.xfail(3),
1583                4,
1584            ])
1585            def test_isEven(n):
1586                assert n % 2 == 0
1587        """
1588        testdir.makepyfile(s)
1589        reprec = testdir.inline_run()
1590        reprec.assertoutcome(passed=2, skipped=1)
1591
1592    def test_xfail_with_arg(self, testdir):
1593        s = """
1594            import pytest
1595
1596            @pytest.mark.parametrize(("n", "expected"), [
1597                (1, 2),
1598                pytest.mark.xfail("True")((1, 3)),
1599                (2, 3),
1600            ])
1601            def test_increment(n, expected):
1602                assert n + 1 == expected
1603        """
1604        testdir.makepyfile(s)
1605        reprec = testdir.inline_run()
1606        reprec.assertoutcome(passed=2, skipped=1)
1607
1608    def test_xfail_with_kwarg(self, testdir):
1609        s = """
1610            import pytest
1611
1612            @pytest.mark.parametrize(("n", "expected"), [
1613                (1, 2),
1614                pytest.mark.xfail(reason="some bug")((1, 3)),
1615                (2, 3),
1616            ])
1617            def test_increment(n, expected):
1618                assert n + 1 == expected
1619        """
1620        testdir.makepyfile(s)
1621        reprec = testdir.inline_run()
1622        reprec.assertoutcome(passed=2, skipped=1)
1623
1624    def test_xfail_with_arg_and_kwarg(self, testdir):
1625        s = """
1626            import pytest
1627
1628            @pytest.mark.parametrize(("n", "expected"), [
1629                (1, 2),
1630                pytest.mark.xfail("True", reason="some bug")((1, 3)),
1631                (2, 3),
1632            ])
1633            def test_increment(n, expected):
1634                assert n + 1 == expected
1635        """
1636        testdir.makepyfile(s)
1637        reprec = testdir.inline_run()
1638        reprec.assertoutcome(passed=2, skipped=1)
1639
1640    @pytest.mark.parametrize("strict", [True, False])
1641    def test_xfail_passing_is_xpass(self, testdir, strict):
1642        s = """
1643            import pytest
1644
1645            @pytest.mark.parametrize(("n", "expected"), [
1646                (1, 2),
1647                pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})((2, 3)),
1648                (3, 4),
1649            ])
1650            def test_increment(n, expected):
1651                assert n + 1 == expected
1652        """.format(
1653            strict=strict
1654        )
1655        testdir.makepyfile(s)
1656        reprec = testdir.inline_run()
1657        passed, failed = (2, 1) if strict else (3, 0)
1658        reprec.assertoutcome(passed=passed, failed=failed)
1659
1660    def test_parametrize_called_in_generate_tests(self, testdir):
1661        s = """
1662            import pytest
1663
1664
1665            def pytest_generate_tests(metafunc):
1666                passingTestData = [(1, 2),
1667                                   (2, 3)]
1668                failingTestData = [(1, 3),
1669                                   (2, 2)]
1670
1671                testData = passingTestData + [pytest.mark.xfail(d)
1672                                  for d in failingTestData]
1673                metafunc.parametrize(("n", "expected"), testData)
1674
1675
1676            def test_increment(n, expected):
1677                assert n + 1 == expected
1678        """
1679        testdir.makepyfile(s)
1680        reprec = testdir.inline_run()
1681        reprec.assertoutcome(passed=2, skipped=2)
1682
1683    @pytest.mark.issue290
1684    def test_parametrize_ID_generation_string_int_works(self, testdir):
1685        testdir.makepyfile(
1686            """
1687            import pytest
1688
1689            @pytest.fixture
1690            def myfixture():
1691                return 'example'
1692            @pytest.mark.parametrize(
1693                'limit', (0, '0'))
1694            def test_limit(limit, myfixture):
1695                return
1696        """
1697        )
1698        reprec = testdir.inline_run()
1699        reprec.assertoutcome(passed=2)
1700
1701    @pytest.mark.parametrize("strict", [True, False])
1702    def test_parametrize_marked_value(self, testdir, strict):
1703        s = """
1704            import pytest
1705
1706            @pytest.mark.parametrize(("n", "expected"), [
1707                pytest.param(
1708                    2,3,
1709                    marks=pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict}),
1710                ),
1711                pytest.param(
1712                    2,3,
1713                    marks=[pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})],
1714                ),
1715            ])
1716            def test_increment(n, expected):
1717                assert n + 1 == expected
1718        """.format(
1719            strict=strict
1720        )
1721        testdir.makepyfile(s)
1722        reprec = testdir.inline_run()
1723        passed, failed = (0, 2) if strict else (2, 0)
1724        reprec.assertoutcome(passed=passed, failed=failed)
1725
1726    def test_pytest_make_parametrize_id(self, testdir):
1727        testdir.makeconftest(
1728            """
1729            def pytest_make_parametrize_id(config, val):
1730                return str(val * 2)
1731        """
1732        )
1733        testdir.makepyfile(
1734            """
1735                import pytest
1736
1737                @pytest.mark.parametrize("x", range(2))
1738                def test_func(x):
1739                    pass
1740                """
1741        )
1742        result = testdir.runpytest("-v")
1743        result.stdout.fnmatch_lines(["*test_func*0*PASS*", "*test_func*2*PASS*"])
1744
1745    def test_pytest_make_parametrize_id_with_argname(self, testdir):
1746        testdir.makeconftest(
1747            """
1748            def pytest_make_parametrize_id(config, val, argname):
1749                return str(val * 2 if argname == 'x' else val * 10)
1750        """
1751        )
1752        testdir.makepyfile(
1753            """
1754                import pytest
1755
1756                @pytest.mark.parametrize("x", range(2))
1757                def test_func_a(x):
1758                    pass
1759
1760                @pytest.mark.parametrize("y", [1])
1761                def test_func_b(y):
1762                    pass
1763                """
1764        )
1765        result = testdir.runpytest("-v")
1766        result.stdout.fnmatch_lines(
1767            ["*test_func_a*0*PASS*", "*test_func_a*2*PASS*", "*test_func_b*10*PASS*"]
1768        )
1769