530 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			530 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Python
		
	
	
	
import pytest
 | 
						|
from _pytest.pytester import Pytester
 | 
						|
 | 
						|
 | 
						|
def setup_module(mod):
 | 
						|
    mod.nose = pytest.importorskip("nose")
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup(pytester: Pytester) -> None:
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        values = []
 | 
						|
        from nose.tools import with_setup
 | 
						|
 | 
						|
        @with_setup(lambda: values.append(1), lambda: values.append(2))
 | 
						|
        def test_hello():
 | 
						|
            assert values == [1]
 | 
						|
 | 
						|
        def test_world():
 | 
						|
            assert values == [1,2]
 | 
						|
 | 
						|
        test_hello.setup = lambda: values.append(1)
 | 
						|
        test_hello.teardown = lambda: values.append(2)
 | 
						|
    """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(
 | 
						|
        p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning"
 | 
						|
    )
 | 
						|
    result.assert_outcomes(passed=2)
 | 
						|
 | 
						|
 | 
						|
def test_setup_func_with_setup_decorator() -> None:
 | 
						|
    from _pytest.nose import call_optional
 | 
						|
 | 
						|
    values = []
 | 
						|
 | 
						|
    class A:
 | 
						|
        @pytest.fixture(autouse=True)
 | 
						|
        def f(self):
 | 
						|
            values.append(1)
 | 
						|
 | 
						|
    call_optional(A(), "f", "A.f")
 | 
						|
    assert not values
 | 
						|
 | 
						|
 | 
						|
def test_setup_func_not_callable() -> None:
 | 
						|
    from _pytest.nose import call_optional
 | 
						|
 | 
						|
    class A:
 | 
						|
        f = 1
 | 
						|
 | 
						|
    call_optional(A(), "f", "A.f")
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup_func(pytester: Pytester) -> None:
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        from nose.tools import with_setup
 | 
						|
 | 
						|
        values = []
 | 
						|
 | 
						|
        def my_setup():
 | 
						|
            a = 1
 | 
						|
            values.append(a)
 | 
						|
 | 
						|
        def my_teardown():
 | 
						|
            b = 2
 | 
						|
            values.append(b)
 | 
						|
 | 
						|
        @with_setup(my_setup, my_teardown)
 | 
						|
        def test_hello():
 | 
						|
            print(values)
 | 
						|
            assert values == [1]
 | 
						|
 | 
						|
        def test_world():
 | 
						|
            print(values)
 | 
						|
            assert values == [1,2]
 | 
						|
 | 
						|
    """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(
 | 
						|
        p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning"
 | 
						|
    )
 | 
						|
    result.assert_outcomes(passed=2)
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup_func_failure(pytester: Pytester) -> None:
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        from nose.tools import with_setup
 | 
						|
 | 
						|
        values = []
 | 
						|
        my_setup = lambda x: 1
 | 
						|
        my_teardown = lambda x: 2
 | 
						|
 | 
						|
        @with_setup(my_setup, my_teardown)
 | 
						|
        def test_hello():
 | 
						|
            print(values)
 | 
						|
            assert values == [1]
 | 
						|
 | 
						|
        def test_world():
 | 
						|
            print(values)
 | 
						|
            assert values == [1,2]
 | 
						|
 | 
						|
    """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(
 | 
						|
        p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning"
 | 
						|
    )
 | 
						|
    result.stdout.fnmatch_lines(["*TypeError: <lambda>()*"])
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup_func_failure_2(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        values = []
 | 
						|
 | 
						|
        my_setup = 1
 | 
						|
        my_teardown = 2
 | 
						|
 | 
						|
        def test_hello():
 | 
						|
            assert values == []
 | 
						|
 | 
						|
        test_hello.setup = my_setup
 | 
						|
        test_hello.teardown = my_teardown
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec = pytester.inline_run()
 | 
						|
    reprec.assertoutcome(passed=1)
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup_partial(pytester: Pytester) -> None:
 | 
						|
    pytest.importorskip("functools")
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        from functools import partial
 | 
						|
 | 
						|
        values = []
 | 
						|
 | 
						|
        def my_setup(x):
 | 
						|
            a = x
 | 
						|
            values.append(a)
 | 
						|
 | 
						|
        def my_teardown(x):
 | 
						|
            b = x
 | 
						|
            values.append(b)
 | 
						|
 | 
						|
        my_setup_partial = partial(my_setup, 1)
 | 
						|
        my_teardown_partial = partial(my_teardown, 2)
 | 
						|
 | 
						|
        def test_hello():
 | 
						|
            print(values)
 | 
						|
            assert values == [1]
 | 
						|
 | 
						|
        def test_world():
 | 
						|
            print(values)
 | 
						|
            assert values == [1,2]
 | 
						|
 | 
						|
        test_hello.setup = my_setup_partial
 | 
						|
        test_hello.teardown = my_teardown_partial
 | 
						|
    """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(
 | 
						|
        p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning"
 | 
						|
    )
 | 
						|
    result.stdout.fnmatch_lines(["*2 passed*"])
 | 
						|
 | 
						|
 | 
						|
def test_module_level_setup(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        from nose.tools import with_setup
 | 
						|
        items = {}
 | 
						|
 | 
						|
        def setup():
 | 
						|
            items.setdefault("setup", []).append("up")
 | 
						|
 | 
						|
        def teardown():
 | 
						|
            items.setdefault("setup", []).append("down")
 | 
						|
 | 
						|
        def setup2():
 | 
						|
            items.setdefault("setup2", []).append("up")
 | 
						|
 | 
						|
        def teardown2():
 | 
						|
            items.setdefault("setup2", []).append("down")
 | 
						|
 | 
						|
        def test_setup_module_setup():
 | 
						|
            assert items["setup"] == ["up"]
 | 
						|
 | 
						|
        def test_setup_module_setup_again():
 | 
						|
            assert items["setup"] == ["up"]
 | 
						|
 | 
						|
        @with_setup(setup2, teardown2)
 | 
						|
        def test_local_setup():
 | 
						|
            assert items["setup"] == ["up"]
 | 
						|
            assert items["setup2"] == ["up"]
 | 
						|
 | 
						|
        @with_setup(setup2, teardown2)
 | 
						|
        def test_local_setup_again():
 | 
						|
            assert items["setup"] == ["up"]
 | 
						|
            assert items["setup2"] == ["up", "down", "up"]
 | 
						|
    """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(
 | 
						|
        "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning"
 | 
						|
    )
 | 
						|
    result.stdout.fnmatch_lines(["*4 passed*"])
 | 
						|
 | 
						|
 | 
						|
def test_nose_style_setup_teardown(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        values = []
 | 
						|
 | 
						|
        def setup_module():
 | 
						|
            values.append(1)
 | 
						|
 | 
						|
        def teardown_module():
 | 
						|
            del values[0]
 | 
						|
 | 
						|
        def test_hello():
 | 
						|
            assert values == [1]
 | 
						|
 | 
						|
        def test_world():
 | 
						|
            assert values == [1]
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest("-p", "nose")
 | 
						|
    result.stdout.fnmatch_lines(["*2 passed*"])
 | 
						|
 | 
						|
 | 
						|
def test_fixtures_nose_setup_issue8394(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        def setup_module():
 | 
						|
            pass
 | 
						|
 | 
						|
        def teardown_module():
 | 
						|
            pass
 | 
						|
 | 
						|
        def setup_function(func):
 | 
						|
            pass
 | 
						|
 | 
						|
        def teardown_function(func):
 | 
						|
            pass
 | 
						|
 | 
						|
        def test_world():
 | 
						|
            pass
 | 
						|
 | 
						|
        class Test(object):
 | 
						|
            def setup_class(cls):
 | 
						|
                pass
 | 
						|
 | 
						|
            def teardown_class(cls):
 | 
						|
                pass
 | 
						|
 | 
						|
            def setup_method(self, meth):
 | 
						|
                pass
 | 
						|
 | 
						|
            def teardown_method(self, meth):
 | 
						|
                pass
 | 
						|
 | 
						|
            def test_method(self): pass
 | 
						|
        """
 | 
						|
    )
 | 
						|
    match = "*no docstring available*"
 | 
						|
    result = pytester.runpytest("--fixtures")
 | 
						|
    assert result.ret == 0
 | 
						|
    result.stdout.no_fnmatch_line(match)
 | 
						|
 | 
						|
    result = pytester.runpytest("--fixtures", "-v")
 | 
						|
    assert result.ret == 0
 | 
						|
    result.stdout.fnmatch_lines([match, match, match, match])
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup_ordering(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        def setup_module(mod):
 | 
						|
            mod.visited = True
 | 
						|
 | 
						|
        class TestClass(object):
 | 
						|
            def setup(self):
 | 
						|
                assert visited
 | 
						|
                self.visited_cls = True
 | 
						|
            def test_first(self):
 | 
						|
                assert visited
 | 
						|
                assert self.visited_cls
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest("-Wignore::pytest.PytestRemovedIn8Warning")
 | 
						|
    result.stdout.fnmatch_lines(["*1 passed*"])
 | 
						|
 | 
						|
 | 
						|
def test_apiwrapper_problem_issue260(pytester: Pytester) -> None:
 | 
						|
    # this would end up trying a call an optional teardown on the class
 | 
						|
    # for plain unittests we don't want nose behaviour
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import unittest
 | 
						|
        class TestCase(unittest.TestCase):
 | 
						|
            def setup(self):
 | 
						|
                #should not be called in unittest testcases
 | 
						|
                assert 0, 'setup'
 | 
						|
            def teardown(self):
 | 
						|
                #should not be called in unittest testcases
 | 
						|
                assert 0, 'teardown'
 | 
						|
            def setUp(self):
 | 
						|
                print('setup')
 | 
						|
            def tearDown(self):
 | 
						|
                print('teardown')
 | 
						|
            def test_fun(self):
 | 
						|
                pass
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest()
 | 
						|
    result.assert_outcomes(passed=1)
 | 
						|
 | 
						|
 | 
						|
def test_setup_teardown_linking_issue265(pytester: Pytester) -> None:
 | 
						|
    # we accidentally didn't integrate nose setupstate with normal setupstate
 | 
						|
    # this test ensures that won't happen again
 | 
						|
    pytester.makepyfile(
 | 
						|
        '''
 | 
						|
        import pytest
 | 
						|
 | 
						|
        class TestGeneric(object):
 | 
						|
            def test_nothing(self):
 | 
						|
                """Tests the API of the implementation (for generic and specialized)."""
 | 
						|
 | 
						|
        @pytest.mark.skipif("True", reason=
 | 
						|
                    "Skip tests to check if teardown is skipped as well.")
 | 
						|
        class TestSkipTeardown(TestGeneric):
 | 
						|
 | 
						|
            def setup(self):
 | 
						|
                """Sets up my specialized implementation for $COOL_PLATFORM."""
 | 
						|
                raise Exception("should not call setup for skipped tests")
 | 
						|
 | 
						|
            def teardown(self):
 | 
						|
                """Undoes the setup."""
 | 
						|
                raise Exception("should not call teardown for skipped tests")
 | 
						|
        '''
 | 
						|
    )
 | 
						|
    reprec = pytester.runpytest()
 | 
						|
    reprec.assert_outcomes(passed=1, skipped=1)
 | 
						|
 | 
						|
 | 
						|
def test_SkipTest_during_collection(pytester: Pytester) -> None:
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import nose
 | 
						|
        raise nose.SkipTest("during collection")
 | 
						|
        def test_failing():
 | 
						|
            assert False
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(p)
 | 
						|
    result.assert_outcomes(skipped=1, warnings=0)
 | 
						|
 | 
						|
 | 
						|
def test_SkipTest_in_test(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import nose
 | 
						|
 | 
						|
        def test_skipping():
 | 
						|
            raise nose.SkipTest("in test")
 | 
						|
        """
 | 
						|
    )
 | 
						|
    reprec = pytester.inline_run()
 | 
						|
    reprec.assertoutcome(skipped=1)
 | 
						|
 | 
						|
 | 
						|
def test_istest_function_decorator(pytester: Pytester) -> None:
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import nose.tools
 | 
						|
        @nose.tools.istest
 | 
						|
        def not_test_prefix():
 | 
						|
            pass
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(p)
 | 
						|
    result.assert_outcomes(passed=1)
 | 
						|
 | 
						|
 | 
						|
def test_nottest_function_decorator(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import nose.tools
 | 
						|
        @nose.tools.nottest
 | 
						|
        def test_prefix():
 | 
						|
            pass
 | 
						|
        """
 | 
						|
    )
 | 
						|
    reprec = pytester.inline_run()
 | 
						|
    assert not reprec.getfailedcollections()
 | 
						|
    calls = reprec.getreports("pytest_runtest_logreport")
 | 
						|
    assert not calls
 | 
						|
 | 
						|
 | 
						|
def test_istest_class_decorator(pytester: Pytester) -> None:
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import nose.tools
 | 
						|
        @nose.tools.istest
 | 
						|
        class NotTestPrefix(object):
 | 
						|
            def test_method(self):
 | 
						|
                pass
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(p)
 | 
						|
    result.assert_outcomes(passed=1)
 | 
						|
 | 
						|
 | 
						|
def test_nottest_class_decorator(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        import nose.tools
 | 
						|
        @nose.tools.nottest
 | 
						|
        class TestPrefix(object):
 | 
						|
            def test_method(self):
 | 
						|
                pass
 | 
						|
        """
 | 
						|
    )
 | 
						|
    reprec = pytester.inline_run()
 | 
						|
    assert not reprec.getfailedcollections()
 | 
						|
    calls = reprec.getreports("pytest_runtest_logreport")
 | 
						|
    assert not calls
 | 
						|
 | 
						|
 | 
						|
def test_skip_test_with_unicode(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """\
 | 
						|
        import unittest
 | 
						|
        class TestClass():
 | 
						|
            def test_io(self):
 | 
						|
                raise unittest.SkipTest('😊')
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest()
 | 
						|
    result.stdout.fnmatch_lines(["* 1 skipped *"])
 | 
						|
 | 
						|
 | 
						|
def test_raises(pytester: Pytester) -> None:
 | 
						|
    pytester.makepyfile(
 | 
						|
        """
 | 
						|
        from nose.tools import raises
 | 
						|
 | 
						|
        @raises(RuntimeError)
 | 
						|
        def test_raises_runtimeerror():
 | 
						|
            raise RuntimeError
 | 
						|
 | 
						|
        @raises(Exception)
 | 
						|
        def test_raises_baseexception_not_caught():
 | 
						|
            raise BaseException
 | 
						|
 | 
						|
        @raises(BaseException)
 | 
						|
        def test_raises_baseexception_caught():
 | 
						|
            raise BaseException
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest("-vv")
 | 
						|
    result.stdout.fnmatch_lines(
 | 
						|
        [
 | 
						|
            "test_raises.py::test_raises_runtimeerror PASSED*",
 | 
						|
            "test_raises.py::test_raises_baseexception_not_caught FAILED*",
 | 
						|
            "test_raises.py::test_raises_baseexception_caught PASSED*",
 | 
						|
            "*= FAILURES =*",
 | 
						|
            "*_ test_raises_baseexception_not_caught _*",
 | 
						|
            "",
 | 
						|
            "arg = (), kw = {}",
 | 
						|
            "",
 | 
						|
            "    def newfunc(*arg, **kw):",
 | 
						|
            "        try:",
 | 
						|
            ">           func(*arg, **kw)",
 | 
						|
            "",
 | 
						|
            "*/nose/*: ",
 | 
						|
            "_ _ *",
 | 
						|
            "",
 | 
						|
            "    @raises(Exception)",
 | 
						|
            "    def test_raises_baseexception_not_caught():",
 | 
						|
            ">       raise BaseException",
 | 
						|
            "E       BaseException",
 | 
						|
            "",
 | 
						|
            "test_raises.py:9: BaseException",
 | 
						|
            "* 1 failed, 2 passed *",
 | 
						|
        ]
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def test_nose_setup_skipped_if_non_callable(pytester: Pytester) -> None:
 | 
						|
    """Regression test for #9391."""
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        __init__="",
 | 
						|
        setup="""
 | 
						|
        """,
 | 
						|
        teardown="""
 | 
						|
        """,
 | 
						|
        test_it="""
 | 
						|
        from . import setup, teardown
 | 
						|
 | 
						|
        def test_it():
 | 
						|
            pass
 | 
						|
        """,
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(p.parent, "-p", "nose")
 | 
						|
    assert result.ret == 0
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("fixture_name", ("teardown", "teardown_class"))
 | 
						|
def test_teardown_fixture_not_called_directly(fixture_name, pytester: Pytester) -> None:
 | 
						|
    """Regression test for #10597."""
 | 
						|
    p = pytester.makepyfile(
 | 
						|
        f"""
 | 
						|
        import pytest
 | 
						|
 | 
						|
        class TestHello:
 | 
						|
 | 
						|
            @pytest.fixture
 | 
						|
            def {fixture_name}(self):
 | 
						|
                yield
 | 
						|
 | 
						|
            def test_hello(self, {fixture_name}):
 | 
						|
                assert True
 | 
						|
        """
 | 
						|
    )
 | 
						|
    result = pytester.runpytest(p, "-p", "nose")
 | 
						|
    assert result.ret == 0
 |