OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import unittest |
| 6 |
| 7 from .type_definitions import Test, Result, MultiTest, FuncCall, Bind |
| 8 |
| 9 |
| 10 def _SetUpClass(test_class): |
| 11 inst = test_class('__init__') |
| 12 inst.setUpClass() |
| 13 return inst |
| 14 |
| 15 |
| 16 def _TearDownClass(test_class_inst): |
| 17 test_class_inst.tearDownClass() |
| 18 |
| 19 |
| 20 def _RunTestCaseSingle(test_case, test_name, test_instance=None): |
| 21 # The hack is so that unittest.TestCase has something to pretend is the |
| 22 # test method without the BS of wrapping each method in a new TestCase |
| 23 # class... |
| 24 test_instance = test_instance or test_case('__init__') |
| 25 test_instance.setUp() |
| 26 try: |
| 27 return Result(getattr(test_instance, test_name)()) |
| 28 finally: |
| 29 test_instance.tearDown() |
| 30 |
| 31 |
| 32 def UnittestTestCase(test_case, name_prefix='', ext='json'): |
| 33 """Yield a MultiTest or multiple Test instances for the unittest.TestCase |
| 34 derived |test_case|. |
| 35 |
| 36 If the TestCase has a field `__expect_tests_serial__` defined to be True, then |
| 37 all test methods in the TestCase will be guaranteed to run in a single process |
| 38 with the same instance. This is automatically set to True if your test class |
| 39 relies on setUpClass/tearDownClass. |
| 40 |
| 41 If the TestCase has a field `__expect_tests_atomic__` defined to be True, then |
| 42 in the event of a test filter which matches any test method in |test_case|, |
| 43 the ENTIRE |test_case| will be executed (i.e. the TestCase has interdependant |
| 44 test methods). This should only need to be set for very poorly designed tests. |
| 45 |
| 46 `__expect_tests_atomic__` implies `__expect_tests_serial__`. |
| 47 |
| 48 @type test_case: unittest.TestCase |
| 49 """ |
| 50 name_prefix = name_prefix + test_case.__name__ |
| 51 def _tests_from_class(cls, *args, **kwargs): |
| 52 for test_name in unittest.defaultTestLoader.getTestCaseNames(cls): |
| 53 yield Test( |
| 54 name_prefix + '.' + test_name, |
| 55 FuncCall(_RunTestCaseSingle, cls, test_name, *args, **kwargs), |
| 56 ext=ext, break_funcs=[getattr(cls, test_name)], |
| 57 ) |
| 58 |
| 59 if hasattr(test_case, '__expect_tests_serial__'): |
| 60 serial = getattr(test_case, '__expect_tests_serial__', False) |
| 61 else: |
| 62 default_setup = unittest.TestCase.setUpClass.im_func |
| 63 default_teardown = unittest.TestCase.tearDownClass.im_func |
| 64 serial = ( |
| 65 test_case.setUpClass.im_func is not default_setup or |
| 66 test_case.tearDownClass.im_func is not default_teardown) |
| 67 |
| 68 atomic = getattr(test_case, '__expect_tests_atomic__', False) |
| 69 if atomic or serial: |
| 70 yield MultiTest( |
| 71 name_prefix, |
| 72 FuncCall(_SetUpClass, test_case), |
| 73 FuncCall(_TearDownClass, Bind(name='context')), |
| 74 list(_tests_from_class(test_case, test_instance=Bind(name='context'))), |
| 75 atomic |
| 76 ) |
| 77 else: |
| 78 for test in _tests_from_class(test_case): |
| 79 yield test |
| 80 |
| 81 |
| 82 def UnitTestModule(test_module, name_prefix='', ext='json'): |
| 83 """Yield MultiTest's and/or Test's for the python module |test_module| which |
| 84 contains zero or more unittest.TestCase implementations. |
| 85 |
| 86 @type test_module: types.ModuleType |
| 87 """ |
| 88 name_prefix = name_prefix + test_module.__name__ + '.' |
| 89 for name in dir(test_module): |
| 90 obj = getattr(test_module, name) |
| 91 if isinstance(obj, type) and issubclass(obj, unittest.TestCase): |
| 92 for test in UnittestTestCase(obj, name_prefix, ext): |
| 93 yield test |
| 94 # TODO(iannucci): Make this compatible with the awful load_tests hack? |
OLD | NEW |