import functools import json import sys import marko import marko.md_renderer def get_tests(template): test_data = None for el in template.children: if isinstance(el, marko.block.BlankLine): continue if isinstance(el, marko.block.Heading): if test_data is not None: yield test_data test_data = [] test_data.append(el) continue if test_data is not None: test_data.append(el) if test_data is not None: yield test_data def apply_settings(settings, txt): for k, v in settings.items(): txt = txt.replace(f'${k}', v) return txt def generate_assertion_expect(result, arg): result.append('result = Suite(code_py).run_code()') result.append(f'assert {repr(arg)} == result.returned_value') def generate_assertion_expect_type_error(result, error_msg, error_comment = None): result.append('with pytest.raises(Type3Exception) as exc_info:') result.append(' Suite(code_py).run_code()') result.append(f'assert {repr(error_msg)} == exc_info.value.args[0][0].msg') result.append(f'assert {repr(error_comment)} == exc_info.value.args[0][0].comment') def generate_assertions(settings, result_code): result = [] locals_ = { 'TYPE_NAME': settings['TYPE_NAME'], 'expect': functools.partial(generate_assertion_expect, result), 'expect_type_error': functools.partial(generate_assertion_expect_type_error, result), } exec(result_code, {}, locals_) return ' ' + '\n '.join(result) + '\n' def generate_code(markdown, template, settings): type_name = settings['TYPE_NAME'] print('"""') print('AUTO GENERATED') print() print('TEMPLATE:', sys.argv[1]) print('SETTINGS:', sys.argv[2]) print('"""') print('import pytest') print() print('from phasm.type3.entry import Type3Exception') print() print('from ..helpers import Suite') print() for test in get_tests(template): assert len(test) == 4, test heading, paragraph, code_block1, code_block2 = test assert isinstance(heading, marko.block.Heading) assert isinstance(paragraph, marko.block.Paragraph) assert isinstance(code_block1, marko.block.FencedCode) assert isinstance(code_block2, marko.block.FencedCode) test_id = apply_settings(settings, heading.children[0].children) user_story = apply_settings(settings, markdown.renderer.render(paragraph)) inp_code = apply_settings(settings, code_block1.children[0].children) result_code = markdown.renderer.render_children(code_block2) print('@pytest.mark.integration_test') print(f'def test_{type_name}_{test_id}():') print(' """') print(' ' + user_story.replace('\n', '\n ')) print(' """') print(' code_py = """') print(inp_code.rstrip('\n')) print('"""') print() print(generate_assertions(settings, result_code)) print() def main(): markdown = marko.Markdown( renderer=marko.md_renderer.MarkdownRenderer, ) with open(sys.argv[1], 'r', encoding='utf-8') as fil: template = markdown.parse(fil.read()) with open(sys.argv[2], 'r', encoding='utf-8') as fil: settings = json.load(fil) if 'TYPE_NAME' not in settings: settings['TYPE_NAME'] = settings['TYPE'] generate_code(markdown, template, settings) if __name__ == '__main__': main()