from typing import Any import pytest from _pytest import python from _pytest import runner class TestOEJSKITSpecials: def test_funcarg_non_pycollectobj( self, testdir, recwarn ) -> None: # rough jstests usage testdir.makeconftest( """ import pytest def pytest_pycollect_makeitem(collector, name, obj): if name == "MyClass": return MyCollector.from_parent(collector, name=name) class MyCollector(pytest.Collector): def reportinfo(self): return self.fspath, 3, "xyz" """ ) modcol = testdir.getmodulecol( """ import pytest @pytest.fixture def arg1(request): return 42 class MyClass(object): pass """ ) # this hook finds funcarg factories rep = runner.collect_one_node(collector=modcol) # TODO: Don't treat as Any. clscol = rep.result[0] # type: Any clscol.obj = lambda arg1: None clscol.funcargs = {} pytest._fillfuncargs(clscol) assert clscol.funcargs["arg1"] == 42 def test_autouse_fixture(self, testdir, recwarn) -> None: # rough jstests usage testdir.makeconftest( """ import pytest def pytest_pycollect_makeitem(collector, name, obj): if name == "MyClass": return MyCollector.from_parent(collector, name=name) class MyCollector(pytest.Collector): def reportinfo(self): return self.fspath, 3, "xyz" """ ) modcol = testdir.getmodulecol( """ import pytest @pytest.fixture(autouse=True) def hello(): pass @pytest.fixture def arg1(request): return 42 class MyClass(object): pass """ ) # this hook finds funcarg factories rep = runner.collect_one_node(modcol) # TODO: Don't treat as Any. clscol = rep.result[0] # type: Any clscol.obj = lambda: None clscol.funcargs = {} pytest._fillfuncargs(clscol) assert not clscol.funcargs def test_wrapped_getfslineno() -> None: def func(): pass def wrap(f): func.__wrapped__ = f # type: ignore func.patchings = ["qwe"] # type: ignore return func @wrap def wrapped_func(x, y, z): pass fs, lineno = python.getfslineno(wrapped_func) fs2, lineno2 = python.getfslineno(wrap) assert lineno > lineno2, "getfslineno does not unwrap correctly" class TestMockDecoration: def test_wrapped_getfuncargnames(self) -> None: from _pytest.compat import getfuncargnames def wrap(f): def func(): pass func.__wrapped__ = f # type: ignore return func @wrap def f(x): pass values = getfuncargnames(f) assert values == ("x",) def test_getfuncargnames_patching(self): from _pytest.compat import getfuncargnames from unittest.mock import patch class T: def original(self, x, y, z): pass @patch.object(T, "original") def f(x, y, z): pass values = getfuncargnames(f) assert values == ("y", "z") def test_unittest_mock(self, testdir): testdir.makepyfile( """ import unittest.mock class T(unittest.TestCase): @unittest.mock.patch("os.path.abspath") def test_hello(self, abspath): import os os.path.abspath("hello") abspath.assert_any_call("hello") """ ) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) def test_unittest_mock_and_fixture(self, testdir): testdir.makepyfile( """ import os.path import unittest.mock import pytest @pytest.fixture def inject_me(): pass @unittest.mock.patch.object(os.path, "abspath", new=unittest.mock.MagicMock) def test_hello(inject_me): import os os.path.abspath("hello") """ ) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) def test_unittest_mock_and_pypi_mock(self, testdir): pytest.importorskip("mock", "1.0.1") testdir.makepyfile( """ import mock import unittest.mock class TestBoth(object): @unittest.mock.patch("os.path.abspath") def test_hello(self, abspath): import os os.path.abspath("hello") abspath.assert_any_call("hello") @mock.patch("os.path.abspath") def test_hello_mock(self, abspath): import os os.path.abspath("hello") abspath.assert_any_call("hello") """ ) reprec = testdir.inline_run() reprec.assertoutcome(passed=2) def test_mock_sentinel_check_against_numpy_like(self, testdir): """Ensure our function that detects mock arguments compares against sentinels using identity to circumvent objects which can't be compared with equality against others in a truth context, like with numpy arrays (#5606). """ testdir.makepyfile( dummy=""" class NumpyLike: def __init__(self, value): self.value = value def __eq__(self, other): raise ValueError("like numpy, cannot compare against others for truth") FOO = NumpyLike(10) """ ) testdir.makepyfile( """ from unittest.mock import patch import dummy class Test(object): @patch("dummy.FOO", new=dummy.NumpyLike(50)) def test_hello(self): assert dummy.FOO.value == 50 """ ) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) def test_mock(self, testdir): pytest.importorskip("mock", "1.0.1") testdir.makepyfile( """ import os import unittest import mock class T(unittest.TestCase): @mock.patch("os.path.abspath") def test_hello(self, abspath): os.path.abspath("hello") abspath.assert_any_call("hello") def mock_basename(path): return "mock_basename" @mock.patch("os.path.abspath") @mock.patch("os.path.normpath") @mock.patch("os.path.basename", new=mock_basename) def test_someting(normpath, abspath, tmpdir): abspath.return_value = "this" os.path.normpath(os.path.abspath("hello")) normpath.assert_any_call("this") assert os.path.basename("123") == "mock_basename" """ ) reprec = testdir.inline_run() reprec.assertoutcome(passed=2) calls = reprec.getcalls("pytest_runtest_logreport") funcnames = [ call.report.location[2] for call in calls if call.report.when == "call" ] assert funcnames == ["T.test_hello", "test_someting"] def test_mock_sorting(self, testdir): pytest.importorskip("mock", "1.0.1") testdir.makepyfile( """ import os import mock @mock.patch("os.path.abspath") def test_one(abspath): pass @mock.patch("os.path.abspath") def test_two(abspath): pass @mock.patch("os.path.abspath") def test_three(abspath): pass """ ) reprec = testdir.inline_run() calls = reprec.getreports("pytest_runtest_logreport") calls = [x for x in calls if x.when == "call"] names = [x.nodeid.split("::")[-1] for x in calls] assert names == ["test_one", "test_two", "test_three"] def test_mock_double_patch_issue473(self, testdir): pytest.importorskip("mock", "1.0.1") testdir.makepyfile( """ from mock import patch from pytest import mark @patch('os.getcwd') @patch('os.path') @mark.slow class TestSimple(object): def test_simple_thing(self, mock_path, mock_getcwd): pass """ ) reprec = testdir.inline_run() reprec.assertoutcome(passed=1) class TestReRunTests: def test_rerun(self, testdir): testdir.makeconftest( """ from _pytest.runner import runtestprotocol def pytest_runtest_protocol(item, nextitem): runtestprotocol(item, log=False, nextitem=nextitem) runtestprotocol(item, log=True, nextitem=nextitem) """ ) testdir.makepyfile( """ import pytest count = 0 req = None @pytest.fixture def fix(request): global count, req assert request != req req = request print("fix count %s" % count) count += 1 def test_fix(fix): pass """ ) result = testdir.runpytest("-s") result.stdout.fnmatch_lines( """ *fix count 0* *fix count 1* """ ) result.stdout.fnmatch_lines( """ *2 passed* """ ) def test_pytestconfig_is_session_scoped() -> None: from _pytest.fixtures import pytestconfig marker = pytestconfig._pytestfixturefunction # type: ignore assert marker.scope == "session" class TestNoselikeTestAttribute: def test_module_with_global_test(self, testdir): testdir.makepyfile( """ __test__ = False def test_hello(): pass """ ) reprec = testdir.inline_run() assert not reprec.getfailedcollections() calls = reprec.getreports("pytest_runtest_logreport") assert not calls def test_class_and_method(self, testdir): testdir.makepyfile( """ __test__ = True def test_func(): pass test_func.__test__ = False class TestSome(object): __test__ = False def test_method(self): pass """ ) reprec = testdir.inline_run() assert not reprec.getfailedcollections() calls = reprec.getreports("pytest_runtest_logreport") assert not calls def test_unittest_class(self, testdir): testdir.makepyfile( """ import unittest class TC(unittest.TestCase): def test_1(self): pass class TC2(unittest.TestCase): __test__ = False def test_2(self): pass """ ) reprec = testdir.inline_run() assert not reprec.getfailedcollections() call = reprec.getcalls("pytest_collection_modifyitems")[0] assert len(call.items) == 1 assert call.items[0].cls.__name__ == "TC" def test_class_with_nasty_getattr(self, testdir): """Make sure we handle classes with a custom nasty __getattr__ right. With a custom __getattr__ which e.g. returns a function (like with a RPC wrapper), we shouldn't assume this meant "__test__ = True". """ # https://github.com/pytest-dev/pytest/issues/1204 testdir.makepyfile( """ class MetaModel(type): def __getattr__(cls, key): return lambda: None BaseModel = MetaModel('Model', (), {}) class Model(BaseModel): __metaclass__ = MetaModel def test_blah(self): pass """ ) reprec = testdir.inline_run() assert not reprec.getfailedcollections() call = reprec.getcalls("pytest_collection_modifyitems")[0] assert not call.items class TestParameterize: """#351""" def test_idfn_marker(self, testdir): testdir.makepyfile( """ import pytest def idfn(param): if param == 0: return 'spam' elif param == 1: return 'ham' else: return None @pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn) def test_params(a, b): pass """ ) res = testdir.runpytest("--collect-only") res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"]) def test_idfn_fixture(self, testdir): testdir.makepyfile( """ import pytest def idfn(param): if param == 0: return 'spam' elif param == 1: return 'ham' else: return None @pytest.fixture(params=[0, 1], ids=idfn) def a(request): return request.param @pytest.fixture(params=[1, 2], ids=idfn) def b(request): return request.param def test_params(a, b): pass """ ) res = testdir.runpytest("--collect-only") res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"])