Mercurial > piecrust2
comparison tests/conftest.py @ 979:45ad976712ec
tests: Big push to get the tests to pass again.
- Lots of fixes everywhere in the code.
- Try to handle debug logging in the multiprocessing worker pool when running in pytest. Not perfect, but usable for now.
- Replace all `.md` test files with `.html` since now a auto-format extension always sets the format.
- Replace `out` with `outfiles` in most places since now blog archives are added to the bake output and I don't want to add expected outputs for blog archives everywhere.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 29 Oct 2017 22:51:57 -0700 |
parents | 72f17534d58e |
children | 63f118c773ee |
comparison
equal
deleted
inserted
replaced
978:7e51d14097cb | 979:45ad976712ec |
---|---|
27 help="Sets the PieCrust logger to write to a file.") | 27 help="Sets the PieCrust logger to write to a file.") |
28 parser.addoption( | 28 parser.addoption( |
29 '--mock-debug', | 29 '--mock-debug', |
30 action='store_true', | 30 action='store_true', |
31 help="Prints contents of the mock file-system.") | 31 help="Prints contents of the mock file-system.") |
32 parser.addoption( | |
33 '--leave-mockfs', | |
34 action='store_true', | |
35 help="Leave the contents of the mock file-system on disk.") | |
32 | 36 |
33 | 37 |
34 def pytest_configure(config): | 38 def pytest_configure(config): |
35 if config.getoption('--log-debug'): | 39 if config.getoption('--log-debug'): |
40 root_logger = logging.getLogger() | |
36 hdl = logging.StreamHandler(stream=sys.stdout) | 41 hdl = logging.StreamHandler(stream=sys.stdout) |
37 logging.getLogger('piecrust').addHandler(hdl) | 42 root_logger.addHandler(hdl) |
38 logging.getLogger('piecrust').setLevel(logging.DEBUG) | 43 root_logger.setLevel(logging.DEBUG) |
44 | |
45 from .basefs import TestFileSystemBase | |
46 TestFileSystemBase._use_chef_debug = True | |
47 TestFileSystemBase._pytest_log_handler = hdl | |
39 | 48 |
40 log_file = config.getoption('--log-file') | 49 log_file = config.getoption('--log-file') |
41 if log_file: | 50 if log_file: |
42 hdl = logging.StreamHandler( | 51 hdl = logging.StreamHandler( |
43 stream=open(log_file, 'w', encoding='utf8')) | 52 stream=open(log_file, 'w', encoding='utf8')) |
44 logging.getLogger().addHandler(hdl) | 53 logging.getLogger().addHandler(hdl) |
45 | 54 |
55 if config.getoption('--leave-mockfs'): | |
56 from .basefs import TestFileSystemBase | |
57 TestFileSystemBase._leave_mockfs = True | |
58 | |
46 | 59 |
47 def pytest_collect_file(parent, path): | 60 def pytest_collect_file(parent, path): |
48 if path.ext == '.yaml' and path.basename.startswith("test"): | 61 if path.ext == '.yaml' and path.basename.startswith("test"): |
49 category = os.path.basename(path.dirname) | 62 category = os.path.basename(path.dirname) |
50 if category == 'bakes': | 63 if category == 'bakes': |
51 return BakeTestFile(path, parent) | 64 return BakeTestFile(path, parent) |
52 elif category == 'procs': | |
53 return PipelineTestFile(path, parent) | |
54 elif category == 'cli': | 65 elif category == 'cli': |
55 return ChefTestFile(path, parent) | 66 return ChefTestFile(path, parent) |
56 elif category == 'servings': | 67 elif category == 'servings': |
57 return ServeTestFile(path, parent) | 68 return ServeTestFile(path, parent) |
58 | 69 |
262 | 273 |
263 values = self.spec.get('config_values') | 274 values = self.spec.get('config_values') |
264 if values is not None: | 275 if values is not None: |
265 values = list(values.items()) | 276 values = list(values.items()) |
266 variants = self.spec.get('config_variants') | 277 variants = self.spec.get('config_variants') |
267 if variants is not None: | |
268 variants = list(variants.items()) | |
269 apply_variants_and_values(app, variants, values) | 278 apply_variants_and_values(app, variants, values) |
270 | 279 |
271 appfactory = PieCrustFactory(app.root_dir, | 280 appfactory = PieCrustFactory(app.root_dir, |
281 theme_site=self.is_theme_site, | |
272 config_variants=variants, | 282 config_variants=variants, |
273 config_values=values) | 283 config_values=values) |
274 baker = Baker(appfactory, app, out_dir) | 284 baker = Baker(appfactory, app, out_dir) |
275 records = baker.bake() | 285 records = baker.bake() |
276 | 286 |
311 | 321 |
312 class BakeTestFile(YamlTestFileBase): | 322 class BakeTestFile(YamlTestFileBase): |
313 __item_class__ = BakeTestItem | 323 __item_class__ = BakeTestItem |
314 | 324 |
315 | 325 |
316 class PipelineTestItem(YamlTestItemBase): | |
317 def runtest(self): | |
318 fs = self._prepareMockFs() | |
319 | |
320 from piecrust.processing.pipeline import ProcessorPipeline | |
321 with mock_fs_scope(fs, keep=self.mock_debug): | |
322 out_dir = fs.path('kitchen/_counter') | |
323 app = fs.getApp(theme_site=self.is_theme_site) | |
324 pipeline = ProcessorPipeline(app, out_dir) | |
325 | |
326 proc_names = self.spec.get('processors') | |
327 if proc_names: | |
328 pipeline.enabled_processors = proc_names | |
329 | |
330 record = pipeline.run() | |
331 | |
332 if not record.success: | |
333 errors = [] | |
334 for e in record.entries: | |
335 errors += e.errors | |
336 raise PipelineError(errors) | |
337 | |
338 check_expected_outputs(self.spec, fs, ExpectedPipelineOutputError) | |
339 | |
340 def reportinfo(self): | |
341 return self.fspath, 0, "pipeline: %s" % self.name | |
342 | |
343 def repr_failure(self, excinfo): | |
344 if isinstance(excinfo.value, ExpectedPipelineOutputError): | |
345 return ('\n'.join( | |
346 ['Unexpected pipeline output. Left is expected output, ' | |
347 'right is actual output'] + | |
348 excinfo.value.args[0])) | |
349 elif isinstance(excinfo.value, PipelineError): | |
350 res = ('\n'.join( | |
351 ['Errors occured during processing:'] + | |
352 excinfo.value.args[0])) | |
353 res += repr_nested_failure(excinfo) | |
354 return res | |
355 return super(PipelineTestItem, self).repr_failure(excinfo) | |
356 | |
357 | |
358 class PipelineError(Exception): | |
359 pass | |
360 | |
361 | |
362 class ExpectedPipelineOutputError(Exception): | |
363 pass | |
364 | |
365 | |
366 class PipelineTestFile(YamlTestFileBase): | |
367 __item_class__ = PipelineTestItem | |
368 | |
369 | |
370 class ServeTestItem(YamlTestItemBase): | 326 class ServeTestItem(YamlTestItemBase): |
371 class _TestApp(object): | |
372 def __init__(self, server): | |
373 self.server = server | |
374 | |
375 def __call__(self, environ, start_response): | |
376 response = self.server._try_run_request(environ) | |
377 return response(environ, start_response) | |
378 | |
379 def runtest(self): | 327 def runtest(self): |
380 fs = self._prepareMockFs() | 328 fs = self._prepareMockFs() |
381 | 329 |
382 url = self.spec.get('url') | 330 url = self.spec.get('url') |
383 if url is None: | 331 if url is None: |
385 | 333 |
386 expected_status = self.spec.get('status', 200) | 334 expected_status = self.spec.get('status', 200) |
387 expected_headers = self.spec.get('headers') | 335 expected_headers = self.spec.get('headers') |
388 expected_output = self.spec.get('out') | 336 expected_output = self.spec.get('out') |
389 expected_contains = self.spec.get('out_contains') | 337 expected_contains = self.spec.get('out_contains') |
390 is_admin_test = self.spec.get('admin') is True | |
391 | 338 |
392 from werkzeug.test import Client | 339 from werkzeug.test import Client |
393 from werkzeug.wrappers import BaseResponse | 340 from werkzeug.wrappers import BaseResponse |
341 from piecrust.app import PieCrustFactory | |
342 from piecrust.serving.server import PieCrustServer | |
343 | |
394 with mock_fs_scope(fs, keep=self.mock_debug): | 344 with mock_fs_scope(fs, keep=self.mock_debug): |
395 if is_admin_test: | 345 appfactory = PieCrustFactory( |
396 from piecrust.admin.web import create_foodtruck_app | 346 fs.path('/kitchen'), |
397 s = { | 347 theme_site=self.is_theme_site) |
398 'FOODTRUCK_CMDLINE_MODE': True, | 348 server = PieCrustServer(appfactory) |
399 'FOODTRUCK_ROOT': fs.path('/kitchen') | 349 |
400 } | 350 client = Client(server, BaseResponse) |
401 test_app = create_foodtruck_app(s) | |
402 else: | |
403 from piecrust.app import PieCrustFactory | |
404 from piecrust.serving.server import Server | |
405 appfactory = PieCrustFactory( | |
406 fs.path('/kitchen'), | |
407 theme_site=self.is_theme_site) | |
408 server = Server(appfactory) | |
409 test_app = self._TestApp(server) | |
410 | |
411 client = Client(test_app, BaseResponse) | |
412 resp = client.get(url) | 351 resp = client.get(url) |
413 assert expected_status == resp.status_code | 352 assert expected_status == resp.status_code |
414 | 353 |
415 if expected_headers: | 354 if expected_headers: |
416 for k, v in expected_headers.items(): | 355 for k, v in expected_headers.items(): |
558 # This is where the time starts. Let's compare that the time | 497 # This is where the time starts. Let's compare that the time |
559 # values are within a few seconds of each other (usually 0 or 1). | 498 # values are within a few seconds of each other (usually 0 or 1). |
560 right_time_str = right[i:i + len(test_time_iso8601)] | 499 right_time_str = right[i:i + len(test_time_iso8601)] |
561 right_time = time.strptime(right_time_str, '%Y-%m-%dT%H:%M:%SZ') | 500 right_time = time.strptime(right_time_str, '%Y-%m-%dT%H:%M:%SZ') |
562 left_time = time.gmtime(ctx.time) | 501 left_time = time.gmtime(ctx.time) |
502 # Need to patch the daylist-savings-time flag because it can | |
503 # mess up the computation of the time difference. | |
504 right_time = (right_time[0], right_time[1], right_time[2], | |
505 right_time[3], right_time[4], right_time[5], | |
506 right_time[6], right_time[7], | |
507 left_time.tm_isdst) | |
563 difference = time.mktime(left_time) - time.mktime(right_time) | 508 difference = time.mktime(left_time) - time.mktime(right_time) |
564 print("Got time difference: %d" % difference) | 509 print("Got time difference: %d" % difference) |
565 if abs(difference) <= 2: | 510 if abs(difference) <= 1: |
566 print("(good enough, moving to end of timestamp)") | 511 print("(good enough, moving to end of timestamp)") |
567 skip_for = len(test_time_iso8601) - 1 | 512 skip_for = len(test_time_iso8601) - 1 |
568 | 513 |
569 if left[i] != right[i]: | 514 if left[i] != right[i]: |
570 start = max(0, i - 15) | 515 start = max(0, i - 15) |