Skip to content

Commit 7b9e112

Browse files
committed
chore: more claude unit test improvements
- install pyright and pyright-lsp for better python symbol navigation - overhaul the unit-tests skill to limit coverage generation to domain tests
1 parent c0b0791 commit 7b9e112

6 files changed

Lines changed: 80 additions & 10 deletions

File tree

.claude/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
"Skill(quality-tests)",
55
"Skill(unit-tests)"
66
]
7+
},
8+
"enabledPlugins": {
9+
"pyright-lsp@anthropic-tools": true
710
}
811
}

.claude/skills/unit-tests/SKILL.md

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@ allowed-tools: Bash(docker *), Bash(make *)
77

88
## Arguments
99

10-
`<TEST_FILES>` (optional): One or more test file paths or pytest node IDs to run. When provided, only the specified tests are run and coverage is disabled (`--no-cov`). When omitted, the full test suite runs with coverage enabled.
10+
`<TEST_FILES>` (optional): One or more folders, test file paths, or pytest node IDs to run. Coverage is only enabled when a single folder representing a code domain is provided or no arguments are provided.
1111

1212
Examples:
1313
- `/unit-tests` — run all tests with coverage
14+
- `/unit-tests enterprise_access/apps/bffs` — run all bff domain tests with domain-only coverage
1415
- `/unit-tests enterprise_access/apps/customer_billing/tests/test_models.py` — run one test file without coverage
1516
- `/unit-tests enterprise_access/apps/subsidy_access_policy/tests/test_models.py enterprise_access/apps/content_assignments/tests/test_api.py` — run multiple test files without coverage
1617
- `/unit-tests enterprise_access/apps/customer_billing/tests/test_models.py::TestSomeClass::test_method` — run a single test by node ID without coverage
1718

19+
## Routing rules (evaluate in order)
20+
21+
- **No arguments** → Step 2c (whole-project tests + whole-project coverage)
22+
- **Single argument that is a directory** (no `.py`, no `::`) → Step 2b (domain tests + domain coverage). Never enable coverage when testing specific files — only for domain or whole-project runs.
23+
- **Everything else** (`.py` files, node IDs, multiple args) → Step 2a (targeted tests, NO coverage)
24+
1825
## Steps
1926

2027
### 1. Make sure the app container is running
@@ -31,16 +38,49 @@ Start the app container if not running:
3138
make dev.up
3239
```
3340

34-
### 2. Run unit tests
41+
### 2a. Run specific unit test files or functions
3542

36-
If `<TEST_FILES>` argument(s) are given, run only those tests with coverage disabled:
43+
If `<TEST_FILES>` specify .py files or functions/classes within, run only those tests using `pytest.local.ini` to disable coverage and warnings:
3744

3845
```bash
39-
docker exec enterprise-access.app bash -c "DJANGO_SETTINGS_MODULE=enterprise_access.settings.test pytest --no-cov <TEST_FILES>"
46+
docker exec enterprise-access.app bash -c "pytest -c pytest.local.ini <TEST_FILES>"
4047
```
4148

42-
If no arguments are given, run the full test suite with coverage enabled:
49+
Example `<TEST_FILES>` which match this case:
50+
- enterprise_access/apps/customer_billing/tests/test_models.py
51+
- enterprise_access/apps/subsidy_access_policy/tests/test_models.py enterprise_access/apps/content_assignments/tests/test_api.py
52+
- enterprise_access/apps/customer_billing/tests/test_models.py::TestSomeClass::test_method
53+
54+
Never enable coverage reports (by adding `--cov`) when only testing specific files, since the results will be misleading.
55+
56+
### 2b. Run domain unit tests and generate domain-only coverage
57+
58+
If `<TEST_FILES>` specifies a single directory which represent a domain, such as a django app, enable coverage.
59+
60+
Convert the directory path to a Python module path for `--cov`: replace `/` with `.` and strip any trailing slash. Example: `enterprise_access/apps/bffs/``enterprise_access.apps.bffs`
4361

4462
```bash
45-
docker exec enterprise-access.app bash -c "DJANGO_SETTINGS_MODULE=enterprise_access.settings.test pytest"
63+
docker exec enterprise-access.app bash -c "pytest -c pytest.local.ini <TEST_DOMAIN> --cov=<MODULE_PATH_OF_TEST_DOMAIN>"
64+
65+
# Example: <TEST_FILES> is "enterprise_access/apps/bffs"
66+
docker exec enterprise-access.app bash -c "pytest -c pytest.local.ini enterprise_access/apps/bffs --cov=enterprise_access.apps.bffs"
4667
```
68+
69+
Example `<TEST_FILES>` which match this case:
70+
- enterprise_access/apps/api
71+
- enterprise_access/apps/api_client/
72+
- enterprise_access/apps/bffs
73+
- enterprise_access/apps/content_assignments/
74+
- enterprise_access/apps/customer_billing/
75+
76+
Whole-domain coverage will be reported in the console output. Specific line numbers with missing coverage will be reported.
77+
78+
### 2c. Run whole-project unit tests and generate coverage
79+
80+
If no arguments are given, assume the user wants to run the full test suite for the entire project:
81+
82+
```bash
83+
docker exec enterprise-access.app bash -c "make test"
84+
```
85+
86+
Whole-project coverage will be reported in the console output. Specific line numbers with missing coverage will be reported.

pytest.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# Standard settings used by CI and Makefile targets.
2+
#
3+
# Designed to run all tests and produce comprehensive coverage reporting.
4+
#
5+
# Example usage:
6+
# ```
7+
# pytest
8+
# ```
19
[pytest]
210
DJANGO_SETTINGS_MODULE = enterprise_access.settings.test
311
addopts = --cov enterprise_access --cov-report term-missing --cov-report xml

pytest.local.ini

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
1-
# This makes it easier to get coverage reports for only specific modules
2-
# when running pytest locally, for example:
3-
# pytest -x enterprise_access/apps/events/ --cov=enterprise_access.apps.events -c pytest.local.ini
1+
# pytest settings optimized for development cycles.
2+
#
3+
# Differences from pytest.ini:
4+
# - Removing `--cov enterprise_access` makes it possible to scope coverage reports to specific modules.
5+
# - Warning are ignored.
6+
#
7+
# Example usage:
8+
# ```
9+
# # Test only one domain and report coverage only for that domain:
10+
# pytest -c pytest.local.ini enterprise_access/apps/events/ --cov=enterprise_access.apps.events
11+
# pytest -c pytest.local.ini enterprise_access/apps/bffs/ --cov=enterprise_access.apps.bffs
12+
#
13+
# # Test only one file or function without generating coverage.
14+
# pytest -c pytest.local.ini enterprise_access/apps/bffs/tests/test_checkout_handlers.py
15+
# ```
416
[pytest]
5-
addopts = --cov-report term-missing --cov-report xml -W ignore --ds=enterprise_access.settings.test
17+
DJANGO_SETTINGS_MODULE = enterprise_access.settings.test
18+
addopts = --cov-report term-missing --cov-report xml -W ignore
619
norecursedirs = .* docs requirements site-packages scripts
720

821
# Filter depr warnings coming from packages that we can't control.

requirements/dev.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
diff-cover # Changeset diff test coverage
77
edx-i18n-tools # For i18n_tool dummy
88
django-debug-toolbar # For debugging Django
9+
pyright # For optimizing Claude Code reads.
910
#transifex-client # For managing translations

requirements/dev.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@ nh3==0.3.3
439439
# via
440440
# -r requirements/validation.txt
441441
# readme-renderer
442+
nodeenv==1.10.0
443+
# via pyright
442444
oauthlib==3.3.1
443445
# via
444446
# -r requirements/validation.txt
@@ -557,6 +559,8 @@ pyproject-hooks==1.2.0
557559
# -r requirements/pip-tools.txt
558560
# build
559561
# pip-tools
562+
pyright==1.1.408
563+
# via -r requirements/dev.in
560564
pytest==9.0.2
561565
# via
562566
# -r requirements/validation.txt
@@ -707,6 +711,7 @@ typing-extensions==4.15.0
707711
# cattrs
708712
# django-countries
709713
# edx-opaque-keys
714+
# pyright
710715
# referencing
711716
# stripe
712717
tzdata==2025.3

0 commit comments

Comments
 (0)