1import pytest
2from _pytest import python
3from _pytest import runner
4
5
6class TestOEJSKITSpecials(object):
7
8    def test_funcarg_non_pycollectobj(self, testdir):  # rough jstests usage
9        testdir.makeconftest(
10            """
11            import pytest
12            def pytest_pycollect_makeitem(collector, name, obj):
13                if name == "MyClass":
14                    return MyCollector(name, parent=collector)
15            class MyCollector(pytest.Collector):
16                def reportinfo(self):
17                    return self.fspath, 3, "xyz"
18        """
19        )
20        modcol = testdir.getmodulecol(
21            """
22            import pytest
23            @pytest.fixture
24            def arg1(request):
25                return 42
26            class MyClass(object):
27                pass
28        """
29        )
30        # this hook finds funcarg factories
31        rep = runner.collect_one_node(collector=modcol)
32        clscol = rep.result[0]
33        clscol.obj = lambda arg1: None
34        clscol.funcargs = {}
35        pytest._fillfuncargs(clscol)
36        assert clscol.funcargs["arg1"] == 42
37
38    def test_autouse_fixture(self, testdir):  # rough jstests usage
39        testdir.makeconftest(
40            """
41            import pytest
42            def pytest_pycollect_makeitem(collector, name, obj):
43                if name == "MyClass":
44                    return MyCollector(name, parent=collector)
45            class MyCollector(pytest.Collector):
46                def reportinfo(self):
47                    return self.fspath, 3, "xyz"
48        """
49        )
50        modcol = testdir.getmodulecol(
51            """
52            import pytest
53            @pytest.fixture(autouse=True)
54            def hello():
55                pass
56            @pytest.fixture
57            def arg1(request):
58                return 42
59            class MyClass(object):
60                pass
61        """
62        )
63        # this hook finds funcarg factories
64        rep = runner.collect_one_node(modcol)
65        clscol = rep.result[0]
66        clscol.obj = lambda: None
67        clscol.funcargs = {}
68        pytest._fillfuncargs(clscol)
69        assert not clscol.funcargs
70
71
72def test_wrapped_getfslineno():
73
74    def func():
75        pass
76
77    def wrap(f):
78        func.__wrapped__ = f
79        func.patchings = ["qwe"]
80        return func
81
82    @wrap
83    def wrapped_func(x, y, z):
84        pass
85
86    fs, lineno = python.getfslineno(wrapped_func)
87    fs2, lineno2 = python.getfslineno(wrap)
88    assert lineno > lineno2, "getfslineno does not unwrap correctly"
89
90
91class TestMockDecoration(object):
92
93    def test_wrapped_getfuncargnames(self):
94        from _pytest.compat import getfuncargnames
95
96        def wrap(f):
97
98            def func():
99                pass
100
101            func.__wrapped__ = f
102            return func
103
104        @wrap
105        def f(x):
106            pass
107
108        values = getfuncargnames(f)
109        assert values == ("x",)
110
111    @pytest.mark.xfail(
112        strict=False, reason="getfuncargnames breaks if mock is imported"
113    )
114    def test_wrapped_getfuncargnames_patching(self):
115        from _pytest.compat import getfuncargnames
116
117        def wrap(f):
118
119            def func():
120                pass
121
122            func.__wrapped__ = f
123            func.patchings = ["qwe"]
124            return func
125
126        @wrap
127        def f(x, y, z):
128            pass
129
130        values = getfuncargnames(f)
131        assert values == ("y", "z")
132
133    def test_unittest_mock(self, testdir):
134        pytest.importorskip("unittest.mock")
135        testdir.makepyfile(
136            """
137            import unittest.mock
138            class T(unittest.TestCase):
139                @unittest.mock.patch("os.path.abspath")
140                def test_hello(self, abspath):
141                    import os
142                    os.path.abspath("hello")
143                    abspath.assert_any_call("hello")
144        """
145        )
146        reprec = testdir.inline_run()
147        reprec.assertoutcome(passed=1)
148
149    def test_unittest_mock_and_fixture(self, testdir):
150        pytest.importorskip("unittest.mock")
151        testdir.makepyfile(
152            """
153            import os.path
154            import unittest.mock
155            import pytest
156
157            @pytest.fixture
158            def inject_me():
159                pass
160
161            @unittest.mock.patch.object(os.path, "abspath",
162                                        new=unittest.mock.MagicMock)
163            def test_hello(inject_me):
164                import os
165                os.path.abspath("hello")
166        """
167        )
168        reprec = testdir.inline_run()
169        reprec.assertoutcome(passed=1)
170
171    def test_unittest_mock_and_pypi_mock(self, testdir):
172        pytest.importorskip("unittest.mock")
173        pytest.importorskip("mock", "1.0.1")
174        testdir.makepyfile(
175            """
176            import mock
177            import unittest.mock
178            class TestBoth(object):
179                @unittest.mock.patch("os.path.abspath")
180                def test_hello(self, abspath):
181                    import os
182                    os.path.abspath("hello")
183                    abspath.assert_any_call("hello")
184
185                @mock.patch("os.path.abspath")
186                def test_hello_mock(self, abspath):
187                    import os
188                    os.path.abspath("hello")
189                    abspath.assert_any_call("hello")
190        """
191        )
192        reprec = testdir.inline_run()
193        reprec.assertoutcome(passed=2)
194
195    def test_mock(self, testdir):
196        pytest.importorskip("mock", "1.0.1")
197        testdir.makepyfile(
198            """
199            import os
200            import unittest
201            import mock
202
203            class T(unittest.TestCase):
204                @mock.patch("os.path.abspath")
205                def test_hello(self, abspath):
206                    os.path.abspath("hello")
207                    abspath.assert_any_call("hello")
208            def mock_basename(path):
209                return "mock_basename"
210            @mock.patch("os.path.abspath")
211            @mock.patch("os.path.normpath")
212            @mock.patch("os.path.basename", new=mock_basename)
213            def test_someting(normpath, abspath, tmpdir):
214                abspath.return_value = "this"
215                os.path.normpath(os.path.abspath("hello"))
216                normpath.assert_any_call("this")
217                assert os.path.basename("123") == "mock_basename"
218        """
219        )
220        reprec = testdir.inline_run()
221        reprec.assertoutcome(passed=2)
222        calls = reprec.getcalls("pytest_runtest_logreport")
223        funcnames = [
224            call.report.location[2] for call in calls if call.report.when == "call"
225        ]
226        assert funcnames == ["T.test_hello", "test_someting"]
227
228    def test_mock_sorting(self, testdir):
229        pytest.importorskip("mock", "1.0.1")
230        testdir.makepyfile(
231            """
232            import os
233            import mock
234
235            @mock.patch("os.path.abspath")
236            def test_one(abspath):
237                pass
238            @mock.patch("os.path.abspath")
239            def test_two(abspath):
240                pass
241            @mock.patch("os.path.abspath")
242            def test_three(abspath):
243                pass
244        """
245        )
246        reprec = testdir.inline_run()
247        calls = reprec.getreports("pytest_runtest_logreport")
248        calls = [x for x in calls if x.when == "call"]
249        names = [x.nodeid.split("::")[-1] for x in calls]
250        assert names == ["test_one", "test_two", "test_three"]
251
252    def test_mock_double_patch_issue473(self, testdir):
253        pytest.importorskip("mock", "1.0.1")
254        testdir.makepyfile(
255            """
256            from mock import patch
257            from pytest import mark
258
259            @patch('os.getcwd')
260            @patch('os.path')
261            @mark.slow
262            class TestSimple(object):
263                def test_simple_thing(self, mock_path, mock_getcwd):
264                    pass
265        """
266        )
267        reprec = testdir.inline_run()
268        reprec.assertoutcome(passed=1)
269
270
271class TestReRunTests(object):
272
273    def test_rerun(self, testdir):
274        testdir.makeconftest(
275            """
276            from _pytest.runner import runtestprotocol
277            def pytest_runtest_protocol(item, nextitem):
278                runtestprotocol(item, log=False, nextitem=nextitem)
279                runtestprotocol(item, log=True, nextitem=nextitem)
280        """
281        )
282        testdir.makepyfile(
283            """
284            import pytest
285            count = 0
286            req = None
287            @pytest.fixture
288            def fix(request):
289                global count, req
290                assert request != req
291                req = request
292                print ("fix count %s" % count)
293                count += 1
294            def test_fix(fix):
295                pass
296        """
297        )
298        result = testdir.runpytest("-s")
299        result.stdout.fnmatch_lines(
300            """
301            *fix count 0*
302            *fix count 1*
303        """
304        )
305        result.stdout.fnmatch_lines(
306            """
307            *2 passed*
308        """
309        )
310
311
312def test_pytestconfig_is_session_scoped():
313    from _pytest.fixtures import pytestconfig
314
315    assert pytestconfig._pytestfixturefunction.scope == "session"
316
317
318class TestNoselikeTestAttribute(object):
319
320    def test_module_with_global_test(self, testdir):
321        testdir.makepyfile(
322            """
323            __test__ = False
324            def test_hello():
325                pass
326        """
327        )
328        reprec = testdir.inline_run()
329        assert not reprec.getfailedcollections()
330        calls = reprec.getreports("pytest_runtest_logreport")
331        assert not calls
332
333    def test_class_and_method(self, testdir):
334        testdir.makepyfile(
335            """
336            __test__ = True
337            def test_func():
338                pass
339            test_func.__test__ = False
340
341            class TestSome(object):
342                __test__ = False
343                def test_method(self):
344                    pass
345        """
346        )
347        reprec = testdir.inline_run()
348        assert not reprec.getfailedcollections()
349        calls = reprec.getreports("pytest_runtest_logreport")
350        assert not calls
351
352    def test_unittest_class(self, testdir):
353        testdir.makepyfile(
354            """
355            import unittest
356            class TC(unittest.TestCase):
357                def test_1(self):
358                    pass
359            class TC2(unittest.TestCase):
360                __test__ = False
361                def test_2(self):
362                    pass
363        """
364        )
365        reprec = testdir.inline_run()
366        assert not reprec.getfailedcollections()
367        call = reprec.getcalls("pytest_collection_modifyitems")[0]
368        assert len(call.items) == 1
369        assert call.items[0].cls.__name__ == "TC"
370
371    def test_class_with_nasty_getattr(self, testdir):
372        """Make sure we handle classes with a custom nasty __getattr__ right.
373
374        With a custom __getattr__ which e.g. returns a function (like with a
375        RPC wrapper), we shouldn't assume this meant "__test__ = True".
376        """
377        # https://github.com/pytest-dev/pytest/issues/1204
378        testdir.makepyfile(
379            """
380            class MetaModel(type):
381
382                def __getattr__(cls, key):
383                    return lambda: None
384
385
386            BaseModel = MetaModel('Model', (), {})
387
388
389            class Model(BaseModel):
390
391                __metaclass__ = MetaModel
392
393                def test_blah(self):
394                    pass
395        """
396        )
397        reprec = testdir.inline_run()
398        assert not reprec.getfailedcollections()
399        call = reprec.getcalls("pytest_collection_modifyitems")[0]
400        assert not call.items
401
402
403@pytest.mark.issue351
404class TestParameterize(object):
405
406    def test_idfn_marker(self, testdir):
407        testdir.makepyfile(
408            """
409            import pytest
410
411            def idfn(param):
412                if param == 0:
413                    return 'spam'
414                elif param == 1:
415                    return 'ham'
416                else:
417                    return None
418
419            @pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn)
420            def test_params(a, b):
421                pass
422        """
423        )
424        res = testdir.runpytest("--collect-only")
425        res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"])
426
427    def test_idfn_fixture(self, testdir):
428        testdir.makepyfile(
429            """
430            import pytest
431
432            def idfn(param):
433                if param == 0:
434                    return 'spam'
435                elif param == 1:
436                    return 'ham'
437                else:
438                    return None
439
440            @pytest.fixture(params=[0, 1], ids=idfn)
441            def a(request):
442                return request.param
443
444            @pytest.fixture(params=[1, 2], ids=idfn)
445            def b(request):
446                return request.param
447
448            def test_params(a, b):
449                pass
450        """
451        )
452        res = testdir.runpytest("--collect-only")
453        res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"])
454