probatio 0.0.0-stage → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env python3
2
+ """Run unittest modules and print one Probatio report as a single JSON line."""
3
+ import importlib.util
4
+ import json
5
+ import os
6
+ import re
7
+ import sys
8
+ import unittest
9
+ from pathlib import Path
10
+
11
+
12
+ def load(path: Path):
13
+ name = f"probatio_{path.stem}"
14
+ spec = importlib.util.spec_from_file_location(name, path)
15
+ if spec is None or spec.loader is None:
16
+ raise RuntimeError(f"cannot load {path}")
17
+ module = importlib.util.module_from_spec(spec)
18
+ sys.modules[name] = module
19
+ spec.loader.exec_module(module)
20
+ return module
21
+
22
+
23
+ def walk(suite):
24
+ for item in suite:
25
+ if isinstance(item, unittest.TestSuite):
26
+ yield from walk(item)
27
+ else:
28
+ yield item
29
+
30
+
31
+ def parse_args(argv):
32
+ pattern = None
33
+ files = []
34
+ index = 0
35
+ while index < len(argv):
36
+ if argv[index] == "--pattern":
37
+ pattern = argv[index + 1]
38
+ index += 2
39
+ continue
40
+ files.append(argv[index])
41
+ index += 1
42
+ return pattern, files
43
+
44
+
45
+ def main():
46
+ pattern, files = parse_args(sys.argv[1:])
47
+ sys.path.insert(0, str(Path.cwd()))
48
+ loader = unittest.TestLoader()
49
+ suite = unittest.TestSuite()
50
+ compiled = re.compile(pattern) if pattern else None
51
+ for file in files:
52
+ loaded = loader.loadTestsFromModule(load(Path(file)))
53
+ if compiled is None:
54
+ suite.addTest(loaded)
55
+ else:
56
+ for case in walk(loaded):
57
+ if compiled.fullmatch(case.id()):
58
+ suite.addTest(case)
59
+ cases = [case for case in walk(suite) if case is not None]
60
+ names = [case.id() for case in cases]
61
+ with open(os.devnull, "w") as stream:
62
+ result = unittest.TextTestRunner(stream=stream, verbosity=0).run(suite)
63
+ failed = []
64
+ for case, tb in list(result.failures) + list(result.errors):
65
+ frames = re.findall(r'File "([^"]+)", line (\d+)', tb)
66
+ file, line = frames[-1] if frames else ("", "0")
67
+ failed.append({"name": case.id(), "file": file, "line": int(line)})
68
+ report = {
69
+ "tests": len(names),
70
+ "pass": len(names) - len(failed),
71
+ "fail": len(failed),
72
+ "failed": failed,
73
+ "names": names,
74
+ }
75
+ sys.stdout.write(json.dumps(report) + "\n")
76
+
77
+
78
+ if __name__ == "__main__":
79
+ main()