1. import unittest
    
  2. from io import StringIO
    
  3. from unittest import mock
    
  4. from unittest.suite import _DebugResult
    
  5. 
    
  6. from django.test import SimpleTestCase
    
  7. 
    
  8. 
    
  9. class ErrorTestCase(SimpleTestCase):
    
  10.     def raising_test(self):
    
  11.         self._pre_setup.assert_called_once_with()
    
  12.         raise Exception("debug() bubbles up exceptions before cleanup.")
    
  13. 
    
  14.     def simple_test(self):
    
  15.         self._pre_setup.assert_called_once_with()
    
  16. 
    
  17.     @unittest.skip("Skip condition.")
    
  18.     def skipped_test(self):
    
  19.         pass
    
  20. 
    
  21. 
    
  22. @mock.patch.object(ErrorTestCase, "_post_teardown")
    
  23. @mock.patch.object(ErrorTestCase, "_pre_setup")
    
  24. class DebugInvocationTests(SimpleTestCase):
    
  25.     def get_runner(self):
    
  26.         return unittest.TextTestRunner(stream=StringIO())
    
  27. 
    
  28.     def isolate_debug_test(self, test_suite, result):
    
  29.         # Suite teardown needs to be manually called to isolate failures.
    
  30.         test_suite._tearDownPreviousClass(None, result)
    
  31.         test_suite._handleModuleTearDown(result)
    
  32. 
    
  33.     def test_run_cleanup(self, _pre_setup, _post_teardown):
    
  34.         """Simple test run: catches errors and runs cleanup."""
    
  35.         test_suite = unittest.TestSuite()
    
  36.         test_suite.addTest(ErrorTestCase("raising_test"))
    
  37.         result = self.get_runner()._makeResult()
    
  38.         self.assertEqual(result.errors, [])
    
  39.         test_suite.run(result)
    
  40.         self.assertEqual(len(result.errors), 1)
    
  41.         _, traceback = result.errors[0]
    
  42.         self.assertIn(
    
  43.             "Exception: debug() bubbles up exceptions before cleanup.", traceback
    
  44.         )
    
  45.         _pre_setup.assert_called_once_with()
    
  46.         _post_teardown.assert_called_once_with()
    
  47. 
    
  48.     def test_run_pre_setup_error(self, _pre_setup, _post_teardown):
    
  49.         _pre_setup.side_effect = Exception("Exception in _pre_setup.")
    
  50.         test_suite = unittest.TestSuite()
    
  51.         test_suite.addTest(ErrorTestCase("simple_test"))
    
  52.         result = self.get_runner()._makeResult()
    
  53.         self.assertEqual(result.errors, [])
    
  54.         test_suite.run(result)
    
  55.         self.assertEqual(len(result.errors), 1)
    
  56.         _, traceback = result.errors[0]
    
  57.         self.assertIn("Exception: Exception in _pre_setup.", traceback)
    
  58.         # pre-setup is called but not post-teardown.
    
  59.         _pre_setup.assert_called_once_with()
    
  60.         self.assertFalse(_post_teardown.called)
    
  61. 
    
  62.     def test_run_post_teardown_error(self, _pre_setup, _post_teardown):
    
  63.         _post_teardown.side_effect = Exception("Exception in _post_teardown.")
    
  64.         test_suite = unittest.TestSuite()
    
  65.         test_suite.addTest(ErrorTestCase("simple_test"))
    
  66.         result = self.get_runner()._makeResult()
    
  67.         self.assertEqual(result.errors, [])
    
  68.         test_suite.run(result)
    
  69.         self.assertEqual(len(result.errors), 1)
    
  70.         _, traceback = result.errors[0]
    
  71.         self.assertIn("Exception: Exception in _post_teardown.", traceback)
    
  72.         # pre-setup and post-teardwn are called.
    
  73.         _pre_setup.assert_called_once_with()
    
  74.         _post_teardown.assert_called_once_with()
    
  75. 
    
  76.     def test_run_skipped_test_no_cleanup(self, _pre_setup, _post_teardown):
    
  77.         test_suite = unittest.TestSuite()
    
  78.         test_suite.addTest(ErrorTestCase("skipped_test"))
    
  79.         try:
    
  80.             test_suite.run(self.get_runner()._makeResult())
    
  81.         except unittest.SkipTest:
    
  82.             self.fail("SkipTest should not be raised at this stage.")
    
  83.         self.assertFalse(_post_teardown.called)
    
  84.         self.assertFalse(_pre_setup.called)
    
  85. 
    
  86.     def test_debug_cleanup(self, _pre_setup, _post_teardown):
    
  87.         """Simple debug run without errors."""
    
  88.         test_suite = unittest.TestSuite()
    
  89.         test_suite.addTest(ErrorTestCase("simple_test"))
    
  90.         test_suite.debug()
    
  91.         _pre_setup.assert_called_once_with()
    
  92.         _post_teardown.assert_called_once_with()
    
  93. 
    
  94.     def test_debug_bubbles_error(self, _pre_setup, _post_teardown):
    
  95.         """debug() bubbles up exceptions before cleanup."""
    
  96.         test_suite = unittest.TestSuite()
    
  97.         test_suite.addTest(ErrorTestCase("raising_test"))
    
  98.         msg = "debug() bubbles up exceptions before cleanup."
    
  99.         with self.assertRaisesMessage(Exception, msg):
    
  100.             # This is the same as test_suite.debug().
    
  101.             result = _DebugResult()
    
  102.             test_suite.run(result, debug=True)
    
  103.         # pre-setup is called but not post-teardown.
    
  104.         _pre_setup.assert_called_once_with()
    
  105.         self.assertFalse(_post_teardown.called)
    
  106.         self.isolate_debug_test(test_suite, result)
    
  107. 
    
  108.     def test_debug_bubbles_pre_setup_error(self, _pre_setup, _post_teardown):
    
  109.         """debug() bubbles up exceptions during _pre_setup."""
    
  110.         msg = "Exception in _pre_setup."
    
  111.         _pre_setup.side_effect = Exception(msg)
    
  112.         test_suite = unittest.TestSuite()
    
  113.         test_suite.addTest(ErrorTestCase("simple_test"))
    
  114.         with self.assertRaisesMessage(Exception, msg):
    
  115.             # This is the same as test_suite.debug().
    
  116.             result = _DebugResult()
    
  117.             test_suite.run(result, debug=True)
    
  118.         # pre-setup is called but not post-teardown.
    
  119.         _pre_setup.assert_called_once_with()
    
  120.         self.assertFalse(_post_teardown.called)
    
  121.         self.isolate_debug_test(test_suite, result)
    
  122. 
    
  123.     def test_debug_bubbles_post_teardown_error(self, _pre_setup, _post_teardown):
    
  124.         """debug() bubbles up exceptions during _post_teardown."""
    
  125.         msg = "Exception in _post_teardown."
    
  126.         _post_teardown.side_effect = Exception(msg)
    
  127.         test_suite = unittest.TestSuite()
    
  128.         test_suite.addTest(ErrorTestCase("simple_test"))
    
  129.         with self.assertRaisesMessage(Exception, msg):
    
  130.             # This is the same as test_suite.debug().
    
  131.             result = _DebugResult()
    
  132.             test_suite.run(result, debug=True)
    
  133.         # pre-setup and post-teardwn are called.
    
  134.         _pre_setup.assert_called_once_with()
    
  135.         _post_teardown.assert_called_once_with()
    
  136.         self.isolate_debug_test(test_suite, result)
    
  137. 
    
  138.     def test_debug_skipped_test_no_cleanup(self, _pre_setup, _post_teardown):
    
  139.         test_suite = unittest.TestSuite()
    
  140.         test_suite.addTest(ErrorTestCase("skipped_test"))
    
  141.         with self.assertRaisesMessage(unittest.SkipTest, "Skip condition."):
    
  142.             # This is the same as test_suite.debug().
    
  143.             result = _DebugResult()
    
  144.             test_suite.run(result, debug=True)
    
  145.         self.assertFalse(_post_teardown.called)
    
  146.         self.assertFalse(_pre_setup.called)
    
  147.         self.isolate_debug_test(test_suite, result)