|
18 | 18 | import argparse
|
19 | 19 | import contextlib
|
20 | 20 | import json
|
| 21 | +import os |
21 | 22 | import sys
|
22 | 23 | import unittest
|
23 | 24 |
|
@@ -103,6 +104,12 @@ def _parse_arguments(argv):
|
103 | 104 | '--fix_tests',
|
104 | 105 | action=argparse.BooleanOptionalAction,
|
105 | 106 | help='Update failing test expectations to match the actual ouput.')
|
| 107 | + parser.add_argument( |
| 108 | + '--create_test', |
| 109 | + action=argparse.BooleanOptionalAction, |
| 110 | + help='Automatically creates a regression test for the given pipeline, ' |
| 111 | + 'adding it to the pipeline spec or test suite dependon on whether ' |
| 112 | + '--test_suite is given.') |
106 | 113 | parser.add_argument(
|
107 | 114 | '--test_suite',
|
108 | 115 | help='Run the given tests against the given pipeline, rather than the '
|
@@ -154,51 +161,69 @@ def run_tests(argv=None, exit=True):
|
154 | 161 | pipeline_spec = yaml.load(pipeline_yaml, Loader=yaml_transform.SafeLineLoader)
|
155 | 162 | options = _build_pipeline_options(pipeline_spec, pipeline_args)
|
156 | 163 |
|
157 |
| - if known_args.test_suite: |
158 |
| - with open(known_args.test_suite) as fin: |
159 |
| - test_suite = yaml.load(fin, Loader=yaml_transform.SafeLineLoader) |
160 |
| - if 'tests' not in test_suite or not isinstance(test_suite['tests'], list): |
161 |
| - raise TypeError('tests attribute must be a list of test specifications') |
162 |
| - test_specs = test_suite['tests'] |
| 164 | + if known_args.create_test and not known_args.fix_tests: |
| 165 | + result = unittest.TestResult() |
163 | 166 | else:
|
164 |
| - test_specs = pipeline_spec.get('tests', []) |
165 |
| - if not isinstance(test_specs, list): |
166 |
| - raise TypeError('tests attribute must be a list of test specifications') |
167 |
| - if not test_specs: |
168 |
| - raise RuntimeError('No tests found.') |
169 |
| - |
170 |
| - with _fix_xlang_instant_coding(): |
171 |
| - tests = [ |
172 |
| - _YamlTestCase(pipeline_spec, test_spec, options, known_args.fix_tests) |
173 |
| - for test_spec in test_specs |
174 |
| - ] |
175 |
| - suite = unittest.TestSuite(tests) |
176 |
| - result = unittest.TextTestRunner().run(suite) |
177 |
| - |
178 |
| - if known_args.fix_tests: |
| 167 | + if known_args.test_suite: |
| 168 | + with open(known_args.test_suite) as fin: |
| 169 | + test_suite = yaml.load(fin, Loader=yaml_transform.SafeLineLoader) or {} |
| 170 | + if 'tests' not in test_suite or not isinstance(test_suite['tests'], list): |
| 171 | + raise TypeError('tests attribute must be a list of test specifications') |
| 172 | + test_specs = test_suite['tests'] |
| 173 | + else: |
| 174 | + test_specs = pipeline_spec.get('tests', []) |
| 175 | + if not isinstance(test_specs, list): |
| 176 | + raise TypeError('tests attribute must be a list of test specifications') |
| 177 | + if not test_specs: |
| 178 | + raise RuntimeError('No tests found.') |
| 179 | + |
| 180 | + with _fix_xlang_instant_coding(): |
| 181 | + tests = [ |
| 182 | + _YamlTestCase( |
| 183 | + pipeline_spec, test_spec, options, known_args.fix_tests) |
| 184 | + for test_spec in test_specs |
| 185 | + ] |
| 186 | + suite = unittest.TestSuite(tests) |
| 187 | + result = unittest.TextTestRunner().run(suite) |
| 188 | + |
| 189 | + if known_args.fix_tests or known_args.create_test: |
179 | 190 | if known_args.test_suite:
|
180 | 191 | path = known_args.test_suite
|
| 192 | + if not os.path.exists(path) and known_args.create_test: |
| 193 | + with open(path, 'w') as fout: |
| 194 | + fout.write('tests: []') |
181 | 195 | elif known_args.yaml_pipeline_file:
|
182 | 196 | path = known_args.yaml_pipeline_file
|
183 | 197 | else:
|
184 | 198 | raise RuntimeError('Test fixing only supported for file-backed tests.')
|
185 | 199 | with open(path) as fin:
|
186 | 200 | original_yaml = fin.read()
|
187 | 201 | if path == known_args.yaml_pipeline_file and pipeline_yaml == content:
|
188 |
| - raise RuntimeError('In-file test fixing not yet supported for templated pipelines.') |
189 |
| - updated_spec = yaml.load(original_yaml, Loader=yaml.SafeLoader) |
190 |
| - |
191 |
| - for ix, test in enumerate(tests): |
192 |
| - if test.fixes: |
193 |
| - test_spec = yaml_transform.SafeLineLoader.strip_metadata(test.spec()) |
194 |
| - assert test_spec == updated_spec['tests'][ix] |
195 |
| - for (loc, name), values in test.fixes.items(): |
196 |
| - for expectation in updated_spec['tests'][ix][loc]: |
197 |
| - if expectation['name'] == name: |
198 |
| - expectation['elements'] = sorted(values, key=json.dumps) |
199 |
| - break |
| 202 | + raise RuntimeError( |
| 203 | + 'In-file test fixing not yet supported for templated pipelines.') |
| 204 | + updated_spec = yaml.load(original_yaml, Loader=yaml.SafeLoader) or {} |
| 205 | + |
| 206 | + if known_args.fix_tests: |
| 207 | + for ix, test in enumerate(tests): |
| 208 | + if test.fixes: |
| 209 | + test_spec = yaml_transform.SafeLineLoader.strip_metadata(test.spec()) |
| 210 | + assert test_spec == updated_spec['tests'][ix] |
| 211 | + for (loc, name), values in test.fixes.items(): |
| 212 | + for expectation in updated_spec['tests'][ix][loc]: |
| 213 | + if expectation['name'] == name: |
| 214 | + expectation['elements'] = sorted(values, key=json.dumps) |
| 215 | + break |
| 216 | + |
| 217 | + if known_args.create_test: |
| 218 | + if 'tests' not in updated_spec: |
| 219 | + updated_spec['tests'] = [] |
| 220 | + updated_spec['tests'].append( |
| 221 | + yaml_testing.create_test(pipeline_spec, options)) |
200 | 222 |
|
201 | 223 | updated_yaml = yaml_utils.patch_yaml(original_yaml, updated_spec)
|
| 224 | + import pprint |
| 225 | + pprint.pprint(updated_spec, sort_dicts=False) |
| 226 | + print(updated_yaml) |
202 | 227 | with open(path, 'w') as fout:
|
203 | 228 | fout.write(updated_yaml)
|
204 | 229 |
|
|
0 commit comments