| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Provides test coverage for individual recipes. | 6 """Provides test coverage for individual recipes. |
| 7 | 7 |
| 8 Recipe tests are located in ../recipes_test/*.py. | 8 Recipe tests are located in ../recipes_test/*.py. |
| 9 | 9 |
| 10 Each py file's splitext'd name is expected to match a recipe in ../recipes/*.py. | 10 Each py file's splitext'd name is expected to match a recipe in ../recipes/*.py. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 | 45 |
| 46 import test_env # pylint: disable=F0401,W0611 | 46 import test_env # pylint: disable=F0401,W0611 |
| 47 | 47 |
| 48 import coverage | 48 import coverage |
| 49 | 49 |
| 50 import common.python26_polyfill # pylint: disable=W0611 | 50 import common.python26_polyfill # pylint: disable=W0611 |
| 51 import unittest | 51 import unittest |
| 52 | 52 |
| 53 from common import annotator | 53 from common import annotator |
| 54 from slave import recipe_util | 54 from slave import recipe_util |
| 55 from slave import recipe_config_types |
| 55 from slave import annotated_run | 56 from slave import annotated_run |
| 56 from slave import recipe_loader | 57 from slave import recipe_loader |
| 57 | 58 |
| 58 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) | 59 SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__)) |
| 59 ROOT_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir, os.pardir, | 60 ROOT_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, os.pardir, os.pardir, |
| 60 os.pardir)) | 61 os.pardir)) |
| 61 SLAVE_DIR = os.path.join(ROOT_PATH, 'slave', 'fake_slave', 'build') | 62 SLAVE_DIR = os.path.join(ROOT_PATH, 'slave', 'fake_slave', 'build') |
| 62 | 63 |
| 63 BASE_DIRS = recipe_util.BASE_DIRS | 64 BASE_DIRS = recipe_util.BASE_DIRS |
| 64 COVERAGE = None | 65 COVERAGE = None |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 try: | 108 try: |
| 108 props = test_data.properties | 109 props = test_data.properties |
| 109 props['recipe'] = recipe_name | 110 props['recipe'] = recipe_name |
| 110 | 111 |
| 111 stream = annotator.StructuredAnnotationStream(stream=open(os.devnull, 'w')) | 112 stream = annotator.StructuredAnnotationStream(stream=open(os.devnull, 'w')) |
| 112 | 113 |
| 113 def api(*args, **kwargs): | 114 def api(*args, **kwargs): |
| 114 return recipe_loader.CreateRecipeApi(test_data=test_data, *args, **kwargs) | 115 return recipe_loader.CreateRecipeApi(test_data=test_data, *args, **kwargs) |
| 115 | 116 |
| 116 with cover(): | 117 with cover(): |
| 118 recipe_config_types.ResetTostringFns() |
| 117 step_data = annotated_run.run_steps( | 119 step_data = annotated_run.run_steps( |
| 118 stream, props, props, api, test_data).steps_ran.values() | 120 stream, props, props, api, test_data).steps_ran.values() |
| 119 return [s.step for s in step_data] | 121 return [s.step for s in step_data] |
| 120 except: | 122 except: |
| 121 print 'Exception while processing "%s"!' % recipe_path | 123 print 'Exception while processing "%s"!' % recipe_path |
| 122 raise | 124 raise |
| 123 | 125 |
| 124 | 126 |
| 125 def train_from_tests((recipe_path, recipe_name)): | 127 def train_from_tests((recipe_path, recipe_name)): |
| 126 for path in glob(expected_for(recipe_path, '*')): | 128 for path in glob(expected_for(recipe_path, '*')): |
| 127 os.unlink(path) | 129 os.unlink(path) |
| 128 | 130 |
| 129 for test_data in exec_test_file(recipe_path): | 131 for test_data in exec_test_file(recipe_path): |
| 130 steps = execute_test_case(test_data, recipe_path, recipe_name) | 132 steps = execute_test_case(test_data, recipe_path, recipe_name) |
| 131 expected_path = expected_for(recipe_path, test_data.name) | 133 expected_path = expected_for(recipe_path, test_data.name) |
| 132 print 'Writing', expected_path | 134 print 'Writing', expected_path |
| 133 with open(expected_path, 'wb') as f: | 135 with open(expected_path, 'wb') as f: |
| 134 json.dump(steps, f, sort_keys=True, indent=2, separators=(',', ': ')) | 136 json.dump(steps, f, sort_keys=True, indent=2, separators=(',', ': '), |
| 137 default=recipe_config_types.json_fixup) |
| 135 | 138 |
| 136 return True | 139 return True |
| 137 | 140 |
| 138 | 141 |
| 139 def load_tests(loader, _standard_tests, _pattern): | 142 def load_tests(loader, _standard_tests, _pattern): |
| 140 """This method is invoked by unittest.main's automatic testloader.""" | 143 """This method is invoked by unittest.main's automatic testloader.""" |
| 141 def create_test_class((recipe_path, recipe_name)): | 144 def create_test_class((recipe_path, recipe_name)): |
| 142 class RecipeTest(unittest.TestCase): | 145 class RecipeTest(unittest.TestCase): |
| 143 @classmethod | 146 @classmethod |
| 144 def add_test_methods(cls): | 147 def add_test_methods(cls): |
| 145 for test_data in exec_test_file(recipe_path): | 148 for test_data in exec_test_file(recipe_path): |
| 146 expected_path = expected_for(recipe_path, test_data.name) | 149 expected_path = expected_for(recipe_path, test_data.name) |
| 147 def add_test(test_data, expected_path, recipe_name): | 150 def add_test(test_data, expected_path, recipe_name): |
| 148 def test_(self): | 151 def test_(self): |
| 149 steps = execute_test_case(test_data, recipe_path, recipe_name) | 152 steps = execute_test_case(test_data, recipe_path, recipe_name) |
| 150 # Roundtrip json to get same string encoding as load | 153 # Roundtrip json to get same string encoding as load |
| 151 steps = json.loads(json.dumps(steps)) | 154 steps = json.loads( |
| 155 json.dumps(steps, default=recipe_config_types.json_fixup)) |
| 152 with open(expected_path, 'rb') as f: | 156 with open(expected_path, 'rb') as f: |
| 153 expected = json.load(f) | 157 expected = json.load(f) |
| 154 self.assertEqual(steps, expected) | 158 self.assertEqual(steps, expected) |
| 155 test_.__name__ += test_data.name | 159 test_.__name__ += test_data.name |
| 156 setattr(cls, test_.__name__, test_) | 160 setattr(cls, test_.__name__, test_) |
| 157 add_test(test_data, expected_path, recipe_name) | 161 add_test(test_data, expected_path, recipe_name) |
| 158 | 162 |
| 159 RecipeTest.add_test_methods() | 163 RecipeTest.add_test_methods() |
| 160 | 164 |
| 161 RecipeTest.__name__ += '_for_%s' % ( | 165 RecipeTest.__name__ += '_for_%s' % ( |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 retcode = retcode or 2 | 220 retcode = retcode or 2 |
| 217 | 221 |
| 218 if training: | 222 if training: |
| 219 test_env.print_coverage_warning() | 223 test_env.print_coverage_warning() |
| 220 | 224 |
| 221 return retcode | 225 return retcode |
| 222 | 226 |
| 223 | 227 |
| 224 if __name__ == '__main__': | 228 if __name__ == '__main__': |
| 225 sys.exit(main(sys.argv)) | 229 sys.exit(main(sys.argv)) |
| OLD | NEW |