Skip to content

Commit

Permalink
Merge pull request #335 from bukzor/systemexit-test
Browse files Browse the repository at this point in the history
fixed exception handling for SystemExit and KeyboardInterrupt, and tests
  • Loading branch information
asottile committed Jul 1, 2016
2 parents 11b5841 + 2a725c4 commit 4737141
Show file tree
Hide file tree
Showing 17 changed files with 85 additions and 35 deletions.
Empty file.
2 changes: 2 additions & 0 deletions examples/keyboardinterrupt/discovery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
""""this example throws KeyboardInterrupt during discovery"""
raise KeyboardInterrupt('fake!')
13 changes: 13 additions & 0 deletions examples/keyboardinterrupt/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""this example throws KeyboardInterrupt during fixture setup"""
import testify as T


class Test(T.TestCase):
def setUp(self):
raise KeyboardInterrupt('fake!')

def test1(self):
pass

def test2(self):
pass
15 changes: 15 additions & 0 deletions examples/keyboardinterrupt/teardown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""this example throws KeyboardInterrupt during fixture teardown"""
import testify as T


class Test(T.TestCase):
@T.setup_teardown
def fixture(self):
yield
raise KeyboardInterrupt('fake!')

def test1(self):
pass

def test2(self):
pass
10 changes: 10 additions & 0 deletions examples/keyboardinterrupt/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""this example throws KeyboardInterrupt during testing"""
import testify as T


class Test(T.TestCase):
def test1(self):
raise KeyboardInterrupt('fake!')

def test2(self):
raise KeyboardInterrupt('fake!')
Empty file added examples/systemexit/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions examples/systemexit/discovery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
""""this example throws SystemExit during discovery"""
import sys
sys.exit('fake!')
8 changes: 8 additions & 0 deletions examples/systemexit/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""this example throws SystemExit during testing"""
import testify as T
import sys


class Test(T.TestCase):
def test(self):
sys.exit('fake!')
2 changes: 1 addition & 1 deletion testify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

from .assertions import *

from .errors import TestifyError
from .exceptions import TestifyError

from .test_case import (
MetaTestCase,
Expand Down
2 changes: 0 additions & 2 deletions testify/errors.py

This file was deleted.

14 changes: 14 additions & 0 deletions testify/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Testify(Exception):
pass


class TestifyError(Testify):
pass


class DiscoveryError(TestifyError):
pass


class Interruption(Testify):
pass
9 changes: 4 additions & 5 deletions testify/test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
from collections import defaultdict
import functools
import inspect
import sys
import types
import unittest

import six

from testify import test_fixtures
from testify.exceptions import Interruption
from testify.utils import class_logger
from testify.test_fixtures import DEPRECATED_FIXTURE_TYPE_MAP
from testify.test_fixtures import TestFixtures
Expand Down Expand Up @@ -303,14 +303,13 @@ def __run_test_methods(self, class_fixture_failures):
for exc_info in fixture_failures:
result.end_in_failure(exc_info)

if result.interrupted:
raise Interruption

# if nothing's gone wrong, it's not about to start
if not result.complete:
result.end_in_success()

except (KeyboardInterrupt, SystemExit):
result.end_in_interruption(sys.exc_info())
raise

finally:
self.fire_event(self.EVENT_ON_COMPLETE_TEST_METHOD, result)

Expand Down
10 changes: 4 additions & 6 deletions testify/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@
import traceback
import unittest
from .test_case import MetaTestCase, TestifiedUnitTest
from .errors import TestifyError


class DiscoveryError(TestifyError):
pass
from .exceptions import DiscoveryError


def to_module(path):
Expand Down Expand Up @@ -97,7 +93,9 @@ def discover(what):
submod = __import__(module_name, fromlist=[str('__trash')])
for cls in get_test_classes_from_module(submod):
yield cls
except Exception:
except GeneratorExit:
raise
except BaseException:
# print the traceback to stderr, or else we can't see errors during --list-tests > testlist
traceback.print_exc()
raise DiscoveryError(
Expand Down
4 changes: 0 additions & 4 deletions testify/test_fixtures.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import contextlib
import inspect
import itertools
import sys

import six

Expand Down Expand Up @@ -193,9 +192,6 @@ def run_fixture(self, fixture, function_to_call, enter_callback=None, exit_callb
result.end_in_success()
else:
return result.exception_infos
except (KeyboardInterrupt, SystemExit):
result.end_in_interruption(sys.exc_info())
raise
finally:
if exit_callback:
exit_callback(result)
Expand Down
9 changes: 4 additions & 5 deletions testify/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,14 @@ def report_test_result(self, result):
}[status]

if status in ('fail', 'error'):
self.writeln("%s: %s\n%s" % (status, self._format_test_method_name(result['method']), result['exception_info']))
self.writeln("\n%s: %s\n%s" % (status, self._format_test_method_name(result['method']), result['exception_info']))

if self.options.verbosity == VERBOSITY_NORMAL:
self.write(self._colorize(status_letter, color))
elif result['normalized_run_time']:
self.writeln("%s in %s" % (self._colorize(status_description, color), result['normalized_run_time']))
else:
if result['normalized_run_time']:
self.writeln("%s in %s" % (self._colorize(status_description, color), result['normalized_run_time']))
else:
self.writeln(self._colorize(status_description, color))
self.writeln(self._colorize(status_description, color))

def heading(self, *messages):
self.writeln("")
Expand Down
12 changes: 3 additions & 9 deletions testify/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ def record(self, function):
"""
try:
function()
except (KeyboardInterrupt, SystemExit):
raise
except Exception as exception:
except BaseException as exception:
# some code may want to use an alternative exc_info for an exception
# (for instance, in an event loop). You can signal an alternative
# stack to use by adding a _testify_exc_tb attribute to the
Expand Down Expand Up @@ -125,6 +123,8 @@ def end_in_failure(self, exception_info):
if isinstance(exception_info[1], AssertionError):
# test failure, kinda expect these vs. unknown errors
self.failure = True
elif isinstance(exception_info[1], KeyboardInterrupt):
self.interrupted = True
else:
self.error = True

Expand All @@ -135,12 +135,6 @@ def end_in_success(self):
self._complete()
self.success = True

def end_in_interruption(self, exception_info):
if not self.complete:
self._complete()
self.interrupted = True
self.exception_infos.append(exception_info)

def __make_multi_error_message(self, formatter):
result = []
for exception_info in self.exception_infos:
Expand Down
7 changes: 4 additions & 3 deletions testify/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .test_case import MetaTestCase, TestCase
from . import test_discovery
from . import exit
from . import exceptions


__author__ = "Oliver Nicholas <bigo@yelp.com>"
Expand Down Expand Up @@ -172,12 +173,12 @@ def failure_counter(result_dict):
# And we finally execute our finely wrapped test case
runnable()

except test_discovery.DiscoveryError as exc:
except exceptions.DiscoveryError as exc:
for reporter in self.test_reporters:
reporter.test_discovery_failure(exc)
return exit.DISCOVERY_FAILED
except KeyboardInterrupt:
# we'll catch and pass a keyboard interrupt so we can cancel in the middle of a run
except exceptions.Interruption:
# handle interruption so we can cancel in the middle of a run
# but still get a testing summary.
pass

Expand Down

0 comments on commit 4737141

Please sign in to comment.