Skip to content

Commit de9bc2e

Browse files
committed
add test script for examples in readme.md
1 parent 1c3dff6 commit de9bc2e

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""Test that README examples actually work.
2+
3+
Extracts Python code blocks from README.md and runs them.
4+
This ensures documentation stays in sync with the actual API.
5+
"""
6+
7+
import re
8+
import subprocess
9+
import sys
10+
import tempfile
11+
from pathlib import Path
12+
13+
import pytest
14+
15+
16+
def extract_python_blocks(readme_path: Path) -> list[tuple[str, str]]:
17+
"""Extract Python code blocks from README.md."""
18+
content = readme_path.read_text()
19+
20+
# Pattern: <summary><b>Name</b></summary> or ### Name followed by ```python
21+
pattern = r'(?:<summary><b>([^<]+)</b></summary>|### ([^\n]+))\s*\n+```python\n(.*?)```'
22+
23+
examples = []
24+
for match in re.finditer(pattern, content, re.DOTALL):
25+
name = match.group(1) or match.group(2)
26+
code = match.group(3)
27+
name = name.strip().replace(" ", "_").lower()
28+
examples.append((name, code))
29+
30+
return examples
31+
32+
33+
# Get README path relative to this file
34+
README_PATH = Path(__file__).parent.parent.parent / "README.md"
35+
EXAMPLES = extract_python_blocks(README_PATH) if README_PATH.exists() else []
36+
37+
# Examples to skip (e.g., require external dependencies)
38+
SKIP_EXAMPLES = {"integration_with_optimizers"}
39+
40+
41+
@pytest.mark.parametrize("name,code", EXAMPLES, ids=[e[0] for e in EXAMPLES])
42+
def test_readme_example(name: str, code: str):
43+
"""Test that a README example runs without errors."""
44+
if name in SKIP_EXAMPLES:
45+
pytest.skip(f"Skipping {name} (external dependencies)")
46+
47+
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
48+
f.write(code)
49+
f.flush()
50+
temp_path = Path(f.name)
51+
52+
try:
53+
result = subprocess.run(
54+
[sys.executable, str(temp_path)],
55+
capture_output=True,
56+
text=True,
57+
timeout=60,
58+
)
59+
60+
assert result.returncode == 0, (
61+
f"Example '{name}' failed:\n"
62+
f"stdout: {result.stdout}\n"
63+
f"stderr: {result.stderr}"
64+
)
65+
finally:
66+
temp_path.unlink()

0 commit comments

Comments
 (0)