340 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			340 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (c) 2009-2011 testtools developers. See LICENSE for details.
 | 
						|
 | 
						|
"""Tests for the RunTest single test execution logic."""
 | 
						|
 | 
						|
from testtools import (
 | 
						|
    ExtendedToOriginalDecorator,
 | 
						|
    run_test_with,
 | 
						|
    RunTest,
 | 
						|
    TestCase,
 | 
						|
    TestResult,
 | 
						|
    )
 | 
						|
from testtools.matchers import HasLength, MatchesException, Is, Raises
 | 
						|
from testtools.testresult.doubles import ExtendedTestResult
 | 
						|
from testtools.tests.helpers import FullStackRunTest
 | 
						|
 | 
						|
 | 
						|
class TestRunTest(TestCase):
 | 
						|
 | 
						|
    run_tests_with = FullStackRunTest
 | 
						|
 | 
						|
    def make_case(self):
 | 
						|
        class Case(TestCase):
 | 
						|
            def test(self):
 | 
						|
                pass
 | 
						|
        return Case('test')
 | 
						|
 | 
						|
    def test___init___short(self):
 | 
						|
        run = RunTest("bar")
 | 
						|
        self.assertEqual("bar", run.case)
 | 
						|
        self.assertEqual([], run.handlers)
 | 
						|
 | 
						|
    def test__init____handlers(self):
 | 
						|
        handlers = [("quux", "baz")]
 | 
						|
        run = RunTest("bar", handlers)
 | 
						|
        self.assertEqual(handlers, run.handlers)
 | 
						|
 | 
						|
    def test__init____handlers_last_resort(self):
 | 
						|
        handlers = [("quux", "baz")]
 | 
						|
        last_resort = "foo"
 | 
						|
        run = RunTest("bar", handlers, last_resort)
 | 
						|
        self.assertEqual(last_resort, run.last_resort)
 | 
						|
 | 
						|
    def test_run_with_result(self):
 | 
						|
        # test.run passes result down to _run_test_method.
 | 
						|
        log = []
 | 
						|
        class Case(TestCase):
 | 
						|
            def _run_test_method(self, result):
 | 
						|
                log.append(result)
 | 
						|
        case = Case('_run_test_method')
 | 
						|
        run = RunTest(case, lambda x: log.append(x))
 | 
						|
        result = TestResult()
 | 
						|
        run.run(result)
 | 
						|
        self.assertEqual(1, len(log))
 | 
						|
        self.assertEqual(result, log[0].decorated)
 | 
						|
 | 
						|
    def test_run_no_result_manages_new_result(self):
 | 
						|
        log = []
 | 
						|
        run = RunTest(self.make_case(), lambda x: log.append(x) or x)
 | 
						|
        result = run.run()
 | 
						|
        self.assertIsInstance(result.decorated, TestResult)
 | 
						|
 | 
						|
    def test__run_core_called(self):
 | 
						|
        case = self.make_case()
 | 
						|
        log = []
 | 
						|
        run = RunTest(case, lambda x: x)
 | 
						|
        run._run_core = lambda: log.append('foo')
 | 
						|
        run.run()
 | 
						|
        self.assertEqual(['foo'], log)
 | 
						|
 | 
						|
    def test__run_prepared_result_does_not_mask_keyboard(self):
 | 
						|
        tearDownRuns = []
 | 
						|
        class Case(TestCase):
 | 
						|
            def test(self):
 | 
						|
                raise KeyboardInterrupt("go")
 | 
						|
            def _run_teardown(self, result):
 | 
						|
                tearDownRuns.append(self)
 | 
						|
                return super(Case, self)._run_teardown(result)
 | 
						|
        case = Case('test')
 | 
						|
        run = RunTest(case)
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        self.assertThat(lambda: run._run_prepared_result(run.result),
 | 
						|
            Raises(MatchesException(KeyboardInterrupt)))
 | 
						|
        self.assertEqual(
 | 
						|
            [('startTest', case), ('stopTest', case)], run.result._events)
 | 
						|
        # tearDown is still run though!
 | 
						|
        self.assertThat(tearDownRuns, HasLength(1))
 | 
						|
 | 
						|
    def test__run_user_calls_onException(self):
 | 
						|
        case = self.make_case()
 | 
						|
        log = []
 | 
						|
        def handler(exc_info):
 | 
						|
            log.append("got it")
 | 
						|
            self.assertEqual(3, len(exc_info))
 | 
						|
            self.assertIsInstance(exc_info[1], KeyError)
 | 
						|
            self.assertIs(KeyError, exc_info[0])
 | 
						|
        case.addOnException(handler)
 | 
						|
        e = KeyError('Yo')
 | 
						|
        def raises():
 | 
						|
            raise e
 | 
						|
        run = RunTest(case, [(KeyError, None)])
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        status = run._run_user(raises)
 | 
						|
        self.assertEqual(run.exception_caught, status)
 | 
						|
        self.assertEqual([], run.result._events)
 | 
						|
        self.assertEqual(["got it"], log)
 | 
						|
 | 
						|
    def test__run_user_can_catch_Exception(self):
 | 
						|
        case = self.make_case()
 | 
						|
        e = Exception('Yo')
 | 
						|
        def raises():
 | 
						|
            raise e
 | 
						|
        log = []
 | 
						|
        run = RunTest(case, [(Exception, None)])
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        status = run._run_user(raises)
 | 
						|
        self.assertEqual(run.exception_caught, status)
 | 
						|
        self.assertEqual([], run.result._events)
 | 
						|
        self.assertEqual([], log)
 | 
						|
 | 
						|
    def test__run_prepared_result_uncaught_Exception_raised(self):
 | 
						|
        e = KeyError('Yo')
 | 
						|
        class Case(TestCase):
 | 
						|
            def test(self):
 | 
						|
                raise e
 | 
						|
        case = Case('test')
 | 
						|
        log = []
 | 
						|
        def log_exc(self, result, err):
 | 
						|
            log.append((result, err))
 | 
						|
        run = RunTest(case, [(ValueError, log_exc)])
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        self.assertThat(lambda: run._run_prepared_result(run.result),
 | 
						|
            Raises(MatchesException(KeyError)))
 | 
						|
        self.assertEqual(
 | 
						|
            [('startTest', case), ('stopTest', case)], run.result._events)
 | 
						|
        self.assertEqual([], log)
 | 
						|
 | 
						|
    def test__run_prepared_result_uncaught_Exception_triggers_error(self):
 | 
						|
        # https://bugs.launchpad.net/testtools/+bug/1364188
 | 
						|
        # When something isn't handled, the test that was
 | 
						|
        # executing has errored, one way or another.
 | 
						|
        e = SystemExit(0)
 | 
						|
        class Case(TestCase):
 | 
						|
            def test(self):
 | 
						|
                raise e
 | 
						|
        case = Case('test')
 | 
						|
        log = []
 | 
						|
        def log_exc(self, result, err):
 | 
						|
            log.append((result, err))
 | 
						|
        run = RunTest(case, [], log_exc)
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        self.assertThat(lambda: run._run_prepared_result(run.result),
 | 
						|
            Raises(MatchesException(SystemExit)))
 | 
						|
        self.assertEqual(
 | 
						|
            [('startTest', case), ('stopTest', case)], run.result._events)
 | 
						|
        self.assertEqual([(run.result, e)], log)
 | 
						|
 | 
						|
    def test__run_user_uncaught_Exception_from_exception_handler_raised(self):
 | 
						|
        case = self.make_case()
 | 
						|
        def broken_handler(exc_info):
 | 
						|
            # ValueError because thats what we know how to catch - and must
 | 
						|
            # not.
 | 
						|
            raise ValueError('boo')
 | 
						|
        case.addOnException(broken_handler)
 | 
						|
        e = KeyError('Yo')
 | 
						|
        def raises():
 | 
						|
            raise e
 | 
						|
        log = []
 | 
						|
        def log_exc(self, result, err):
 | 
						|
            log.append((result, err))
 | 
						|
        run = RunTest(case, [(ValueError, log_exc)])
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        self.assertThat(lambda: run._run_user(raises),
 | 
						|
            Raises(MatchesException(ValueError)))
 | 
						|
        self.assertEqual([], run.result._events)
 | 
						|
        self.assertEqual([], log)
 | 
						|
 | 
						|
    def test__run_user_returns_result(self):
 | 
						|
        case = self.make_case()
 | 
						|
        def returns():
 | 
						|
            return 1
 | 
						|
        run = RunTest(case)
 | 
						|
        run.result = ExtendedTestResult()
 | 
						|
        self.assertEqual(1, run._run_user(returns))
 | 
						|
        self.assertEqual([], run.result._events)
 | 
						|
 | 
						|
    def test__run_one_decorates_result(self):
 | 
						|
        log = []
 | 
						|
        class Run(RunTest):
 | 
						|
            def _run_prepared_result(self, result):
 | 
						|
                log.append(result)
 | 
						|
                return result
 | 
						|
        run = Run(self.make_case(), lambda x: x)
 | 
						|
        result = run._run_one('foo')
 | 
						|
        self.assertEqual([result], log)
 | 
						|
        self.assertIsInstance(log[0], ExtendedToOriginalDecorator)
 | 
						|
        self.assertEqual('foo', result.decorated)
 | 
						|
 | 
						|
    def test__run_prepared_result_calls_start_and_stop_test(self):
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        case = self.make_case()
 | 
						|
        run = RunTest(case, lambda x: x)
 | 
						|
        run.run(result)
 | 
						|
        self.assertEqual([
 | 
						|
            ('startTest', case),
 | 
						|
            ('addSuccess', case),
 | 
						|
            ('stopTest', case),
 | 
						|
            ], result._events)
 | 
						|
 | 
						|
    def test__run_prepared_result_calls_stop_test_always(self):
 | 
						|
        result = ExtendedTestResult()
 | 
						|
        case = self.make_case()
 | 
						|
        def inner():
 | 
						|
            raise Exception("foo")
 | 
						|
        run = RunTest(case, lambda x: x)
 | 
						|
        run._run_core = inner
 | 
						|
        self.assertThat(lambda: run.run(result),
 | 
						|
            Raises(MatchesException(Exception("foo"))))
 | 
						|
        self.assertEqual([
 | 
						|
            ('startTest', case),
 | 
						|
            ('stopTest', case),
 | 
						|
            ], result._events)
 | 
						|
 | 
						|
 | 
						|
class CustomRunTest(RunTest):
 | 
						|
 | 
						|
    marker = object()
 | 
						|
 | 
						|
    def run(self, result=None):
 | 
						|
        return self.marker
 | 
						|
 | 
						|
 | 
						|
class TestTestCaseSupportForRunTest(TestCase):
 | 
						|
 | 
						|
    def test_pass_custom_run_test(self):
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo', runTest=CustomRunTest)
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(CustomRunTest.marker))
 | 
						|
 | 
						|
    def test_default_is_runTest_class_variable(self):
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            run_tests_with = CustomRunTest
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo')
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(CustomRunTest.marker))
 | 
						|
 | 
						|
    def test_constructor_argument_overrides_class_variable(self):
 | 
						|
        # If a 'runTest' argument is passed to the test's constructor, that
 | 
						|
        # overrides the class variable.
 | 
						|
        marker = object()
 | 
						|
        class DifferentRunTest(RunTest):
 | 
						|
            def run(self, result=None):
 | 
						|
                return marker
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            run_tests_with = CustomRunTest
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo', runTest=DifferentRunTest)
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(marker))
 | 
						|
 | 
						|
    def test_decorator_for_run_test(self):
 | 
						|
        # Individual test methods can be marked as needing a special runner.
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            @run_test_with(CustomRunTest)
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo')
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(CustomRunTest.marker))
 | 
						|
 | 
						|
    def test_extended_decorator_for_run_test(self):
 | 
						|
        # Individual test methods can be marked as needing a special runner.
 | 
						|
        # Extra arguments can be passed to the decorator which will then be
 | 
						|
        # passed on to the RunTest object.
 | 
						|
        marker = object()
 | 
						|
        class FooRunTest(RunTest):
 | 
						|
            def __init__(self, case, handlers=None, bar=None):
 | 
						|
                super(FooRunTest, self).__init__(case, handlers)
 | 
						|
                self.bar = bar
 | 
						|
            def run(self, result=None):
 | 
						|
                return self.bar
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            @run_test_with(FooRunTest, bar=marker)
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo')
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(marker))
 | 
						|
 | 
						|
    def test_works_as_inner_decorator(self):
 | 
						|
        # Even if run_test_with is the innermost decorator, it will be
 | 
						|
        # respected.
 | 
						|
        def wrapped(function):
 | 
						|
            """Silly, trivial decorator."""
 | 
						|
            def decorated(*args, **kwargs):
 | 
						|
                return function(*args, **kwargs)
 | 
						|
            decorated.__name__ = function.__name__
 | 
						|
            decorated.__dict__.update(function.__dict__)
 | 
						|
            return decorated
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            @wrapped
 | 
						|
            @run_test_with(CustomRunTest)
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo')
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(CustomRunTest.marker))
 | 
						|
 | 
						|
    def test_constructor_overrides_decorator(self):
 | 
						|
        # If a 'runTest' argument is passed to the test's constructor, that
 | 
						|
        # overrides the decorator.
 | 
						|
        marker = object()
 | 
						|
        class DifferentRunTest(RunTest):
 | 
						|
            def run(self, result=None):
 | 
						|
                return marker
 | 
						|
        class SomeCase(TestCase):
 | 
						|
            @run_test_with(CustomRunTest)
 | 
						|
            def test_foo(self):
 | 
						|
                pass
 | 
						|
        result = TestResult()
 | 
						|
        case = SomeCase('test_foo', runTest=DifferentRunTest)
 | 
						|
        from_run_test = case.run(result)
 | 
						|
        self.assertThat(from_run_test, Is(marker))
 | 
						|
 | 
						|
 | 
						|
def test_suite():
 | 
						|
    from unittest import TestLoader
 | 
						|
    return TestLoader().loadTestsFromName(__name__)
 |