| """Sample tests driven by test.test_support.TestIsolated. |
| |
| This module is imported, never run as a test file, so that |
| :func:`test.support.isolation.runInSubprocess` has a real, importable target to run in |
| a subprocess. Several of these tests fail, error or are skipped on purpose. |
| """ |
| |
| import atexit |
| import os |
| import sys |
| import time |
| import unittest |
| from test import support |
| from test.support import isolation |
| |
| # DurationSample sleeps this long in the subprocess; a parent-reported duration |
| # close to it proves the subprocess timing was forwarded, not the replay time. |
| DURATION_SLEEP = 0.2 |
| |
| |
| class MethodSample(unittest.TestCase): |
| |
| @isolation.runInSubprocess() |
| def test_pass(self): |
| self.assertTrue(isolation.runningInSubprocess) |
| |
| @isolation.runInSubprocess() |
| def test_fail(self): |
| self.assertEqual(1, 2) |
| |
| @isolation.runInSubprocess() |
| def test_error(self): |
| raise RuntimeError('boom') |
| |
| @isolation.runInSubprocess() |
| def test_skip(self): |
| self.skipTest('nope') |
| |
| @isolation.runInSubprocess() |
| @unittest.expectedFailure |
| def test_expected_failure(self): |
| self.assertEqual(1, 2) |
| |
| @isolation.runInSubprocess() |
| @unittest.expectedFailure |
| def test_unexpected_success(self): |
| pass |
| |
| |
| @isolation.runInSubprocess() |
| class ClassSample(unittest.TestCase): |
| |
| def test_pass(self): |
| self.assertTrue(isolation.runningInSubprocess) |
| |
| def test_fail(self): |
| self.assertEqual(1, 2) |
| |
| @unittest.expectedFailure |
| def test_expected_failure(self): |
| self.assertEqual(1, 2) |
| |
| |
| class SubtestSample(unittest.TestCase): |
| |
| @isolation.runInSubprocess() |
| def test_subtests(self): |
| for i in range(3): |
| with self.subTest(i=i): |
| self.assertNotEqual(i, 1) |
| |
| |
| @isolation.runInSubprocess() |
| class DurationSample(unittest.TestCase): |
| |
| def test_slow(self): |
| time.sleep(DURATION_SLEEP) |
| |
| |
| @isolation.runInSubprocess() |
| class SubclassingSample(unittest.TestCase): |
| # setUpClass must run bound to the runtime class, so a subclass sees its own |
| # name here rather than the base class's. |
| |
| @classmethod |
| def setUpClass(cls): |
| cls.setup_class_name = cls.__name__ |
| |
| def setUp(self): |
| self.set_up = True |
| |
| def test_runtime_class(self): |
| self.assertEqual(self.setup_class_name, type(self).__name__) |
| |
| |
| class SubclassSample(SubclassingSample): |
| # What a subclass adds or overrides must run in the subprocess too. |
| |
| def setUp(self): |
| super().setUp() |
| self.set_up_in_subclass = True |
| |
| def test_added_in_subclass(self): |
| self.assertTrue(isolation.runningInSubprocess) |
| self.assertTrue(self.set_up) |
| self.assertTrue(self.set_up_in_subclass) |
| |
| |
| class BrokenSubclassSample(SubclassingSample): |
| # An overriding setUpClass() that does not call super() bypasses the |
| # subprocess entirely. |
| |
| @classmethod |
| def setUpClass(cls): |
| pass |
| |
| |
| # The exit code the samples below die with, after their tests have run. |
| EXIT_CODE = 3 |
| |
| |
| def _die_at_exit(): |
| atexit.register(os._exit, EXIT_CODE) |
| |
| |
| class MethodExitSample(unittest.TestCase): |
| |
| @isolation.runInSubprocess() |
| def test_passes_then_dies(self): |
| _die_at_exit() |
| |
| @isolation.runInSubprocess() |
| def test_fails_and_dies(self): |
| _die_at_exit() |
| self.fail('the test itself failed') |
| |
| |
| @isolation.runInSubprocess() |
| class ClassExitSample(unittest.TestCase): |
| |
| def test_pass(self): |
| pass |
| |
| def test_dies(self): |
| _die_at_exit() |
| |
| |
| @isolation.runInSubprocess(options=['-X', 'dev', '-W', 'error::BytesWarning']) |
| class OptionsSample(unittest.TestCase): |
| |
| def test_options_applied(self): |
| self.assertTrue(sys.flags.dev_mode) |
| self.assertIn('error::BytesWarning', sys.warnoptions) |
| |
| |
| class EnvSample(unittest.TestCase): |
| |
| @isolation.runInSubprocess(env={'_PYTHON_ISOLATION_PROBE': 'set-by-test'}) |
| def test_env_set(self): |
| self.assertEqual(os.environ.get('_PYTHON_ISOLATION_PROBE'), 'set-by-test') |
| |
| @isolation.runInSubprocess(env={'_PYTHON_ISOLATION_PROBE': None}) |
| def test_env_unset(self): |
| self.assertNotIn('_PYTHON_ISOLATION_PROBE', os.environ) |
| |
| @isolation.runInSubprocess() |
| def test_env_inherited(self): |
| # Without env= the subprocess inherits the parent environment as it is. |
| self.assertEqual(os.environ.get('_PYTHON_ISOLATION_PROBE'), 'set-by-parent') |
| |
| |
| # TimeoutSample hangs this long, so that the timeout always fires first. |
| TIMEOUT_HANG = 60.0 |
| TIMEOUT = 0.5 |
| |
| |
| class TimeoutSample(unittest.TestCase): |
| |
| @isolation.runInSubprocess(timeout=TIMEOUT) |
| def test_hang(self): |
| time.sleep(TIMEOUT_HANG) |
| |
| |
| class BigmemSample(unittest.TestCase): |
| |
| @support.bigmemtest(size=1024, memuse=1) |
| def test_where_it_runs(self, size): |
| # A real run is isolated by bigmemtest() itself, a dummy run is not. |
| self.assertEqual(isolation.runningInSubprocess, |
| bool(support.real_max_memuse)) |