File size: 4,336 Bytes
35b8d61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python
"""Generate a markdown summary of the test suite."""
import ast
import os
from pathlib import Path


def summarize_tests(start_dir: str, output_file: str):
    """
    Parses Python test files to extract test function names and their docstrings,
    then writes a summary to a markdown file.
    """
    project_root = Path(__file__).parent.parent
    search_path = project_root / start_dir
    output_path = project_root / output_file

    # First pass: collect counts by category
    counts = {
        "unit": {"files": 0, "tests": 0},
        "integration": {"files": 0, "tests": 0},
        "other": {"files": 0, "tests": 0},
    }

    for root, _, files in os.walk(search_path):
        for file in files:
            if file.startswith("test_") and file.endswith(".py"):
                file_path = Path(root) / file
                relative_path = str(file_path.relative_to(project_root))

                # Determine category based on markers or path
                if "/unit/" in relative_path or "_unit" in file:
                    category = "unit"
                elif "/integration/" in relative_path or "integration" in file:
                    category = "integration"
                else:
                    category = "other"

                counts[category]["files"] += 1

                try:
                    with open(file_path, "r", encoding="utf-8") as f:
                        source = f.read()
                        tree = ast.parse(source)
                        for node in ast.walk(tree):
                            # Count both sync and async test functions
                            if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name.startswith("test_"):
                                counts[category]["tests"] += 1
                except Exception:
                    pass

    # Build summary with counts header
    total_files = sum(c["files"] for c in counts.values())
    total_tests = sum(c["tests"] for c in counts.values())

    summary_lines = [
        "# Test Suite Summary\n",
        "## Overview\n",
        "| Category | Files | Tests |",
        "|----------|-------|-------|",
        f"| Unit | {counts['unit']['files']} | {counts['unit']['tests']} |",
        f"| Integration | {counts['integration']['files']} | {counts['integration']['tests']} |",
    ]

    if counts["other"]["files"] > 0:
        summary_lines.append(f"| Other | {counts['other']['files']} | {counts['other']['tests']} |")

    summary_lines.extend([
        f"| **Total** | **{total_files}** | **{total_tests}** |",
        "",
    ])

    # Second pass: detailed listing
    for root, _, files in os.walk(search_path):
        for file in sorted(files):
            if file.startswith("test_") and file.endswith(".py"):
                file_path = Path(root) / file
                relative_path = file_path.relative_to(project_root)
                summary_lines.append(f"\n## `{relative_path}`\n")

                try:
                    with open(file_path, "r", encoding="utf-8") as f:
                        source = f.read()
                        tree = ast.parse(source)

                        for node in ast.walk(tree):
                            # Include both sync and async test functions
                            if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)) and node.name.startswith("test_"):
                                docstring = ast.get_docstring(node)
                                summary_lines.append(f"- **`{node.name}`**")
                                if docstring:
                                    # Clean up the docstring for single-line display
                                    first_line = docstring.strip().split("\n")[0]
                                    summary_lines.append(f"  - *{first_line}*")
                except Exception as e:
                    summary_lines.append(f"- Error parsing file: {e}")

    with open(output_path, "w", encoding="utf-8") as f:
        f.write("\n".join(summary_lines))

    print(f"Test suite summary generated at: {output_path}")


if __name__ == "__main__":
    # Configuration for prompt-prix
    TEST_DIRECTORY = "tests"
    OUTPUT_MARKDOWN_FILE = "docs/TEST_SUMMARY.md"

    summarize_tests(TEST_DIRECTORY, OUTPUT_MARKDOWN_FILE)