Skip to content

Commit 1dfff87

Browse files
authored
Add downstream test discrepancy reporter (#167)
1 parent 8cea075 commit 1dfff87

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import argparse
2+
import json
3+
import os
4+
import re
5+
import subprocess
6+
import typing
7+
from collections import namedtuple
8+
9+
from playwright.path_utils import get_file_dirname
10+
11+
_dirname = get_file_dirname()
12+
13+
TestCase = namedtuple("TestCase", ["api", "file", "test"])
14+
15+
16+
def pytest_test_cases() -> typing.Generator[TestCase, None, None]:
17+
p = subprocess.run(
18+
["pytest", "--browser", "chromium", "--collect-only", "-q"],
19+
cwd=_dirname / ".." / "tests",
20+
stdout=subprocess.PIPE,
21+
check=True,
22+
)
23+
regex = (
24+
r"tests/(?P<api>a?sync)/test_(?P<file>.*)\.py::test_(?P<test>.*)\[chromium\]"
25+
)
26+
matches = re.finditer(regex, p.stdout.decode(), re.MULTILINE)
27+
for match in matches:
28+
yield TestCase(
29+
match.group("api"), match.group("file"), match.group("test"),
30+
)
31+
32+
33+
def jest_test_cases(playwright_js_path: str) -> typing.Generator[TestCase, None, None]:
34+
p = subprocess.run(
35+
[
36+
"node",
37+
os.path.join("test", "runner"),
38+
"test",
39+
"--trial-run",
40+
"--reporter",
41+
"json",
42+
],
43+
cwd=playwright_js_path,
44+
stdout=subprocess.PIPE,
45+
stderr=subprocess.DEVNULL,
46+
check=True,
47+
)
48+
49+
tests = json.loads(p.stdout.decode())
50+
for test in [*tests["pending"], *tests["passes"], *tests["failures"]]:
51+
regex = r"(.*/)?(?P<file>[^/]+)\.spec\.[jt]s$"
52+
53+
match = re.match(regex, test["file"])
54+
if not match:
55+
continue
56+
57+
file = match.group("file")
58+
59+
yield TestCase("sync", normalized(file), normalized(test["title"]))
60+
yield TestCase("async", normalized(file), normalized(test["title"]))
61+
62+
63+
def normalized(original: str) -> str:
64+
cleaned = re.sub(r"[^a-z0-9_]", "_", original, flags=re.IGNORECASE)
65+
cleaned = re.sub(r"[_]+", "_", cleaned)
66+
cleaned = cleaned.strip("_")
67+
return cleaned
68+
69+
70+
def main() -> None:
71+
parser = argparse.ArgumentParser()
72+
parser.add_argument(
73+
"--playwright-js-path",
74+
type=str,
75+
help="path to playwright JavaScript directory",
76+
required=True,
77+
)
78+
parser.add_argument(
79+
"--api",
80+
type=str,
81+
help="filter test cases based on API",
82+
choices=["sync", "async"],
83+
)
84+
args = parser.parse_args()
85+
86+
python_tests = set(pytest_test_cases())
87+
javascript_tests = set(jest_test_cases(args.playwright_js_path))
88+
89+
if args.api:
90+
javascript_tests = set([x for x in javascript_tests if x.api == args.api])
91+
92+
missing = javascript_tests.difference(python_tests)
93+
found = javascript_tests.intersection(python_tests)
94+
95+
print("MISSING, MISPELLED, OR MISNAMED:")
96+
print("=" * 80)
97+
for (api, file, test) in sorted(missing):
98+
print(f"{api}/test_{file}.py::test_{test}")
99+
100+
print(f"\nMissing: {len(missing)}, Found: {len(found)}")
101+
102+
103+
if __name__ == "__main__":
104+
main()

0 commit comments

Comments
 (0)