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