Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Side by Side Diff: unittests/test_test.py

Issue 2797023002: Always identify test names that lead to failures (Closed)
Patch Set: proto Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « recipe_engine/test_result_pb2.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2017 The LUCI Authors. All rights reserved. 2 # Copyright 2017 The LUCI Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 3 # Use of this source code is governed under the Apache License, Version 2.0
4 # that can be found in the LICENSE file. 4 # that can be found in the LICENSE file.
5 5
6 import json 6 import json
7 import os 7 import os
8 import shutil 8 import shutil
9 import subprocess 9 import subprocess
10 import sys 10 import sys
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 'version': 1, 137 'version': 1,
138 'valid': True, 138 'valid': True,
139 } 139 }
140 140
141 def diff_failure(self, test): 141 def diff_failure(self, test):
142 """Simulates a diff failure for |test|.""" 142 """Simulates a diff failure for |test|."""
143 self._result.setdefault('test_failures', {}).setdefault( 143 self._result.setdefault('test_failures', {}).setdefault(
144 test, {'failures': []})['failures'].append({'diff_failure': {}}) 144 test, {'failures': []})['failures'].append({'diff_failure': {}})
145 return self 145 return self
146 146
147 def internal_failure(self, test):
148 """Simulates an internal failure for |test|."""
149 self._result.setdefault('test_failures', {}).setdefault(
150 test, {'failures': []})['failures'].append({'internal_failure': {}})
151 return self
152
147 def check_failure(self, test, filename, lineno, func, args=None, kwargs=None, 153 def check_failure(self, test, filename, lineno, func, args=None, kwargs=None,
148 name=None): 154 name=None):
149 """Simulates a check failure for |test|. 155 """Simulates a check failure for |test|.
150 156
151 Arguments: 157 Arguments:
152 test(str): name of the test 158 test(str): name of the test
153 filename(str): path where check is introduced 159 filename(str): path where check is introduced
154 lineno(int): line number where check is introduced 160 lineno(int): line number where check is introduced
155 func(str): function/callable name of the check 161 func(str): function/callable name of the check
156 args(list): arguments for |func| 162 args(list): arguments for |func|
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 427
422 def test_test_recipe_syntax_error(self): 428 def test_test_recipe_syntax_error(self):
423 rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') 429 rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo')
424 rw.RunStepsLines = ['baz'] 430 rw.RunStepsLines = ['baz']
425 rw.add_expectation('basic') 431 rw.add_expectation('basic')
426 rw.write() 432 rw.write()
427 with self.assertRaises(subprocess.CalledProcessError) as cm: 433 with self.assertRaises(subprocess.CalledProcessError) as cm:
428 self._run_recipes('test', 'run', '--json', self.json_path) 434 self._run_recipes('test', 'run', '--json', self.json_path)
429 self.assertIn('NameError: global name \'baz\' is not defined', 435 self.assertIn('NameError: global name \'baz\' is not defined',
430 cm.exception.output) 436 cm.exception.output)
431 self.assertFalse(self.json_contents.get('valid')) 437 self.assertEqual(
438 self.json_generator
439 .invalid()
440 .internal_failure('foo.basic')
441 .coverage_failure('recipes/foo.py', [6])
442 .unused_expectation('recipes/foo.expected')
443 .unused_expectation('recipes/foo.expected/basic.json').get(),
444 self.json_contents)
432 445
433 def test_test_recipe_module_uncovered(self): 446 def test_test_recipe_module_uncovered(self):
434 mw = RecipeModuleWriter(self._root_dir, 'foo') 447 mw = RecipeModuleWriter(self._root_dir, 'foo')
435 mw.write() 448 mw.write()
436 with self.assertRaises(subprocess.CalledProcessError) as cm: 449 with self.assertRaises(subprocess.CalledProcessError) as cm:
437 self._run_recipes('test', 'run', '--json', self.json_path) 450 self._run_recipes('test', 'run', '--json', self.json_path)
438 self.assertIn('The following modules lack test coverage: foo', 451 self.assertIn('The following modules lack test coverage: foo',
439 cm.exception.output) 452 cm.exception.output)
440 self.assertEqual(self.json_generator.uncovered_module('foo').get(), 453 self.assertEqual(self.json_generator.uncovered_module('foo').get(),
441 self.json_contents) 454 self.json_contents)
442 455
443 def test_test_recipe_module_syntax_error(self): 456 def test_test_recipe_module_syntax_error(self):
444 mw = RecipeModuleWriter(self._root_dir, 'foo_module') 457 mw = RecipeModuleWriter(self._root_dir, 'foo_module')
445 mw.methods['foo'] = ['baz'] 458 mw.methods['foo'] = ['baz']
446 mw.write() 459 mw.write()
447 mw.example.DEPS = ['foo_module'] 460 mw.example.DEPS = ['foo_module']
448 mw.example.RunStepsLines = ['api.foo_module.foo()'] 461 mw.example.RunStepsLines = ['api.foo_module.foo()']
449 mw.example.write() 462 mw.example.write()
450 with self.assertRaises(subprocess.CalledProcessError) as cm: 463 with self.assertRaises(subprocess.CalledProcessError) as cm:
451 self._run_recipes('test', 'run', '--json', self.json_path) 464 self._run_recipes('test', 'run', '--json', self.json_path)
452 self.assertIn('NameError: global name \'baz\' is not defined', 465 self.assertIn('NameError: global name \'baz\' is not defined',
453 cm.exception.output) 466 cm.exception.output)
454 self.assertIn('FATAL: Insufficient coverage', cm.exception.output) 467 self.assertIn('FATAL: Insufficient coverage', cm.exception.output)
455 self.assertFalse(self.json_contents.get('valid')) 468 self.assertEqual(
469 self.json_generator
470 .invalid()
471 .internal_failure('foo_module:example.basic')
472 .coverage_failure('recipe_modules/foo_module/api.py', [6])
473 .coverage_failure('recipe_modules/foo_module/example.py', [6])
474 .get(),
475 self.json_contents)
456 476
457 def test_test_recipe_module_syntax_error_in_example(self): 477 def test_test_recipe_module_syntax_error_in_example(self):
458 mw = RecipeModuleWriter(self._root_dir, 'foo_module') 478 mw = RecipeModuleWriter(self._root_dir, 'foo_module')
459 mw.methods['foo'] = ['pass'] 479 mw.methods['foo'] = ['pass']
460 mw.write() 480 mw.write()
461 mw.example.DEPS = ['foo_module'] 481 mw.example.DEPS = ['foo_module']
462 mw.example.RunStepsLines = ['baz'] 482 mw.example.RunStepsLines = ['baz']
463 mw.example.write() 483 mw.example.write()
464 with self.assertRaises(subprocess.CalledProcessError) as cm: 484 with self.assertRaises(subprocess.CalledProcessError) as cm:
465 self._run_recipes('test', 'run', '--json', self.json_path) 485 self._run_recipes('test', 'run', '--json', self.json_path)
466 self.assertIn('NameError: global name \'baz\' is not defined', 486 self.assertIn('NameError: global name \'baz\' is not defined',
467 cm.exception.output) 487 cm.exception.output)
468 self.assertIn('FATAL: Insufficient coverage', cm.exception.output) 488 self.assertIn('FATAL: Insufficient coverage', cm.exception.output)
469 self.assertFalse(self.json_contents.get('valid')) 489 self.assertEqual(
490 self.json_generator
491 .invalid()
492 .internal_failure('foo_module:example.basic')
493 .coverage_failure('recipe_modules/foo_module/api.py', [6])
494 .coverage_failure('recipe_modules/foo_module/example.py', [6])
495 .get(),
496 self.json_contents)
470 497
471 def test_test_recipe_module_example_not_covered(self): 498 def test_test_recipe_module_example_not_covered(self):
472 mw = RecipeModuleWriter(self._root_dir, 'foo_module') 499 mw = RecipeModuleWriter(self._root_dir, 'foo_module')
473 mw.methods['foo'] = ['pass'] 500 mw.methods['foo'] = ['pass']
474 mw.write() 501 mw.write()
475 mw.example.DEPS = ['foo_module'] 502 mw.example.DEPS = ['foo_module']
476 mw.example.RunStepsLines = ['if False:', ' pass'] 503 mw.example.RunStepsLines = ['if False:', ' pass']
477 mw.example.write() 504 mw.example.write()
478 with self.assertRaises(subprocess.CalledProcessError) as cm: 505 with self.assertRaises(subprocess.CalledProcessError) as cm:
479 self._run_recipes('test', 'run', '--json', self.json_path) 506 self._run_recipes('test', 'run', '--json', self.json_path)
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 886
860 g1.diff_failure('foo_diff') 887 g1.diff_failure('foo_diff')
861 g2.diff_failure('foo_diff').diff_failure('bar_diff') 888 g2.diff_failure('foo_diff').diff_failure('bar_diff')
862 889
863 g1.check_failure( 890 g1.check_failure(
864 'foo_check', 'foo_file', 1, 'foo_func') 891 'foo_check', 'foo_file', 1, 'foo_func')
865 g2.check_failure( 892 g2.check_failure(
866 'foo_check', 'foo_file', 1, 'foo_func').check_failure( 893 'foo_check', 'foo_file', 1, 'foo_func').check_failure(
867 'bar_check', 'bar_file', 2, 'bar_func', ['bar_args']) 894 'bar_check', 'bar_file', 2, 'bar_func', ['bar_args'])
868 895
896 g1.internal_failure('foo_internal')
897 g2.internal_failure('foo_internal').internal_failure('bar_internal')
898
869 g1.uncovered_module('foo_module') 899 g1.uncovered_module('foo_module')
870 g2.uncovered_module('foo_module').uncovered_module('bar_module') 900 g2.uncovered_module('foo_module').uncovered_module('bar_module')
871 901
872 g1.unused_expectation( 902 g1.unused_expectation(
873 'foo_expectation') 903 'foo_expectation')
874 g2.unused_expectation( 904 g2.unused_expectation(
875 'foo_expectation').unused_expectation('bar_expectation') 905 'foo_expectation').unused_expectation('bar_expectation')
876 906
877 with self.assertRaises(subprocess.CalledProcessError) as cm: 907 with self.assertRaises(subprocess.CalledProcessError) as cm:
878 self._run_recipes( 908 self._run_recipes(
879 'test', 'diff', 909 'test', 'diff',
880 '--baseline', g1.write(), 910 '--baseline', g1.write(),
881 '--actual', g2.write(), 911 '--actual', g2.write(),
882 '--json', self.json_path) 912 '--json', self.json_path)
883 self.assertEqual( 913 self.assertEqual(
884 self.json_generator 914 self.json_generator
885 .coverage_failure('bar_coverage', [2]) 915 .coverage_failure('bar_coverage', [2])
886 .diff_failure('bar_diff') 916 .diff_failure('bar_diff')
887 .check_failure('bar_check', 'bar_file', 2, 'bar_func', ['bar_args']) 917 .check_failure('bar_check', 'bar_file', 2, 'bar_func', ['bar_args'])
918 .internal_failure('bar_internal')
888 .uncovered_module('bar_module') 919 .uncovered_module('bar_module')
889 .unused_expectation('bar_expectation') 920 .unused_expectation('bar_expectation')
890 .get(), 921 .get(),
891 self.json_contents) 922 self.json_contents)
892 923
893 924
894 if __name__ == '__main__': 925 if __name__ == '__main__':
895 sys.exit(unittest.main()) 926 sys.exit(unittest.main())
OLDNEW
« no previous file with comments | « recipe_engine/test_result_pb2.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698