OLD | NEW |
1 # Copyright 2014 Dirk Pranke. All rights reserved. | 1 # Copyright 2014 Dirk Pranke. All rights reserved. |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 pass | 152 pass |
153 | 153 |
154 setattr(BaseTest, "test_fail", method_fail) | 154 setattr(BaseTest, "test_fail", method_fail) |
155 setattr(BaseTest, "test_pass", method_pass) | 155 setattr(BaseTest, "test_pass", method_pass) |
156 suite = unittest.TestSuite() | 156 suite = unittest.TestSuite() |
157 suite.addTest(BaseTest("test_fail")) | 157 suite.addTest(BaseTest("test_fail")) |
158 suite.addTest(BaseTest("test_pass")) | 158 suite.addTest(BaseTest("test_pass")) |
159 return suite | 159 return suite |
160 """ | 160 """ |
161 | 161 |
| 162 LOAD_TEST_FILES = {'load_test.py': LOAD_TEST_PY} |
162 | 163 |
163 LOAD_TEST_FILES = {'load_test.py': LOAD_TEST_PY} | 164 |
| 165 MIXED_TEST_PY = """ |
| 166 import unittest |
| 167 class SampleTest(unittest.TestCase): |
| 168 |
| 169 def test_pass_0(self): |
| 170 self.assertEqual(1, 1) |
| 171 |
| 172 def test_pass_1(self): |
| 173 self.assertEqual(1, 1) |
| 174 |
| 175 def test_fail_0(self): |
| 176 self.assertEqual(1, 2) |
| 177 |
| 178 def test_fail_1(self): |
| 179 raise Exception() |
| 180 |
| 181 @unittest.skip('Skip for no reason') |
| 182 def test_skip_0(self): |
| 183 pass |
| 184 """ |
| 185 |
| 186 |
| 187 LOAD_MANY_TEST_PY = """ |
| 188 import unittest |
| 189 |
| 190 def generate_test_case(test_method_name, test_type): |
| 191 class GeneratedTest(unittest.TestCase): |
| 192 pass |
| 193 |
| 194 if test_type == 'pass': |
| 195 def test_method(self): |
| 196 self.assertEqual(1, 1) |
| 197 elif test_type == 'fail': |
| 198 def test_method(self): |
| 199 self.assertEqual(1, 2) |
| 200 elif test_type == 'skip': |
| 201 def test_method(self): |
| 202 self.skipTest('Skipped') |
| 203 else: |
| 204 raise Exception |
| 205 |
| 206 setattr(GeneratedTest, test_method_name, test_method) |
| 207 return GeneratedTest(test_method_name) |
| 208 |
| 209 |
| 210 def load_tests(loader, standard_tests, pattern): |
| 211 del loader, standard_tests, pattern # unused |
| 212 |
| 213 suite = unittest.TestSuite() |
| 214 |
| 215 passed_test_names = [ |
| 216 str('test_pass_%s' % i) for i in range(2, 15)] |
| 217 |
| 218 failed_test_names = [ |
| 219 str('test_fail_%s' % i) for i in range(2, 10)] |
| 220 |
| 221 skipped_test_names = [ |
| 222 str('test_skip_%s' % i) for i in range(1, 10)] |
| 223 |
| 224 for test_method_name in passed_test_names: |
| 225 suite.addTest(generate_test_case(test_method_name, 'pass')) |
| 226 |
| 227 for test_method_name in failed_test_names: |
| 228 suite.addTest(generate_test_case(test_method_name, 'fail')) |
| 229 |
| 230 for test_method_name in skipped_test_names: |
| 231 suite.addTest(generate_test_case(test_method_name, 'skip')) |
| 232 |
| 233 return suite |
| 234 """ |
| 235 |
| 236 |
| 237 MANY_TEST_FILES = { |
| 238 'mixed_test.py': MIXED_TEST_PY, # 2 passes, 2 fails, 1 skip |
| 239 'load_many_test.py': LOAD_MANY_TEST_PY} # 13 passes, 13 fails, 9 skips |
164 | 240 |
165 | 241 |
166 path_to_main = os.path.join( | 242 path_to_main = os.path.join( |
167 os.path.dirname(os.path.dirname(os.path.abspath(__file__))), | 243 os.path.dirname(os.path.dirname(os.path.abspath(__file__))), |
168 'runner.py') | 244 'runner.py') |
169 | 245 |
170 | 246 |
171 class TestCli(test_case.MainTestCase): | 247 class TestCli(test_case.MainTestCase): |
172 prog = [sys.executable, path_to_main] | 248 prog = [sys.executable, path_to_main] |
173 files_to_ignore = ['*.pyc'] | 249 files_to_ignore = ['*.pyc'] |
174 | 250 |
| 251 def get_test_results_stat(self, test_output): |
| 252 num_passes = test_output.count(' passed\n') |
| 253 num_fails = test_output.count(' failed unexpectedly:\n') |
| 254 num_skips = test_output.count(' was skipped\n') |
| 255 return num_passes, num_fails, num_skips |
| 256 |
| 257 def run_and_check_test_results(self, num_shards): |
| 258 total_passes, total_fails, total_skips = 0, 0, 0 |
| 259 min_num_tests_run = float('inf') |
| 260 max_num_tests_run = 0 |
| 261 for shard_index in range(num_shards): |
| 262 _, out, _, _ = self.check( |
| 263 ['--total-shards', str(num_shards), '--shard-index', |
| 264 str(shard_index)], files=MANY_TEST_FILES) |
| 265 passes, fails, skips = self.get_test_results_stat(out) |
| 266 total_passes += passes |
| 267 total_fails += fails |
| 268 total_skips += skips |
| 269 num_tests_run = passes + fails |
| 270 min_num_tests_run = min(min_num_tests_run, num_tests_run) |
| 271 max_num_tests_run = max(max_num_tests_run, num_tests_run) |
| 272 self.assertEqual(total_passes, 15) |
| 273 self.assertEqual(total_fails, 10) |
| 274 self.assertEqual(total_skips, 10) |
| 275 |
| 276 # Make sure that we don't distribute the tests too unevenly. |
| 277 self.assertLessEqual(max_num_tests_run - min_num_tests_run, 2) |
| 278 |
175 def test_bad_arg(self): | 279 def test_bad_arg(self): |
176 self.check(['--bad-arg'], ret=2, out='', | 280 self.check(['--bad-arg'], ret=2, out='', |
177 rerr='.*: error: unrecognized arguments: --bad-arg\n') | 281 rerr='.*: error: unrecognized arguments: --bad-arg\n') |
178 self.check(['-help'], ret=2, out='', | 282 self.check(['-help'], ret=2, out='', |
179 rerr=(".*: error: argument -h/--help: " | 283 rerr=(".*: error: argument -h/--help: " |
180 "ignored explicit argument 'elp'\n")) | 284 "ignored explicit argument 'elp'\n")) |
181 | 285 |
182 def test_bad_metadata(self): | 286 def test_bad_metadata(self): |
183 self.check(['--metadata', 'foo'], ret=2, err='', | 287 self.check(['--metadata', 'foo'], ret=2, err='', |
184 out='Error: malformed --metadata "foo"\n') | 288 out='Error: malformed --metadata "foo"\n') |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 files=SF_TEST_FILES, ret=1, err='') | 624 files=SF_TEST_FILES, ret=1, err='') |
521 self.assertIn('sf_test.SkipClass.test_method failed', out) | 625 self.assertIn('sf_test.SkipClass.test_method failed', out) |
522 self.assertIn('sf_test.SkipMethods.test_reason failed', out) | 626 self.assertIn('sf_test.SkipMethods.test_reason failed', out) |
523 self.assertIn('sf_test.SkipMethods.test_skip_if_true failed', out) | 627 self.assertIn('sf_test.SkipMethods.test_skip_if_true failed', out) |
524 self.assertIn('sf_test.SkipMethods.test_skip_if_false failed', out) | 628 self.assertIn('sf_test.SkipMethods.test_skip_if_false failed', out) |
525 | 629 |
526 # --all does not override explicit calls to skipTest(), only | 630 # --all does not override explicit calls to skipTest(), only |
527 # the decorators. | 631 # the decorators. |
528 self.assertIn('sf_test.SkipSetup.test_notrun was skipped', out) | 632 self.assertIn('sf_test.SkipSetup.test_notrun was skipped', out) |
529 | 633 |
| 634 def test_sharding(self): |
| 635 # Test no sharding. |
| 636 self.run_and_check_test_results(1) |
| 637 |
| 638 # A typical with 4 shards. |
| 639 self.run_and_check_test_results(4) |
| 640 |
| 641 # Case which number of shards is a prime. |
| 642 self.run_and_check_test_results(7) |
| 643 |
| 644 # Case which number of shards is more than number of tests. |
| 645 self.run_and_check_test_results(50) |
| 646 |
530 def test_subdir(self): | 647 def test_subdir(self): |
531 files = { | 648 files = { |
532 'foo/__init__.py': '', | 649 'foo/__init__.py': '', |
533 'foo/bar/__init__.py': '', | 650 'foo/bar/__init__.py': '', |
534 'foo/bar/pass_test.py': PASS_TEST_PY | 651 'foo/bar/pass_test.py': PASS_TEST_PY |
535 } | 652 } |
536 self.check(['foo/bar'], files=files, ret=0, err='', | 653 self.check(['foo/bar'], files=files, ret=0, err='', |
537 out=d("""\ | 654 out=d("""\ |
538 [1/1] foo.bar.pass_test.PassingTest.test_pass passed | 655 [1/1] foo.bar.pass_test.PassingTest.test_pass passed |
539 1 test run, 0 failures. | 656 1 test run, 0 failures. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 modules_to_unload.append(k) | 802 modules_to_unload.append(k) |
686 for k in modules_to_unload: | 803 for k in modules_to_unload: |
687 del sys.modules[k] | 804 del sys.modules[k] |
688 sys.path = orig_sys_path | 805 sys.path = orig_sys_path |
689 | 806 |
690 return ret, out, err | 807 return ret, out, err |
691 | 808 |
692 def test_debugger(self): | 809 def test_debugger(self): |
693 # TODO: this test seems to hang under coverage. | 810 # TODO: this test seems to hang under coverage. |
694 pass | 811 pass |
OLD | NEW |