hoedown/test/runner.py

94 lines
2.7 KiB
Python
Raw Normal View History

2014-09-09 08:10:50 +00:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function
import difflib
2014-09-09 08:10:50 +00:00
import json
import os
2014-09-09 08:10:50 +00:00
import re
import subprocess
import unittest
DLN = '======================================================================'
SLN = '----------------------------------------------------------------------'
TEST_ROOT = os.path.dirname(__file__)
PROJECT_ROOT = os.path.dirname(TEST_ROOT)
HOEDOWN = [os.path.abspath(os.path.join(PROJECT_ROOT, 'hoedown'))]
2014-09-09 08:10:50 +00:00
TIDY = ['tidy', '--show-body-only', '1', '--show-warnings', '0',
'--quiet', '1']
CONFIG_PATH = os.path.join(TEST_ROOT, 'config.json')
SLUGIFY_PATTERN = re.compile(r'\W')
class TestFailed(AssertionError):
def __init__(self, name, expected, got):
super(TestFailed, self).__init__(self)
2014-09-09 09:16:08 +00:00
diff = difflib.unified_diff(
expected.splitlines(), got.splitlines(),
fromfile='Expected', tofile='Got',
)
2014-09-09 09:14:38 +00:00
self.description = '{name}\n{diff}'.format(
name=name, diff='\n'.join(diff),
2014-09-09 08:10:50 +00:00
)
def __str__(self):
return self.description
def _test_func(test_case):
flags = test_case.get('flags') or []
hoedown_proc = subprocess.Popen(
HOEDOWN + flags + [os.path.join(TEST_ROOT, test_case['input'])],
stdout=subprocess.PIPE,
)
hoedown_proc.wait()
got_tidy_proc = subprocess.Popen(
TIDY, stdin=hoedown_proc.stdout, stdout=subprocess.PIPE,
)
got_tidy_proc.wait()
2014-09-09 09:14:38 +00:00
got = got_tidy_proc.stdout.read().strip()
2014-09-09 08:10:50 +00:00
expected_tidy_proc = subprocess.Popen(
TIDY + [os.path.join(TEST_ROOT, test_case['output'])],
stdout=subprocess.PIPE,
)
expected_tidy_proc.wait()
2014-09-09 09:14:38 +00:00
expected = expected_tidy_proc.stdout.read().strip()
2014-09-09 08:10:50 +00:00
try:
assert expected == got
except AssertionError:
raise TestFailed(test_case['input'], expected, got)
def _make_test(test_case):
return lambda self: _test_func(test_case)
class MarkdownTestCaseMeta(type):
"""Meta class for ``MarkdownTestCase`` to inject test cases on the fly.
"""
def __new__(meta, name, bases, attrs):
with open(CONFIG_PATH) as f:
config = json.load(f)
for test in config['tests']:
input_name = test['input']
attr_name = 'test_' + SLUGIFY_PATTERN.sub(
'_', os.path.splitext(input_name)[0].lower(),
)
func = _make_test(test)
func.__doc__ = input_name
if test.get('skip', False):
func = unittest.skip(input_name)(func)
attrs[attr_name] = func
return type.__new__(meta, name, bases, attrs)
class MarkdownTestCase(unittest.TestCase):
__metaclass__ = MarkdownTestCaseMeta
if __name__ == '__main__':
unittest.main()