1473 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			1473 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Python
		
	
	
	
| import gc
 | |
| import sys
 | |
| from typing import List
 | |
| 
 | |
| import pytest
 | |
| from _pytest.config import ExitCode
 | |
| from _pytest.monkeypatch import MonkeyPatch
 | |
| from _pytest.pytester import Pytester
 | |
| 
 | |
| 
 | |
| def test_simple_unittest(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def testpassing(self):
 | |
|                 self.assertEqual('foo', 'foo')
 | |
|             def test_failing(self):
 | |
|                 self.assertEqual('foo', 'bar')
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     assert reprec.matchreport("testpassing").passed
 | |
|     assert reprec.matchreport("test_failing").failed
 | |
| 
 | |
| 
 | |
| def test_runTest_method(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCaseWithRunTest(unittest.TestCase):
 | |
|             def runTest(self):
 | |
|                 self.assertEqual('foo', 'foo')
 | |
|         class MyTestCaseWithoutRunTest(unittest.TestCase):
 | |
|             def runTest(self):
 | |
|                 self.assertEqual('foo', 'foo')
 | |
|             def test_something(self):
 | |
|                 pass
 | |
|         """
 | |
|     )
 | |
|     result = pytester.runpytest("-v")
 | |
|     result.stdout.fnmatch_lines(
 | |
|         """
 | |
|         *MyTestCaseWithRunTest::runTest*
 | |
|         *MyTestCaseWithoutRunTest::test_something*
 | |
|         *2 passed*
 | |
|     """
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_isclasscheck_issue53(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class _E(object):
 | |
|             def __getattr__(self, tag):
 | |
|                 pass
 | |
|         E = _E()
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest(testpath)
 | |
|     assert result.ret == ExitCode.NO_TESTS_COLLECTED
 | |
| 
 | |
| 
 | |
| def test_setup(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def setUp(self):
 | |
|                 self.foo = 1
 | |
|             def setup_method(self, method):
 | |
|                 self.foo2 = 1
 | |
|             def test_both(self):
 | |
|                 self.assertEqual(1, self.foo)
 | |
|                 assert self.foo2 == 1
 | |
|             def teardown_method(self, method):
 | |
|                 assert 0, "42"
 | |
| 
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run("-s", testpath)
 | |
|     assert reprec.matchreport("test_both", when="call").passed
 | |
|     rep = reprec.matchreport("test_both", when="teardown")
 | |
|     assert rep.failed and "42" in str(rep.longrepr)
 | |
| 
 | |
| 
 | |
| def test_setUpModule(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         values = []
 | |
| 
 | |
|         def setUpModule():
 | |
|             values.append(1)
 | |
| 
 | |
|         def tearDownModule():
 | |
|             del values[0]
 | |
| 
 | |
|         def test_hello():
 | |
|             assert values == [1]
 | |
| 
 | |
|         def test_world():
 | |
|             assert values == [1]
 | |
|         """
 | |
|     )
 | |
|     result = pytester.runpytest(testpath)
 | |
|     result.stdout.fnmatch_lines(["*2 passed*"])
 | |
| 
 | |
| 
 | |
| def test_setUpModule_failing_no_teardown(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         values = []
 | |
| 
 | |
|         def setUpModule():
 | |
|             0/0
 | |
| 
 | |
|         def tearDownModule():
 | |
|             values.append(1)
 | |
| 
 | |
|         def test_hello():
 | |
|             pass
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(passed=0, failed=1)
 | |
|     call = reprec.getcalls("pytest_runtest_setup")[0]
 | |
|     assert not call.item.module.values
 | |
| 
 | |
| 
 | |
| def test_new_instances(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test_func1(self):
 | |
|                 self.x = 2
 | |
|             def test_func2(self):
 | |
|                 assert not hasattr(self, 'x')
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(passed=2)
 | |
| 
 | |
| 
 | |
| def test_function_item_obj_is_instance(pytester: Pytester) -> None:
 | |
|     """item.obj should be a bound method on unittest.TestCase function items (#5390)."""
 | |
|     pytester.makeconftest(
 | |
|         """
 | |
|         def pytest_runtest_makereport(item, call):
 | |
|             if call.when == 'call':
 | |
|                 class_ = item.parent.obj
 | |
|                 assert isinstance(item.obj.__self__, class_)
 | |
|     """
 | |
|     )
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
| 
 | |
|         class Test(unittest.TestCase):
 | |
|             def test_foo(self):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest_inprocess()
 | |
|     result.stdout.fnmatch_lines(["* 1 passed in*"])
 | |
| 
 | |
| 
 | |
| def test_teardown(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             def tearDown(self):
 | |
|                 self.values.append(None)
 | |
|         class Second(unittest.TestCase):
 | |
|             def test_check(self):
 | |
|                 self.assertEqual(MyTestCase.values, [None])
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert failed == 0, failed
 | |
|     assert passed == 2
 | |
|     assert passed + skipped + failed == 2
 | |
| 
 | |
| 
 | |
| def test_teardown_issue1649(pytester: Pytester) -> None:
 | |
|     """
 | |
|     Are TestCase objects cleaned up? Often unittest TestCase objects set
 | |
|     attributes that are large and expensive during setUp.
 | |
| 
 | |
|     The TestCase will not be cleaned up if the test fails, because it
 | |
|     would then exist in the stackframe.
 | |
|     """
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
 | |
|             def setUp(self):
 | |
|                 self.an_expensive_object = 1
 | |
|             def test_demo(self):
 | |
|                 pass
 | |
| 
 | |
|     """
 | |
|     )
 | |
|     pytester.inline_run("-s", testpath)
 | |
|     gc.collect()
 | |
|     for obj in gc.get_objects():
 | |
|         assert type(obj).__name__ != "TestCaseObjectsShouldBeCleanedUp"
 | |
| 
 | |
| 
 | |
| def test_unittest_skip_issue148(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
| 
 | |
|         @unittest.skip("hello")
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             @classmethod
 | |
|             def setUpClass(self):
 | |
|                 xxx
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             @classmethod
 | |
|             def tearDownClass(self):
 | |
|                 xxx
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(skipped=1)
 | |
| 
 | |
| 
 | |
| def test_method_and_teardown_failing_reporting(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class TC(unittest.TestCase):
 | |
|             def tearDown(self):
 | |
|                 assert 0, "down1"
 | |
|             def test_method(self):
 | |
|                 assert False, "down2"
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("-s")
 | |
|     assert result.ret == 1
 | |
|     result.stdout.fnmatch_lines(
 | |
|         [
 | |
|             "*tearDown*",
 | |
|             "*assert 0*",
 | |
|             "*test_method*",
 | |
|             "*assert False*",
 | |
|             "*1 failed*1 error*",
 | |
|         ]
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_setup_failure_is_shown(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
|         class TC(unittest.TestCase):
 | |
|             def setUp(self):
 | |
|                 assert 0, "down1"
 | |
|             def test_method(self):
 | |
|                 print("never42")
 | |
|                 xyz
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("-s")
 | |
|     assert result.ret == 1
 | |
|     result.stdout.fnmatch_lines(["*setUp*", "*assert 0*down1*", "*1 failed*"])
 | |
|     result.stdout.no_fnmatch_line("*never42*")
 | |
| 
 | |
| 
 | |
| def test_setup_setUpClass(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             x = 0
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 cls.x += 1
 | |
|             def test_func1(self):
 | |
|                 assert self.x == 1
 | |
|             def test_func2(self):
 | |
|                 assert self.x == 1
 | |
|             @classmethod
 | |
|             def tearDownClass(cls):
 | |
|                 cls.x -= 1
 | |
|         def test_teareddown():
 | |
|             assert MyTestCase.x == 0
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(passed=3)
 | |
| 
 | |
| 
 | |
| def test_fixtures_setup_setUpClass_issue8394(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 pass
 | |
|             def test_func1(self):
 | |
|                 pass
 | |
|             @classmethod
 | |
|             def tearDownClass(cls):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("--fixtures")
 | |
|     assert result.ret == 0
 | |
|     result.stdout.no_fnmatch_line("*no docstring available*")
 | |
| 
 | |
|     result = pytester.runpytest("--fixtures", "-v")
 | |
|     assert result.ret == 0
 | |
|     result.stdout.fnmatch_lines(["*no docstring available*"])
 | |
| 
 | |
| 
 | |
| def test_setup_class(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             x = 0
 | |
|             def setup_class(cls):
 | |
|                 cls.x += 1
 | |
|             def test_func1(self):
 | |
|                 assert self.x == 1
 | |
|             def test_func2(self):
 | |
|                 assert self.x == 1
 | |
|             def teardown_class(cls):
 | |
|                 cls.x -= 1
 | |
|         def test_teareddown():
 | |
|             assert MyTestCase.x == 0
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(passed=3)
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("type", ["Error", "Failure"])
 | |
| def test_testcase_adderrorandfailure_defers(pytester: Pytester, type: str) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         from unittest import TestCase
 | |
|         import pytest
 | |
|         class MyTestCase(TestCase):
 | |
|             def run(self, result):
 | |
|                 excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
 | |
|                 try:
 | |
|                     result.add%s(self, excinfo._excinfo)
 | |
|                 except KeyboardInterrupt:
 | |
|                     raise
 | |
|                 except:
 | |
|                     pytest.fail("add%s should not raise")
 | |
|             def test_hello(self):
 | |
|                 pass
 | |
|     """
 | |
|         % (type, type)
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.no_fnmatch_line("*should not raise*")
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("type", ["Error", "Failure"])
 | |
| def test_testcase_custom_exception_info(pytester: Pytester, type: str) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         from typing import Generic, TypeVar
 | |
|         from unittest import TestCase
 | |
|         import pytest, _pytest._code
 | |
| 
 | |
|         class MyTestCase(TestCase):
 | |
|             def run(self, result):
 | |
|                 excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
 | |
|                 # We fake an incompatible exception info.
 | |
|                 class FakeExceptionInfo(Generic[TypeVar("E")]):
 | |
|                     def __init__(self, *args, **kwargs):
 | |
|                         mp.undo()
 | |
|                         raise TypeError()
 | |
|                     @classmethod
 | |
|                     def from_current(cls):
 | |
|                         return cls()
 | |
|                     @classmethod
 | |
|                     def from_exc_info(cls, *args, **kwargs):
 | |
|                         return cls()
 | |
|                 mp = pytest.MonkeyPatch()
 | |
|                 mp.setattr(_pytest._code, 'ExceptionInfo', FakeExceptionInfo)
 | |
|                 try:
 | |
|                     excinfo = excinfo._excinfo
 | |
|                     result.add%(type)s(self, excinfo)
 | |
|                 finally:
 | |
|                     mp.undo()
 | |
| 
 | |
|             def test_hello(self):
 | |
|                 pass
 | |
|     """
 | |
|         % locals()
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.fnmatch_lines(
 | |
|         [
 | |
|             "NOTE: Incompatible Exception Representation*",
 | |
|             "*ZeroDivisionError*",
 | |
|             "*1 failed*",
 | |
|         ]
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_testcase_totally_incompatible_exception_info(pytester: Pytester) -> None:
 | |
|     import _pytest.unittest
 | |
| 
 | |
|     (item,) = pytester.getitems(
 | |
|         """
 | |
|         from unittest import TestCase
 | |
|         class MyTestCase(TestCase):
 | |
|             def test_hello(self):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     assert isinstance(item, _pytest.unittest.TestCaseFunction)
 | |
|     item.addError(None, 42)  # type: ignore[arg-type]
 | |
|     excinfo = item._excinfo
 | |
|     assert excinfo is not None
 | |
|     assert "ERROR: Unknown Incompatible" in str(excinfo.pop(0).getrepr())
 | |
| 
 | |
| 
 | |
| def test_module_level_pytestmark(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
|         pytestmark = pytest.mark.xfail
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test_func1(self):
 | |
|                 assert 0
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath, "-s")
 | |
|     reprec.assertoutcome(skipped=1)
 | |
| 
 | |
| 
 | |
| class TestTrialUnittest:
 | |
|     def setup_class(cls):
 | |
|         cls.ut = pytest.importorskip("twisted.trial.unittest")
 | |
|         # on windows trial uses a socket for a reactor and apparently doesn't close it properly
 | |
|         # https://twistedmatrix.com/trac/ticket/9227
 | |
|         cls.ignore_unclosed_socket_warning = ("-W", "always")
 | |
| 
 | |
|     def test_trial_testcase_runtest_not_collected(self, pytester: Pytester) -> None:
 | |
|         pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial.unittest import TestCase
 | |
| 
 | |
|             class TC(TestCase):
 | |
|                 def test_hello(self):
 | |
|                     pass
 | |
|         """
 | |
|         )
 | |
|         reprec = pytester.inline_run(*self.ignore_unclosed_socket_warning)
 | |
|         reprec.assertoutcome(passed=1)
 | |
|         pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial.unittest import TestCase
 | |
| 
 | |
|             class TC(TestCase):
 | |
|                 def runTest(self):
 | |
|                     pass
 | |
|         """
 | |
|         )
 | |
|         reprec = pytester.inline_run(*self.ignore_unclosed_socket_warning)
 | |
|         reprec.assertoutcome(passed=1)
 | |
| 
 | |
|     def test_trial_exceptions_with_skips(self, pytester: Pytester) -> None:
 | |
|         pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial import unittest
 | |
|             import pytest
 | |
|             class TC(unittest.TestCase):
 | |
|                 def test_hello(self):
 | |
|                     pytest.skip("skip_in_method")
 | |
|                 @pytest.mark.skipif("sys.version_info != 1")
 | |
|                 def test_hello2(self):
 | |
|                     pass
 | |
|                 @pytest.mark.xfail(reason="iwanto")
 | |
|                 def test_hello3(self):
 | |
|                     assert 0
 | |
|                 def test_hello4(self):
 | |
|                     pytest.xfail("i2wanto")
 | |
|                 def test_trial_skip(self):
 | |
|                     pass
 | |
|                 test_trial_skip.skip = "trialselfskip"
 | |
| 
 | |
|                 def test_trial_todo(self):
 | |
|                     assert 0
 | |
|                 test_trial_todo.todo = "mytodo"
 | |
| 
 | |
|                 def test_trial_todo_success(self):
 | |
|                     pass
 | |
|                 test_trial_todo_success.todo = "mytodo"
 | |
| 
 | |
|             class TC2(unittest.TestCase):
 | |
|                 def setup_class(cls):
 | |
|                     pytest.skip("skip_in_setup_class")
 | |
|                 def test_method(self):
 | |
|                     pass
 | |
|         """
 | |
|         )
 | |
|         result = pytester.runpytest("-rxs", *self.ignore_unclosed_socket_warning)
 | |
|         result.stdout.fnmatch_lines_random(
 | |
|             [
 | |
|                 "*XFAIL*test_trial_todo*",
 | |
|                 "*trialselfskip*",
 | |
|                 "*skip_in_setup_class*",
 | |
|                 "*iwanto*",
 | |
|                 "*i2wanto*",
 | |
|                 "*sys.version_info*",
 | |
|                 "*skip_in_method*",
 | |
|                 "*1 failed*4 skipped*3 xfailed*",
 | |
|             ]
 | |
|         )
 | |
|         assert result.ret == 1
 | |
| 
 | |
|     def test_trial_error(self, pytester: Pytester) -> None:
 | |
|         pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial.unittest import TestCase
 | |
|             from twisted.internet.defer import Deferred
 | |
|             from twisted.internet import reactor
 | |
| 
 | |
|             class TC(TestCase):
 | |
|                 def test_one(self):
 | |
|                     crash
 | |
| 
 | |
|                 def test_two(self):
 | |
|                     def f(_):
 | |
|                         crash
 | |
| 
 | |
|                     d = Deferred()
 | |
|                     d.addCallback(f)
 | |
|                     reactor.callLater(0.3, d.callback, None)
 | |
|                     return d
 | |
| 
 | |
|                 def test_three(self):
 | |
|                     def f():
 | |
|                         pass # will never get called
 | |
|                     reactor.callLater(0.3, f)
 | |
|                 # will crash at teardown
 | |
| 
 | |
|                 def test_four(self):
 | |
|                     def f(_):
 | |
|                         reactor.callLater(0.3, f)
 | |
|                         crash
 | |
| 
 | |
|                     d = Deferred()
 | |
|                     d.addCallback(f)
 | |
|                     reactor.callLater(0.3, d.callback, None)
 | |
|                     return d
 | |
|                 # will crash both at test time and at teardown
 | |
|         """
 | |
|         )
 | |
|         result = pytester.runpytest("-vv", "-oconsole_output_style=classic")
 | |
|         result.stdout.fnmatch_lines(
 | |
|             [
 | |
|                 "test_trial_error.py::TC::test_four FAILED",
 | |
|                 "test_trial_error.py::TC::test_four ERROR",
 | |
|                 "test_trial_error.py::TC::test_one FAILED",
 | |
|                 "test_trial_error.py::TC::test_three FAILED",
 | |
|                 "test_trial_error.py::TC::test_two FAILED",
 | |
|                 "*ERRORS*",
 | |
|                 "*_ ERROR at teardown of TC.test_four _*",
 | |
|                 "*DelayedCalls*",
 | |
|                 "*= FAILURES =*",
 | |
|                 "*_ TC.test_four _*",
 | |
|                 "*NameError*crash*",
 | |
|                 "*_ TC.test_one _*",
 | |
|                 "*NameError*crash*",
 | |
|                 "*_ TC.test_three _*",
 | |
|                 "*DelayedCalls*",
 | |
|                 "*_ TC.test_two _*",
 | |
|                 "*NameError*crash*",
 | |
|                 "*= 4 failed, 1 error in *",
 | |
|             ]
 | |
|         )
 | |
| 
 | |
|     def test_trial_pdb(self, pytester: Pytester) -> None:
 | |
|         p = pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial import unittest
 | |
|             import pytest
 | |
|             class TC(unittest.TestCase):
 | |
|                 def test_hello(self):
 | |
|                     assert 0, "hellopdb"
 | |
|         """
 | |
|         )
 | |
|         child = pytester.spawn_pytest(str(p))
 | |
|         child.expect("hellopdb")
 | |
|         child.sendeof()
 | |
| 
 | |
|     def test_trial_testcase_skip_property(self, pytester: Pytester) -> None:
 | |
|         testpath = pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial import unittest
 | |
|             class MyTestCase(unittest.TestCase):
 | |
|                 skip = 'dont run'
 | |
|                 def test_func(self):
 | |
|                     pass
 | |
|             """
 | |
|         )
 | |
|         reprec = pytester.inline_run(testpath, "-s")
 | |
|         reprec.assertoutcome(skipped=1)
 | |
| 
 | |
|     def test_trial_testfunction_skip_property(self, pytester: Pytester) -> None:
 | |
|         testpath = pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial import unittest
 | |
|             class MyTestCase(unittest.TestCase):
 | |
|                 def test_func(self):
 | |
|                     pass
 | |
|                 test_func.skip = 'dont run'
 | |
|             """
 | |
|         )
 | |
|         reprec = pytester.inline_run(testpath, "-s")
 | |
|         reprec.assertoutcome(skipped=1)
 | |
| 
 | |
|     def test_trial_testcase_todo_property(self, pytester: Pytester) -> None:
 | |
|         testpath = pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial import unittest
 | |
|             class MyTestCase(unittest.TestCase):
 | |
|                 todo = 'dont run'
 | |
|                 def test_func(self):
 | |
|                     assert 0
 | |
|             """
 | |
|         )
 | |
|         reprec = pytester.inline_run(testpath, "-s")
 | |
|         reprec.assertoutcome(skipped=1)
 | |
| 
 | |
|     def test_trial_testfunction_todo_property(self, pytester: Pytester) -> None:
 | |
|         testpath = pytester.makepyfile(
 | |
|             """
 | |
|             from twisted.trial import unittest
 | |
|             class MyTestCase(unittest.TestCase):
 | |
|                 def test_func(self):
 | |
|                     assert 0
 | |
|                 test_func.todo = 'dont run'
 | |
|             """
 | |
|         )
 | |
|         reprec = pytester.inline_run(
 | |
|             testpath, "-s", *self.ignore_unclosed_socket_warning
 | |
|         )
 | |
|         reprec.assertoutcome(skipped=1)
 | |
| 
 | |
| 
 | |
| def test_djangolike_testcase(pytester: Pytester) -> None:
 | |
|     # contributed from Morten Breekevold
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         from unittest import TestCase, main
 | |
| 
 | |
|         class DjangoLikeTestCase(TestCase):
 | |
| 
 | |
|             def setUp(self):
 | |
|                 print("setUp()")
 | |
| 
 | |
|             def test_presetup_has_been_run(self):
 | |
|                 print("test_thing()")
 | |
|                 self.assertTrue(hasattr(self, 'was_presetup'))
 | |
| 
 | |
|             def tearDown(self):
 | |
|                 print("tearDown()")
 | |
| 
 | |
|             def __call__(self, result=None):
 | |
|                 try:
 | |
|                     self._pre_setup()
 | |
|                 except (KeyboardInterrupt, SystemExit):
 | |
|                     raise
 | |
|                 except Exception:
 | |
|                     import sys
 | |
|                     result.addError(self, sys.exc_info())
 | |
|                     return
 | |
|                 super(DjangoLikeTestCase, self).__call__(result)
 | |
|                 try:
 | |
|                     self._post_teardown()
 | |
|                 except (KeyboardInterrupt, SystemExit):
 | |
|                     raise
 | |
|                 except Exception:
 | |
|                     import sys
 | |
|                     result.addError(self, sys.exc_info())
 | |
|                     return
 | |
| 
 | |
|             def _pre_setup(self):
 | |
|                 print("_pre_setup()")
 | |
|                 self.was_presetup = True
 | |
| 
 | |
|             def _post_teardown(self):
 | |
|                 print("_post_teardown()")
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("-s")
 | |
|     assert result.ret == 0
 | |
|     result.stdout.fnmatch_lines(
 | |
|         [
 | |
|             "*_pre_setup()*",
 | |
|             "*setUp()*",
 | |
|             "*test_thing()*",
 | |
|             "*tearDown()*",
 | |
|             "*_post_teardown()*",
 | |
|         ]
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_unittest_not_shown_in_traceback(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class t(unittest.TestCase):
 | |
|             def test_hello(self):
 | |
|                 x = 3
 | |
|                 self.assertEqual(x, 4)
 | |
|     """
 | |
|     )
 | |
|     res = pytester.runpytest()
 | |
|     res.stdout.no_fnmatch_line("*failUnlessEqual*")
 | |
| 
 | |
| 
 | |
| def test_unorderable_types(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class TestJoinEmpty(unittest.TestCase):
 | |
|             pass
 | |
| 
 | |
|         def make_test():
 | |
|             class Test(unittest.TestCase):
 | |
|                 pass
 | |
|             Test.__name__ = "TestFoo"
 | |
|             return Test
 | |
|         TestFoo = make_test()
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.no_fnmatch_line("*TypeError*")
 | |
|     assert result.ret == ExitCode.NO_TESTS_COLLECTED
 | |
| 
 | |
| 
 | |
| def test_unittest_typerror_traceback(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class TestJoinEmpty(unittest.TestCase):
 | |
|             def test_hello(self, arg1):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     assert "TypeError" in result.stdout.str()
 | |
|     assert result.ret == 1
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("runner", ["pytest", "unittest"])
 | |
| def test_unittest_expected_failure_for_failing_test_is_xfail(
 | |
|     pytester: Pytester, runner
 | |
| ) -> None:
 | |
|     script = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             @unittest.expectedFailure
 | |
|             def test_failing_test_is_xfail(self):
 | |
|                 assert False
 | |
|         if __name__ == '__main__':
 | |
|             unittest.main()
 | |
|     """
 | |
|     )
 | |
|     if runner == "pytest":
 | |
|         result = pytester.runpytest("-rxX")
 | |
|         result.stdout.fnmatch_lines(
 | |
|             ["*XFAIL*MyTestCase*test_failing_test_is_xfail*", "*1 xfailed*"]
 | |
|         )
 | |
|     else:
 | |
|         result = pytester.runpython(script)
 | |
|         result.stderr.fnmatch_lines(["*1 test in*", "*OK*(expected failures=1)*"])
 | |
|     assert result.ret == 0
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("runner", ["pytest", "unittest"])
 | |
| def test_unittest_expected_failure_for_passing_test_is_fail(
 | |
|     pytester: Pytester,
 | |
|     runner: str,
 | |
| ) -> None:
 | |
|     script = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             @unittest.expectedFailure
 | |
|             def test_passing_test_is_fail(self):
 | |
|                 assert True
 | |
|         if __name__ == '__main__':
 | |
|             unittest.main()
 | |
|     """
 | |
|     )
 | |
| 
 | |
|     if runner == "pytest":
 | |
|         result = pytester.runpytest("-rxX")
 | |
|         result.stdout.fnmatch_lines(
 | |
|             [
 | |
|                 "*MyTestCase*test_passing_test_is_fail*",
 | |
|                 "Unexpected success",
 | |
|                 "*1 failed*",
 | |
|             ]
 | |
|         )
 | |
|     else:
 | |
|         result = pytester.runpython(script)
 | |
|         result.stderr.fnmatch_lines(["*1 test in*", "*(unexpected successes=1)*"])
 | |
| 
 | |
|     assert result.ret == 1
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("stmt", ["return", "yield"])
 | |
| def test_unittest_setup_interaction(pytester: Pytester, stmt: str) -> None:
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             @pytest.fixture(scope="class", autouse=True)
 | |
|             def perclass(self, request):
 | |
|                 request.cls.hello = "world"
 | |
|                 {stmt}
 | |
|             @pytest.fixture(scope="function", autouse=True)
 | |
|             def perfunction(self, request):
 | |
|                 request.instance.funcname = request.function.__name__
 | |
|                 {stmt}
 | |
| 
 | |
|             def test_method1(self):
 | |
|                 assert self.funcname == "test_method1"
 | |
|                 assert self.hello == "world"
 | |
| 
 | |
|             def test_method2(self):
 | |
|                 assert self.funcname == "test_method2"
 | |
| 
 | |
|             def test_classattr(self):
 | |
|                 assert self.__class__.hello == "world"
 | |
|     """.format(
 | |
|             stmt=stmt
 | |
|         )
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.fnmatch_lines(["*3 passed*"])
 | |
| 
 | |
| 
 | |
| def test_non_unittest_no_setupclass_support(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         class TestFoo(object):
 | |
|             x = 0
 | |
| 
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 cls.x = 1
 | |
| 
 | |
|             def test_method1(self):
 | |
|                 assert self.x == 0
 | |
| 
 | |
|             @classmethod
 | |
|             def tearDownClass(cls):
 | |
|                 cls.x = 1
 | |
| 
 | |
|         def test_not_teareddown():
 | |
|             assert TestFoo.x == 0
 | |
| 
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(passed=2)
 | |
| 
 | |
| 
 | |
| def test_no_teardown_if_setupclass_failed(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             x = 0
 | |
| 
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 cls.x = 1
 | |
|                 assert False
 | |
| 
 | |
|             def test_func1(self):
 | |
|                 cls.x = 10
 | |
| 
 | |
|             @classmethod
 | |
|             def tearDownClass(cls):
 | |
|                 cls.x = 100
 | |
| 
 | |
|         def test_notTornDown():
 | |
|             assert MyTestCase.x == 1
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     reprec.assertoutcome(passed=1, failed=1)
 | |
| 
 | |
| 
 | |
| def test_cleanup_functions(pytester: Pytester) -> None:
 | |
|     """Ensure functions added with addCleanup are always called after each test ends (#6947)"""
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
| 
 | |
|         cleanups = []
 | |
| 
 | |
|         class Test(unittest.TestCase):
 | |
| 
 | |
|             def test_func_1(self):
 | |
|                 self.addCleanup(cleanups.append, "test_func_1")
 | |
| 
 | |
|             def test_func_2(self):
 | |
|                 self.addCleanup(cleanups.append, "test_func_2")
 | |
|                 assert 0
 | |
| 
 | |
|             def test_func_3_check_cleanups(self):
 | |
|                 assert cleanups == ["test_func_1", "test_func_2"]
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("-v")
 | |
|     result.stdout.fnmatch_lines(
 | |
|         [
 | |
|             "*::test_func_1 PASSED *",
 | |
|             "*::test_func_2 FAILED *",
 | |
|             "*::test_func_3_check_cleanups PASSED *",
 | |
|         ]
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_issue333_result_clearing(pytester: Pytester) -> None:
 | |
|     pytester.makeconftest(
 | |
|         """
 | |
|         import pytest
 | |
|         @pytest.hookimpl(hookwrapper=True)
 | |
|         def pytest_runtest_call(item):
 | |
|             yield
 | |
|             assert 0
 | |
|     """
 | |
|     )
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class TestIt(unittest.TestCase):
 | |
|             def test_func(self):
 | |
|                 0/0
 | |
|     """
 | |
|     )
 | |
| 
 | |
|     reprec = pytester.inline_run()
 | |
|     reprec.assertoutcome(failed=1)
 | |
| 
 | |
| 
 | |
| def test_unittest_raise_skip_issue748(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         test_foo="""
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test_one(self):
 | |
|                 raise unittest.SkipTest('skipping due to reasons')
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("-v", "-rs")
 | |
|     result.stdout.fnmatch_lines(
 | |
|         """
 | |
|         *SKIP*[1]*test_foo.py*skipping due to reasons*
 | |
|         *1 skipped*
 | |
|     """
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_unittest_skip_issue1169(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         test_foo="""
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             @unittest.skip("skipping due to reasons")
 | |
|             def test_skip(self):
 | |
|                  self.fail()
 | |
|         """
 | |
|     )
 | |
|     result = pytester.runpytest("-v", "-rs")
 | |
|     result.stdout.fnmatch_lines(
 | |
|         """
 | |
|         *SKIP*[1]*skipping due to reasons*
 | |
|         *1 skipped*
 | |
|     """
 | |
|     )
 | |
| 
 | |
| 
 | |
| def test_class_method_containing_test_issue1558(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         test_foo="""
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test_should_run(self):
 | |
|                 pass
 | |
|             def test_should_not_run(self):
 | |
|                 pass
 | |
|             test_should_not_run.__test__ = False
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run()
 | |
|     reprec.assertoutcome(passed=1)
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("base", ["builtins.object", "unittest.TestCase"])
 | |
| def test_usefixtures_marker_on_unittest(base, pytester: Pytester) -> None:
 | |
|     """#3498"""
 | |
|     module = base.rsplit(".", 1)[0]
 | |
|     pytest.importorskip(module)
 | |
|     pytester.makepyfile(
 | |
|         conftest="""
 | |
|         import pytest
 | |
| 
 | |
|         @pytest.fixture(scope='function')
 | |
|         def fixture1(request, monkeypatch):
 | |
|             monkeypatch.setattr(request.instance, 'fixture1', True )
 | |
| 
 | |
| 
 | |
|         @pytest.fixture(scope='function')
 | |
|         def fixture2(request, monkeypatch):
 | |
|             monkeypatch.setattr(request.instance, 'fixture2', True )
 | |
| 
 | |
|         def node_and_marks(item):
 | |
|             print(item.nodeid)
 | |
|             for mark in item.iter_markers():
 | |
|                 print("  ", mark)
 | |
| 
 | |
|         @pytest.fixture(autouse=True)
 | |
|         def my_marks(request):
 | |
|             node_and_marks(request.node)
 | |
| 
 | |
|         def pytest_collection_modifyitems(items):
 | |
|             for item in items:
 | |
|                node_and_marks(item)
 | |
| 
 | |
|         """
 | |
|     )
 | |
| 
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import pytest
 | |
|         import {module}
 | |
| 
 | |
|         class Tests({base}):
 | |
|             fixture1 = False
 | |
|             fixture2 = False
 | |
| 
 | |
|             @pytest.mark.usefixtures("fixture1")
 | |
|             def test_one(self):
 | |
|                 assert self.fixture1
 | |
|                 assert not self.fixture2
 | |
| 
 | |
|             @pytest.mark.usefixtures("fixture1", "fixture2")
 | |
|             def test_two(self):
 | |
|                 assert self.fixture1
 | |
|                 assert self.fixture2
 | |
| 
 | |
| 
 | |
|     """.format(
 | |
|             module=module, base=base
 | |
|         )
 | |
|     )
 | |
| 
 | |
|     result = pytester.runpytest("-s")
 | |
|     result.assert_outcomes(passed=2)
 | |
| 
 | |
| 
 | |
| def test_testcase_handles_init_exceptions(pytester: Pytester) -> None:
 | |
|     """
 | |
|     Regression test to make sure exceptions in the __init__ method are bubbled up correctly.
 | |
|     See https://github.com/pytest-dev/pytest/issues/3788
 | |
|     """
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         from unittest import TestCase
 | |
|         import pytest
 | |
|         class MyTestCase(TestCase):
 | |
|             def __init__(self, *args, **kwargs):
 | |
|                 raise Exception("should raise this exception")
 | |
|             def test_hello(self):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     assert "should raise this exception" in result.stdout.str()
 | |
|     result.stdout.no_fnmatch_line("*ERROR at teardown of MyTestCase.test_hello*")
 | |
| 
 | |
| 
 | |
| def test_error_message_with_parametrized_fixtures(pytester: Pytester) -> None:
 | |
|     pytester.copy_example("unittest/test_parametrized_fixture_error_message.py")
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.fnmatch_lines(
 | |
|         [
 | |
|             "*test_two does not support fixtures*",
 | |
|             "*TestSomethingElse::test_two",
 | |
|             "*Function type: TestCaseFunction",
 | |
|         ]
 | |
|     )
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize(
 | |
|     "test_name, expected_outcome",
 | |
|     [
 | |
|         ("test_setup_skip.py", "1 skipped"),
 | |
|         ("test_setup_skip_class.py", "1 skipped"),
 | |
|         ("test_setup_skip_module.py", "1 error"),
 | |
|     ],
 | |
| )
 | |
| def test_setup_inheritance_skipping(
 | |
|     pytester: Pytester, test_name, expected_outcome
 | |
| ) -> None:
 | |
|     """Issue #4700"""
 | |
|     pytester.copy_example(f"unittest/{test_name}")
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.fnmatch_lines([f"* {expected_outcome} in *"])
 | |
| 
 | |
| 
 | |
| def test_BdbQuit(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         test_foo="""
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test_bdbquit(self):
 | |
|                 import bdb
 | |
|                 raise bdb.BdbQuit()
 | |
| 
 | |
|             def test_should_not_run(self):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run()
 | |
|     reprec.assertoutcome(failed=1, passed=1)
 | |
| 
 | |
| 
 | |
| def test_exit_outcome(pytester: Pytester) -> None:
 | |
|     pytester.makepyfile(
 | |
|         test_foo="""
 | |
|         import pytest
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test_exit_outcome(self):
 | |
|                 pytest.exit("pytest_exit called")
 | |
| 
 | |
|             def test_should_not_run(self):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest()
 | |
|     result.stdout.fnmatch_lines(["*Exit: pytest_exit called*", "*= no tests ran in *"])
 | |
| 
 | |
| 
 | |
| def test_trace(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
 | |
|     calls = []
 | |
| 
 | |
|     def check_call(*args, **kwargs):
 | |
|         calls.append((args, kwargs))
 | |
|         assert args == ("runcall",)
 | |
| 
 | |
|         class _pdb:
 | |
|             def runcall(*args, **kwargs):
 | |
|                 calls.append((args, kwargs))
 | |
| 
 | |
|         return _pdb
 | |
| 
 | |
|     monkeypatch.setattr("_pytest.debugging.pytestPDB._init_pdb", check_call)
 | |
| 
 | |
|     p1 = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             def test(self):
 | |
|                 self.assertEqual('foo', 'foo')
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest("--trace", str(p1))
 | |
|     assert len(calls) == 2
 | |
|     assert result.ret == 0
 | |
| 
 | |
| 
 | |
| def test_pdb_teardown_called(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
 | |
|     """Ensure tearDown() is always called when --pdb is given in the command-line.
 | |
| 
 | |
|     We delay the normal tearDown() calls when --pdb is given, so this ensures we are calling
 | |
|     tearDown() eventually to avoid memory leaks when using --pdb.
 | |
|     """
 | |
|     teardowns: List[str] = []
 | |
|     monkeypatch.setattr(
 | |
|         pytest, "test_pdb_teardown_called_teardowns", teardowns, raising=False
 | |
|     )
 | |
| 
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
| 
 | |
|             def tearDown(self):
 | |
|                 pytest.test_pdb_teardown_called_teardowns.append(self.id())
 | |
| 
 | |
|             def test_1(self):
 | |
|                 pass
 | |
|             def test_2(self):
 | |
|                 pass
 | |
|     """
 | |
|     )
 | |
|     result = pytester.runpytest_inprocess("--pdb")
 | |
|     result.stdout.fnmatch_lines("* 2 passed in *")
 | |
|     assert teardowns == [
 | |
|         "test_pdb_teardown_called.MyTestCase.test_1",
 | |
|         "test_pdb_teardown_called.MyTestCase.test_2",
 | |
|     ]
 | |
| 
 | |
| 
 | |
| @pytest.mark.parametrize("mark", ["@unittest.skip", "@pytest.mark.skip"])
 | |
| def test_pdb_teardown_skipped(
 | |
|     pytester: Pytester, monkeypatch: MonkeyPatch, mark: str
 | |
| ) -> None:
 | |
|     """With --pdb, setUp and tearDown should not be called for skipped tests."""
 | |
|     tracked: List[str] = []
 | |
|     monkeypatch.setattr(pytest, "test_pdb_teardown_skipped", tracked, raising=False)
 | |
| 
 | |
|     pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         import pytest
 | |
| 
 | |
|         class MyTestCase(unittest.TestCase):
 | |
| 
 | |
|             def setUp(self):
 | |
|                 pytest.test_pdb_teardown_skipped.append("setUp:" + self.id())
 | |
| 
 | |
|             def tearDown(self):
 | |
|                 pytest.test_pdb_teardown_skipped.append("tearDown:" + self.id())
 | |
| 
 | |
|             {mark}("skipped for reasons")
 | |
|             def test_1(self):
 | |
|                 pass
 | |
| 
 | |
|     """.format(
 | |
|             mark=mark
 | |
|         )
 | |
|     )
 | |
|     result = pytester.runpytest_inprocess("--pdb")
 | |
|     result.stdout.fnmatch_lines("* 1 skipped in *")
 | |
|     assert tracked == []
 | |
| 
 | |
| 
 | |
| def test_async_support(pytester: Pytester) -> None:
 | |
|     pytest.importorskip("unittest.async_case")
 | |
| 
 | |
|     pytester.copy_example("unittest/test_unittest_asyncio.py")
 | |
|     reprec = pytester.inline_run()
 | |
|     reprec.assertoutcome(failed=1, passed=2)
 | |
| 
 | |
| 
 | |
| def test_asynctest_support(pytester: Pytester) -> None:
 | |
|     """Check asynctest support (#7110)"""
 | |
|     pytest.importorskip("asynctest")
 | |
| 
 | |
|     pytester.copy_example("unittest/test_unittest_asynctest.py")
 | |
|     reprec = pytester.inline_run()
 | |
|     reprec.assertoutcome(failed=1, passed=2)
 | |
| 
 | |
| 
 | |
| def test_plain_unittest_does_not_support_async(pytester: Pytester) -> None:
 | |
|     """Async functions in plain unittest.TestCase subclasses are not supported without plugins.
 | |
| 
 | |
|     This test exists here to avoid introducing this support by accident, leading users
 | |
|     to expect that it works, rather than doing so intentionally as a feature.
 | |
| 
 | |
|     See https://github.com/pytest-dev/pytest-asyncio/issues/180 for more context.
 | |
|     """
 | |
|     pytester.copy_example("unittest/test_unittest_plain_async.py")
 | |
|     result = pytester.runpytest_subprocess()
 | |
|     if hasattr(sys, "pypy_version_info"):
 | |
|         # in PyPy we can't reliable get the warning about the coroutine not being awaited,
 | |
|         # because it depends on the coroutine being garbage collected; given that
 | |
|         # we are running in a subprocess, that's difficult to enforce
 | |
|         expected_lines = ["*1 passed*"]
 | |
|     else:
 | |
|         expected_lines = [
 | |
|             "*RuntimeWarning: coroutine * was never awaited",
 | |
|             "*1 passed*",
 | |
|         ]
 | |
|     result.stdout.fnmatch_lines(expected_lines)
 | |
| 
 | |
| 
 | |
| @pytest.mark.skipif(
 | |
|     sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
 | |
| )
 | |
| def test_do_class_cleanups_on_success(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 def cleanup():
 | |
|                     cls.values.append(1)
 | |
|                 cls.addClassCleanup(cleanup)
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             def test_two(self):
 | |
|                 pass
 | |
|         def test_cleanup_called_exactly_once():
 | |
|             assert MyTestCase.values == [1]
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert failed == 0
 | |
|     assert passed == 3
 | |
| 
 | |
| 
 | |
| @pytest.mark.skipif(
 | |
|     sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
 | |
| )
 | |
| def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 def cleanup():
 | |
|                     cls.values.append(1)
 | |
|                 cls.addClassCleanup(cleanup)
 | |
|                 assert False
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|         def test_cleanup_called_exactly_once():
 | |
|             assert MyTestCase.values == [1]
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert failed == 1
 | |
|     assert passed == 1
 | |
| 
 | |
| 
 | |
| @pytest.mark.skipif(
 | |
|     sys.version_info < (3, 8), reason="Feature introduced in Python 3.8"
 | |
| )
 | |
| def test_do_class_cleanups_on_teardownclass_failure(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             @classmethod
 | |
|             def setUpClass(cls):
 | |
|                 def cleanup():
 | |
|                     cls.values.append(1)
 | |
|                 cls.addClassCleanup(cleanup)
 | |
|             @classmethod
 | |
|             def tearDownClass(cls):
 | |
|                 assert False
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             def test_two(self):
 | |
|                 pass
 | |
|         def test_cleanup_called_exactly_once():
 | |
|             assert MyTestCase.values == [1]
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert passed == 3
 | |
| 
 | |
| 
 | |
| def test_do_cleanups_on_success(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             def setUp(self):
 | |
|                 def cleanup():
 | |
|                     self.values.append(1)
 | |
|                 self.addCleanup(cleanup)
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             def test_two(self):
 | |
|                 pass
 | |
|         def test_cleanup_called_the_right_number_of_times():
 | |
|             assert MyTestCase.values == [1, 1]
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert failed == 0
 | |
|     assert passed == 3
 | |
| 
 | |
| 
 | |
| def test_do_cleanups_on_setup_failure(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             def setUp(self):
 | |
|                 def cleanup():
 | |
|                     self.values.append(1)
 | |
|                 self.addCleanup(cleanup)
 | |
|                 assert False
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             def test_two(self):
 | |
|                 pass
 | |
|         def test_cleanup_called_the_right_number_of_times():
 | |
|             assert MyTestCase.values == [1, 1]
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert failed == 2
 | |
|     assert passed == 1
 | |
| 
 | |
| 
 | |
| def test_do_cleanups_on_teardown_failure(pytester: Pytester) -> None:
 | |
|     testpath = pytester.makepyfile(
 | |
|         """
 | |
|         import unittest
 | |
|         class MyTestCase(unittest.TestCase):
 | |
|             values = []
 | |
|             def setUp(self):
 | |
|                 def cleanup():
 | |
|                     self.values.append(1)
 | |
|                 self.addCleanup(cleanup)
 | |
|             def tearDown(self):
 | |
|                 assert False
 | |
|             def test_one(self):
 | |
|                 pass
 | |
|             def test_two(self):
 | |
|                 pass
 | |
|         def test_cleanup_called_the_right_number_of_times():
 | |
|             assert MyTestCase.values == [1, 1]
 | |
|     """
 | |
|     )
 | |
|     reprec = pytester.inline_run(testpath)
 | |
|     passed, skipped, failed = reprec.countoutcomes()
 | |
|     assert failed == 2
 | |
|     assert passed == 1
 |