Skip to content

Commit 242c450

Browse files
karlwaldmanclaude
andauthored
docs(performance): wire performance guide into README + docs nav, add doc contract tests (#39)
Closes #26. The SDK Performance Guide content already existed at docs/PERFORMANCE_GUIDE.md but was undiscoverable: the README did not link to it and it was absent from the mkdocs site navigation. This makes the guide reachable and locks all five issue acceptance criteria behind executable tests so they cannot regress. Changes (additive, minimal): - README.md: add a "Performance Guide" link in the Documentation section. - mkdocs.yml: add the guide to the docs site nav. - tests/unit/test_performance_docs.py: new documentation contract tests (TDD) asserting the guide exists, documents expected response times/timeouts, best practices, troubleshooting, runnable examples, README link, and nav discoverability. TDD: tests written first; 2 of 7 failed (README link + mkdocs nav) before the fix and all 7 pass after. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8e67190 commit 242c450

3 files changed

Lines changed: 114 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,8 @@ async with AsyncOilPriceAPI() as client:
525525

526526
**[Complete SDK Documentation →](docs/index.md)** | **[Online Docs →](https://docs.oilpriceapi.com/sdk/python)**
527527

528+
**[⚡ Performance Guide →](docs/PERFORMANCE_GUIDE.md)** — expected response times, recommended timeouts, optimization best practices, and troubleshooting for slow queries.
529+
528530
### Authentication
529531

530532
```python

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ theme:
1515

1616
nav:
1717
- Home: index.md
18+
- Performance Guide: PERFORMANCE_GUIDE.md
1819
- API Reference:
1920
- Client: reference/client.md
2021
- Async Client: reference/async_client.md
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
"""Documentation contract tests for the SDK Performance Guide (issue #26).
2+
3+
Issue #26 ("[Q2-P2] Document SDK performance characteristics and best
4+
practices") defines five acceptance criteria:
5+
6+
- [ ] Performance guide added to docs
7+
- [ ] Best practices documented
8+
- [ ] Troubleshooting guide added
9+
- [ ] Examples updated with performance notes
10+
- [ ] README links to performance guide
11+
12+
These tests encode each criterion as an executable assertion so the
13+
documentation cannot silently regress. They are pure filesystem checks
14+
(no network, no API key) and therefore run in the default `unit` gate.
15+
"""
16+
17+
from __future__ import annotations
18+
19+
from pathlib import Path
20+
21+
import pytest
22+
23+
# Repo root is two levels up from this file: tests/unit/ -> repo root.
24+
REPO_ROOT = Path(__file__).resolve().parents[2]
25+
PERF_GUIDE = REPO_ROOT / "docs" / "PERFORMANCE_GUIDE.md"
26+
README = REPO_ROOT / "README.md"
27+
MKDOCS = REPO_ROOT / "mkdocs.yml"
28+
29+
30+
@pytest.fixture(scope="module")
31+
def perf_guide_text() -> str:
32+
assert PERF_GUIDE.exists(), f"Performance guide missing at {PERF_GUIDE}"
33+
return PERF_GUIDE.read_text(encoding="utf-8")
34+
35+
36+
# --- Criterion 1: Performance guide added to docs --------------------------
37+
38+
39+
def test_performance_guide_exists() -> None:
40+
"""A dedicated performance guide must live under docs/."""
41+
assert PERF_GUIDE.exists(), f"Expected performance guide at {PERF_GUIDE}"
42+
assert PERF_GUIDE.stat().st_size > 0, "Performance guide must not be empty"
43+
44+
45+
def test_performance_guide_documents_expected_response_times(
46+
perf_guide_text: str,
47+
) -> None:
48+
"""The guide must set expectations for query latency and timeouts."""
49+
lowered = perf_guide_text.lower()
50+
assert "expected performance" in lowered or "expected response" in lowered
51+
assert "timeout" in lowered
52+
# Concrete latency baselines users can compare against.
53+
assert "ms" in perf_guide_text
54+
assert "<500ms" in perf_guide_text or "500ms" in perf_guide_text
55+
56+
57+
# --- Criterion 2: Best practices documented --------------------------------
58+
59+
60+
def test_best_practices_documented(perf_guide_text: str) -> None:
61+
lowered = perf_guide_text.lower()
62+
assert "optimization" in lowered or "best practice" in lowered
63+
# Core best-practice levers called out in the issue.
64+
assert "per_page" in perf_guide_text, "Pagination guidance missing"
65+
assert "async" in lowered, "Async/parallel guidance missing"
66+
assert "context manager" in lowered or "with OilPriceAPI" in perf_guide_text
67+
68+
69+
# --- Criterion 3: Troubleshooting guide added ------------------------------
70+
71+
72+
def test_troubleshooting_section_present(perf_guide_text: str) -> None:
73+
lowered = perf_guide_text.lower()
74+
assert "troubleshooting" in lowered, "Troubleshooting section missing"
75+
assert "timeout" in lowered
76+
77+
78+
# --- Criterion 4: Examples updated with performance notes ------------------
79+
80+
81+
def test_guide_contains_runnable_examples(perf_guide_text: str) -> None:
82+
"""Guidance must include concrete, copy-pasteable code examples."""
83+
assert "```python" in perf_guide_text, "Guide must include python examples"
84+
# Both a slow anti-pattern and a fast recommended pattern.
85+
assert "historical.get(" in perf_guide_text
86+
87+
88+
# --- Criterion 5: README links to performance guide ------------------------
89+
90+
91+
def test_readme_links_to_performance_guide() -> None:
92+
"""README must link to docs/PERFORMANCE_GUIDE.md so users can find it."""
93+
assert README.exists(), f"README missing at {README}"
94+
text = README.read_text(encoding="utf-8")
95+
assert "docs/PERFORMANCE_GUIDE.md" in text, (
96+
"README must link to docs/PERFORMANCE_GUIDE.md "
97+
"(acceptance criterion: 'README links to performance guide')"
98+
)
99+
100+
101+
# --- Discoverability: guide wired into the docs site nav -------------------
102+
103+
104+
def test_performance_guide_in_mkdocs_nav() -> None:
105+
"""The guide must be reachable from the published docs site navigation."""
106+
assert MKDOCS.exists(), f"mkdocs.yml missing at {MKDOCS}"
107+
text = MKDOCS.read_text(encoding="utf-8")
108+
assert "PERFORMANCE_GUIDE.md" in text, (
109+
"mkdocs.yml nav must include PERFORMANCE_GUIDE.md so the guide is "
110+
"discoverable on the docs site"
111+
)

0 commit comments

Comments
 (0)