# Properly handling different test cases at the same time. import unittest, doctest, re, inspect, typing, types, contextlib ## Sample test methods. def test_me(): assert True class TestClass(unittest.TestCase): def test_this(self): assert False ## Methods ### Combine `unittest and doctest` suites. def make_test_suite(*objects: typing.Union[ unittest.TestCase, types.FunctionType, str ]) -> unittest.TestSuite: Create a test suite from a few different objects. suite, doctest_suite = unittest.TestSuite(), doctest.DocTestSuite() suite.addTest(doctest_suite) for object in objects: if isinstance(object, type) and issubclass(object, unittest.TestCase): Load `unittest.TestCase` when that type is encountered. suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(object)) elif isinstance(object, str): In the case of strings we'll use the `doctest` module to find standard doctests and inline markdown code. doctest_suite.addTest(doctest.DocTestCase(doctest.DocTestParser().get_doctest(object, globals(), __name__, __name__, 0))) doctest_suite.addTest(doctest.DocTestCase(InlineDoctestParser().get_doctest(object, globals(), __name__, __name__, 0), checker=NullOutputCheck)) elif inspect.isfunction(object): When a function is encountered create a test case from that. suite.addTest(unittest.FunctionTestCase(object)) return suite ### Run the main test suite def run(suite: unittest.TestCase) -> unittest.TestResult: `run` a test suite likely created from make_test_suite. result = unittest.TestResult(); suite.run(result) if result.failures: sys.stderr.writelines((str(result) + '\n' + '\n'.join(msg for text, msg in result.failures)).splitlines(True)) return result class NullOutputCheck(doctest.OutputChecker): A compatability tool for tests as long as they don't return an exception. def check_output(self, *e): return True ### A `doctest` parser for inline code objects. class InlineDoctestParser(doctest.DocTestParser): In `"pidgy"`, we want all code to compute. Specifically we add the ability to run inline markdown code objects. as tests. _EXAMPLE_RE = re.compile(r'`(?P\s{0})' r'(?P[^`].*?)' r'`') def _parse_example(self, m, name, lineno): return m.group('source'), None, "...", None ## Running the examples. Running some made up tests. result = run(make_test_suite("""What is the `range` >>> 10 10 """, test_me, TestClass)) ## Expected output. ```console Traceback (most recent call last): File "", line 10, in test_this def test_this(self): assert False AssertionError ```