353 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Python
		
	
	
	
"""
 | 
						|
 test correct setup/teardowns at
 | 
						|
 module, class, and instance level
 | 
						|
"""
 | 
						|
from __future__ import absolute_import, division, print_function
 | 
						|
import pytest
 | 
						|
 | 
						|
 | 
						|
def test_module_and_function_setup(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        modlevel = []
 | 
						|
        def setup_module(module):
 | 
						|
            assert not modlevel
 | 
						|
            module.modlevel.append(42)
 | 
						|
 | 
						|
        def teardown_module(module):
 | 
						|
            modlevel.pop()
 | 
						|
 | 
						|
        def setup_function(function):
 | 
						|
            function.answer = 17
 | 
						|
 | 
						|
        def teardown_function(function):
 | 
						|
            del function.answer
 | 
						|
 | 
						|
        def test_modlevel():
 | 
						|
            assert modlevel[0] == 42
 | 
						|
            assert test_modlevel.answer == 17
 | 
						|
 | 
						|
        class TestFromClass(object):
 | 
						|
            def test_module(self):
 | 
						|
                assert modlevel[0] == 42
 | 
						|
                assert not hasattr(test_modlevel, 'answer')
 | 
						|
    """
 | 
						|
    )
 | 
						|
    rep = reprec.matchreport("test_modlevel")
 | 
						|
    assert rep.passed
 | 
						|
    rep = reprec.matchreport("test_module")
 | 
						|
    assert rep.passed
 | 
						|
 | 
						|
 | 
						|
def test_module_setup_failure_no_teardown(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        values = []
 | 
						|
        def setup_module(module):
 | 
						|
            values.append(1)
 | 
						|
            0/0
 | 
						|
 | 
						|
        def test_nothing():
 | 
						|
            pass
 | 
						|
 | 
						|
        def teardown_module(module):
 | 
						|
            values.append(2)
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(failed=1)
 | 
						|
    calls = reprec.getcalls("pytest_runtest_setup")
 | 
						|
    assert calls[0].item.module.values == [1]
 | 
						|
 | 
						|
 | 
						|
def test_setup_function_failure_no_teardown(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        modlevel = []
 | 
						|
        def setup_function(function):
 | 
						|
            modlevel.append(1)
 | 
						|
            0/0
 | 
						|
 | 
						|
        def teardown_function(module):
 | 
						|
            modlevel.append(2)
 | 
						|
 | 
						|
        def test_func():
 | 
						|
            pass
 | 
						|
    """
 | 
						|
    )
 | 
						|
    calls = reprec.getcalls("pytest_runtest_setup")
 | 
						|
    assert calls[0].item.module.modlevel == [1]
 | 
						|
 | 
						|
 | 
						|
def test_class_setup(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        class TestSimpleClassSetup(object):
 | 
						|
            clslevel = []
 | 
						|
            def setup_class(cls):
 | 
						|
                cls.clslevel.append(23)
 | 
						|
 | 
						|
            def teardown_class(cls):
 | 
						|
                cls.clslevel.pop()
 | 
						|
 | 
						|
            def test_classlevel(self):
 | 
						|
                assert self.clslevel[0] == 23
 | 
						|
 | 
						|
        class TestInheritedClassSetupStillWorks(TestSimpleClassSetup):
 | 
						|
            def test_classlevel_anothertime(self):
 | 
						|
                assert self.clslevel == [23]
 | 
						|
 | 
						|
        def test_cleanup():
 | 
						|
            assert not TestSimpleClassSetup.clslevel
 | 
						|
            assert not TestInheritedClassSetupStillWorks.clslevel
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(passed=1 + 2 + 1)
 | 
						|
 | 
						|
 | 
						|
def test_class_setup_failure_no_teardown(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        class TestSimpleClassSetup(object):
 | 
						|
            clslevel = []
 | 
						|
            def setup_class(cls):
 | 
						|
                0/0
 | 
						|
 | 
						|
            def teardown_class(cls):
 | 
						|
                cls.clslevel.append(1)
 | 
						|
 | 
						|
            def test_classlevel(self):
 | 
						|
                pass
 | 
						|
 | 
						|
        def test_cleanup():
 | 
						|
            assert not TestSimpleClassSetup.clslevel
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(failed=1, passed=1)
 | 
						|
 | 
						|
 | 
						|
def test_method_setup(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        class TestSetupMethod(object):
 | 
						|
            def setup_method(self, meth):
 | 
						|
                self.methsetup = meth
 | 
						|
            def teardown_method(self, meth):
 | 
						|
                del self.methsetup
 | 
						|
 | 
						|
            def test_some(self):
 | 
						|
                assert self.methsetup == self.test_some
 | 
						|
 | 
						|
            def test_other(self):
 | 
						|
                assert self.methsetup == self.test_other
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(passed=2)
 | 
						|
 | 
						|
 | 
						|
def test_method_setup_failure_no_teardown(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        class TestMethodSetup(object):
 | 
						|
            clslevel = []
 | 
						|
            def setup_method(self, method):
 | 
						|
                self.clslevel.append(1)
 | 
						|
                0/0
 | 
						|
 | 
						|
            def teardown_method(self, method):
 | 
						|
                self.clslevel.append(2)
 | 
						|
 | 
						|
            def test_method(self):
 | 
						|
                pass
 | 
						|
 | 
						|
        def test_cleanup():
 | 
						|
            assert TestMethodSetup.clslevel == [1]
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(failed=1, passed=1)
 | 
						|
 | 
						|
 | 
						|
def test_method_generator_setup(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        class TestSetupTeardownOnInstance(object):
 | 
						|
            def setup_class(cls):
 | 
						|
                cls.classsetup = True
 | 
						|
 | 
						|
            def setup_method(self, method):
 | 
						|
                self.methsetup = method
 | 
						|
 | 
						|
            def test_generate(self):
 | 
						|
                assert self.classsetup
 | 
						|
                assert self.methsetup == self.test_generate
 | 
						|
                yield self.generated, 5
 | 
						|
                yield self.generated, 2
 | 
						|
 | 
						|
            def generated(self, value):
 | 
						|
                assert self.classsetup
 | 
						|
                assert self.methsetup == self.test_generate
 | 
						|
                assert value == 5
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(passed=1, failed=1)
 | 
						|
 | 
						|
 | 
						|
def test_func_generator_setup(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        import sys
 | 
						|
 | 
						|
        def setup_module(mod):
 | 
						|
            print ("setup_module")
 | 
						|
            mod.x = []
 | 
						|
 | 
						|
        def setup_function(fun):
 | 
						|
            print ("setup_function")
 | 
						|
            x.append(1)
 | 
						|
 | 
						|
        def teardown_function(fun):
 | 
						|
            print ("teardown_function")
 | 
						|
            x.pop()
 | 
						|
 | 
						|
        def test_one():
 | 
						|
            assert x == [1]
 | 
						|
            def check():
 | 
						|
                print ("check")
 | 
						|
                sys.stderr.write("e\\n")
 | 
						|
                assert x == [1]
 | 
						|
            yield check
 | 
						|
            assert x == [1]
 | 
						|
    """
 | 
						|
    )
 | 
						|
    rep = reprec.matchreport("test_one", names="pytest_runtest_logreport")
 | 
						|
    assert rep.passed
 | 
						|
 | 
						|
 | 
						|
def test_method_setup_uses_fresh_instances(testdir):
 | 
						|
    reprec = testdir.inline_runsource(
 | 
						|
        """
 | 
						|
        class TestSelfState1(object):
 | 
						|
            memory = []
 | 
						|
            def test_hello(self):
 | 
						|
                self.memory.append(self)
 | 
						|
 | 
						|
            def test_afterhello(self):
 | 
						|
                assert self != self.memory[0]
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec.assertoutcome(passed=2, failed=0)
 | 
						|
 | 
						|
 | 
						|
def test_setup_that_skips_calledagain(testdir):
 | 
						|
    p = testdir.makepyfile(
 | 
						|
        """
 | 
						|
        import pytest
 | 
						|
        def setup_module(mod):
 | 
						|
            pytest.skip("x")
 | 
						|
        def test_function1():
 | 
						|
            pass
 | 
						|
        def test_function2():
 | 
						|
            pass
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec = testdir.inline_run(p)
 | 
						|
    reprec.assertoutcome(skipped=2)
 | 
						|
 | 
						|
 | 
						|
def test_setup_fails_again_on_all_tests(testdir):
 | 
						|
    p = testdir.makepyfile(
 | 
						|
        """
 | 
						|
        import pytest
 | 
						|
        def setup_module(mod):
 | 
						|
            raise ValueError(42)
 | 
						|
        def test_function1():
 | 
						|
            pass
 | 
						|
        def test_function2():
 | 
						|
            pass
 | 
						|
    """
 | 
						|
    )
 | 
						|
    reprec = testdir.inline_run(p)
 | 
						|
    reprec.assertoutcome(failed=2)
 | 
						|
 | 
						|
 | 
						|
def test_setup_funcarg_setup_when_outer_scope_fails(testdir):
 | 
						|
    p = testdir.makepyfile(
 | 
						|
        """
 | 
						|
        import pytest
 | 
						|
        def setup_module(mod):
 | 
						|
            raise ValueError(42)
 | 
						|
        @pytest.fixture
 | 
						|
        def hello(request):
 | 
						|
            raise ValueError("xyz43")
 | 
						|
        def test_function1(hello):
 | 
						|
            pass
 | 
						|
        def test_function2(hello):
 | 
						|
            pass
 | 
						|
    """
 | 
						|
    )
 | 
						|
    result = testdir.runpytest(p)
 | 
						|
    result.stdout.fnmatch_lines(
 | 
						|
        [
 | 
						|
            "*function1*",
 | 
						|
            "*ValueError*42*",
 | 
						|
            "*function2*",
 | 
						|
            "*ValueError*42*",
 | 
						|
            "*2 error*",
 | 
						|
        ]
 | 
						|
    )
 | 
						|
    assert "xyz43" not in result.stdout.str()
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize("arg", ["", "arg"])
 | 
						|
def test_setup_teardown_function_level_with_optional_argument(
 | 
						|
    testdir, monkeypatch, arg
 | 
						|
):
 | 
						|
    """parameter to setup/teardown xunit-style functions parameter is now optional (#1728)."""
 | 
						|
    import sys
 | 
						|
 | 
						|
    trace_setups_teardowns = []
 | 
						|
    monkeypatch.setattr(
 | 
						|
        sys, "trace_setups_teardowns", trace_setups_teardowns, raising=False
 | 
						|
    )
 | 
						|
    p = testdir.makepyfile(
 | 
						|
        """
 | 
						|
        import pytest
 | 
						|
        import sys
 | 
						|
 | 
						|
        trace = sys.trace_setups_teardowns.append
 | 
						|
 | 
						|
        def setup_module({arg}): trace('setup_module')
 | 
						|
        def teardown_module({arg}): trace('teardown_module')
 | 
						|
 | 
						|
        def setup_function({arg}): trace('setup_function')
 | 
						|
        def teardown_function({arg}): trace('teardown_function')
 | 
						|
 | 
						|
        def test_function_1(): pass
 | 
						|
        def test_function_2(): pass
 | 
						|
 | 
						|
        class Test(object):
 | 
						|
            def setup_method(self, {arg}): trace('setup_method')
 | 
						|
            def teardown_method(self, {arg}): trace('teardown_method')
 | 
						|
 | 
						|
            def test_method_1(self): pass
 | 
						|
            def test_method_2(self): pass
 | 
						|
    """.format(
 | 
						|
            arg=arg
 | 
						|
        )
 | 
						|
    )
 | 
						|
    result = testdir.inline_run(p)
 | 
						|
    result.assertoutcome(passed=4)
 | 
						|
 | 
						|
    expected = [
 | 
						|
        "setup_module",
 | 
						|
        "setup_function",
 | 
						|
        "teardown_function",
 | 
						|
        "setup_function",
 | 
						|
        "teardown_function",
 | 
						|
        "setup_method",
 | 
						|
        "teardown_method",
 | 
						|
        "setup_method",
 | 
						|
        "teardown_method",
 | 
						|
        "teardown_module",
 | 
						|
    ]
 | 
						|
    assert trace_setups_teardowns == expected
 |