feat: add pytest test suite for 3 Python scripts#2247
Conversation
mackowski
left a comment
There was a problem hiding this comment.
Thanks, @AnandSundar — nicely built: I ran the suite (56 tests pass) and confirmed the Update_CheatSheets_Index.py refactor is byte-for-byte output-identical to master. Most of it protects code the project doesn't actively use, so I'd like to narrow the scope.
Worth keeping: the tests for Update_CheatSheets_Index.py — it's the one script on the live build path (Generate_Site_mkDocs.sh → build-and-deploy-website.yml).
Not adding value — please drop: tests/refactors for Generate_CheatSheets_TOC.py (only used by the retired GitBook build) and Generate_Technologies_JSON.py (referenced by no workflow at all). Both are effectively dead code, untouched for ~4–7 years.
Needed before merge:
- Add requests to requirements-dev.txt — it only lists pytest, so the suite fails to collect in a clean env (ModuleNotFoundError: requests).
- Add a CI job that runs pytest — nothing runs it today, so as-is it provides zero regression protection.
- Drop the unrelated docs/plans/ entry from .gitignore.
One higher-value idea instead of unit tests: a CI check that regenerates Index.md and fails on drift. The committed Index.md is already stale ("92 cheat sheets" vs ~120 actual) and nothing catches it.
Happy to re-review once it's scoped to the active script with a CI runner in place. Thanks again.
|
@mackowski Thank you for reviewing my PR. I'll work on your recommendations and update the PR soon. |
Introduces a pytest-based test suite for the three build-helper scripts
in scripts/ that have no network dependencies:
- Generate_CheatSheets_TOC.py
- Update_CheatSheets_Index.py
- Generate_Technologies_JSON.py
Each script is minimally refactored to expose pure helper functions
(to_display_name, parse_index_line, group_by_letter, etc.) and to
wrap its imperative top-level code in a main() function with
parameterized paths. Byte-for-byte output of the original scripts is
preserved when invoked from the scripts/ directory.
The test suite covers 56 cases (unit + integration), including:
- helper-function unit tests (display names, language detection,
letter grouping, whitespace cleanup, line parsing)
- main() integration tests against fixture cheatsheet directories
- mocked HTTP path for Generate_Technologies_JSON.main()
Files added:
- pytest.ini, requirements-dev.txt
- tests/__init__.py, tests/conftest.py
- tests/test_*.py for the three scripts
The remaining two scripts (Generate_RSS_Feed.py, Identify_Old_Issue_And_PR.py)
and a CI workflow that runs pytest on PRs are deferred to follow-up PRs.
AI assistance: this change was developed with the help of an AI coding
assistant. The refactor, tests, and commit message were reviewed by the
author before submission.
9887f6e to
bc98d25
Compare
Drop the refactors and tests for Generate_CheatSheets_TOC.py (retired GitBook) and Generate_Technologies_JSON.py (no live consumer) per mackowski's review. Retain refactor + tests for the one script on the live build path, Update_CheatSheets_Index.py. .gitignore was already cleaned of docs/plans/ during rebase conflict resolution; this commit only handles the script and test file changes.
Adds .github/workflows/test-python.yml that runs python -m pytest on every pull request to master. Trigger mirrors md_lint_check.yml (pull_request only, no push). actions/checkout and actions/setup-python are pinned to commit SHAs already in use across the repo. python-version is pinned to 3.12 to avoid silent drift. requirements-dev.txt is the test-only deps file, intentionally separate from requirements.txt so the production image does not pull in pytest. Per the plan, this new check is informational-only until a maintainer adds it to the branch protection required-checks list for master; that admin step is a follow-up.
|
Thanks for the careful review, mackowski. Addressing each point: Tests for the two retired scripts and their refactors — dropped. Commits on the rebased head:
New
Index.md drift check — declined for this PR. Tracked as a separate issue: the idea is a higher-value follow-up than the test infra, but bundling it would push net additions toward Rebase onto current master — done. PR moved from One note for the maintainer audience — the new Note: the original plan called for an inline review-reply API endpoint that doesn't actually exist in GitHub's REST API for review-summary replies — this comment is the closest scripting equivalent and mentions you directly, so the notification still reaches you. |
|
@mackowski — scope narrowed per your review (commits One thing to flag for whoever clicks the merge button: the 6 workflows on the PR (5 existing + the new pytest one) are currently in Ready for re-review when you have a moment — thanks again for the careful reading. |
Summary
Adds a pytest test suite for
scripts/Update_CheatSheets_Index.py— the one script on the live build path (Generate_Site_mkDocs.sh→build-and-deploy-website.yml). Refactors the script to expose pure helper functions (extract_languages_snippet_provided,group_by_letter,clean_trailing_whitespace) and a parameterizedmain(). The refactor preserves byte-for-byte output of the original script when invoked from thescripts/directory — verified via smoke test against the realcheatsheets/directory.What's in this PR
Update_CheatSheets_Index.pynow has importable helpers and amain()that returns an exit code, with anif __name__ == "__main__":guard. No behavioral change for the existing CLI usage.main()end-to-end. Usestmp_path-based fixtures fromtests/conftest.py; no new runtime dependencies beyondpytest.pytest.ini,requirements-dev.txt,tests/__init__.py,tests/conftest.py): kept separate fromrequirements.txtso the production image does not pull in pytest..gitignorecleanup:__pycache__/and*.pycadded;docs/plans/line dropped..claude/rules resolved during rebase against upstream commit40f21c5(kept upstream's specific.claude/settings.local.json,.claude/settings.json,.claude/worktreesrules)..github/workflows/test-python.yml): new workflow runspython -m pyteston every pull request tomaster. Note: the new check is informational-only until a maintainer adds it to the branch protection required-checks list formaster— that admin step is a follow-up. Per the branch protection query, the only required checks arelintandBuild website.Test results
python -m pytestexits 0--strict-markersenabledPR scope-check compliance
md_lint_check.ymlworkflow is unaffected)Rebase
The PR was rebased onto current master (18 commits ahead of the original base) with a single conflict resolution in
.gitignore. Used--force-with-leaseper the standing rule for security-critical repos.Out of scope (deferred to follow-up PRs)
Generate_RSS_Feed.pyandIdentify_Old_Issue_And_PR.py(network-dependent; the mocking pattern from this PR carries forward).Index.md, diff against the committed copy, fail on drift). This is the "higher-value" follow-up suggested in mackowski's review; the implementation is deferred to its own PR so it can be scoped on its own merits.