diff options
| author | 2021-02-24 12:07:13 +0100 | |
|---|---|---|
| committer | 2021-02-24 12:07:13 +0100 | |
| commit | d931810f51f27e55455be7e8a87c5a27a04d431d (patch) | |
| tree | 306c5e1995107f32870c81dda7bab56434b41c50 | |
| parent | Add unittests to the schema (diff) | |
Add unittest template
| -rw-r--r-- | resources/unittest_template.py | 81 | 
1 files changed, 81 insertions, 0 deletions
diff --git a/resources/unittest_template.py b/resources/unittest_template.py new file mode 100644 index 0000000..7e21b97 --- /dev/null +++ b/resources/unittest_template.py @@ -0,0 +1,81 @@ +import ast +import io +import os +import sys +import traceback +import unittest +from itertools import chain +from types import ModuleType, SimpleNamespace +from typing import NoReturn +from unittest import mock + +### USER CODE + + +class RunnerTestCase(unittest.TestCase): +### UNIT CODE + + +# Fake file object not writing anything +DEVNULL = SimpleNamespace(write=lambda *_: None, flush=lambda *_: None) + +RESULT = io.StringIO() +ORIGINAL_STDOUT = sys.stdout + +sys.stdout = DEVNULL +sys.stderr = DEVNULL + + +def _exit_sandbox(code: int) -> NoReturn: +    """ +    Codes: +    - 0: Executed with success +    - 5: Syntax error while parsing user code +    - 99: Internal error +    """ +    result_content = RESULT.getvalue() + +    print( +        f"{result_content}", +        file=ORIGINAL_STDOUT +    ) +    sys.exit(code) + + +def _load_user_module() -> ModuleType: +    try: +        ast.parse(USER_CODE, "<input>") +    except SyntaxError: +        RESULT.write("".join(traceback.format_exception(*sys.exc_info(), limit=0))) +        _exit_sandbox(5) + +    _module = ModuleType("module") +    exec(USER_CODE, _module.__dict__) + +    return _module + + +def _main() -> None: +    suite = unittest.defaultTestLoader.loadTestsFromTestCase(RunnerTestCase) +    result = suite.run(unittest.TestResult()) + +    RESULT.write(str(int(result.wasSuccessful()))) + +    if not result.wasSuccessful(): +        RESULT.write( +            ";".join(chain( +                (error[0]._testMethodName.lstrip("test_") for error in result.errors), +                (failure[0]._testMethodName.lstrip("test_") for failure in result.failures) +            )) +        ) + +    _exit_sandbox(0) + + +try: +    module = _load_user_module() +    _main() +except Exception: +    print("Uncaught exception:\n", file=RESULT) +    traceback.print_exc(file=RESULT) +    _exit_sandbox(99)  |