docs(dev): correct the test-running and rgbmatrix build instructions

- HOW_TO_RUN_TESTS: coverage is not collected by a plain pytest run and
  pytest.ini has no threshold; the only one is --cov-fail-under=52 in the
  core unit-test job of .github/workflows/test.yml, which runs the whole
  test/ tree (not an allowlist). Almost no tests carry markers, so
  -m integration / -m slow select nothing; drop them and -m unit as the
  quick check. Replace the hardcoded /home/chuck path.
- DEVELOPMENT: the rgbmatrix package is built with pip install . from
  the submodule root (scikit-build-core + CMake + Ninja), as
  first_time_install.sh does; there is no make build-python /
  bindings/python step, and the build deps are python-dev-is-python3,
  cmake and ninja-build, not cython3/scons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-22 16:27:12 -04:00
co-authored by Claude Opus 5.5
parent b2a3c17fad
commit d54a6c8545
2 changed files with 47 additions and 71 deletions
+10 -9
View File
@@ -43,16 +43,21 @@ git submodule update --init --recursive rpi-rgb-led-matrix-master
#### Building the Submodule
After initializing the submodule, you need to build the Python bindings:
After initializing the submodule, build and install the `rgbmatrix` Python
package from the submodule root. Upstream's `pyproject.toml` builds it with
scikit-build-core, CMake and Ninja; there is no separate `make` step:
```bash
cd rpi-rgb-led-matrix-master
make build-python
cd bindings/python
python3 -m pip install --break-system-packages .
```
**Note:** The `first_time_install.sh` script automates this process during installation.
On a board with 1 GB of RAM or less, cap the compile so it doesn't run out of
memory: `CMAKE_BUILD_PARALLEL_LEVEL=1 python3 -m pip install --break-system-packages .`
**Note:** The `first_time_install.sh` script automates this process during
installation, including the parallelism cap and a temporary swapfile on
low-memory boards.
#### Troubleshooting
@@ -69,7 +74,7 @@ git submodule update --init --recursive rpi-rgb-led-matrix-master
**Build fails:**
Ensure you have the required build dependencies installed:
```bash
sudo apt install -y build-essential python3-dev cython3 scons
sudo apt install -y build-essential python-dev-is-python3 cmake ninja-build
```
**Import error for `rgbmatrix` module:**
@@ -97,8 +102,6 @@ When setting up CI/CD pipelines, ensure submodules are initialized before buildi
- name: Build rpi-rgb-led-matrix
run: |
cd rpi-rgb-led-matrix-master
make build-python
cd bindings/python
pip install .
```
@@ -110,8 +113,6 @@ variables:
build:
script:
- cd rpi-rgb-led-matrix-master
- make build-python
- cd bindings/python
- pip install .
```
+37 -62
View File
@@ -60,20 +60,18 @@ pytest test/test_display_controller.py::TestDisplayControllerModeRotation::test_
### Run Tests by Marker
The tests use markers to categorize them:
`pytest.ini` declares the markers `unit`, `integration`, `hardware`, `slow`
and `plugin` (with `--strict-markers`, so a typo in a marker name is an
error). Few tests are marked: only a handful carry `unit`, and none currently
carry `integration`, `slow` or `hardware`, so `-m integration` and `-m slow`
select nothing. Select tests by file, directory or `-k` instead.
```bash
# Run only unit tests (fast, isolated)
pytest -m unit
# What CI runs for the core suites (excludes anything marked hardware)
pytest -m "not hardware" test/ --ignore=test/plugins
# Run only integration tests
pytest -m integration
# Run tests that don't require hardware
pytest -m "not hardware"
# Run slow tests
pytest -m slow
# Tests whose name matches an expression
pytest -k "config and not secrets"
```
### Run Tests in a Directory
@@ -138,58 +136,35 @@ pytest -sv
## Coverage Reports
The test suite is configured to generate coverage reports.
### View Coverage in Terminal
Coverage is not collected by a plain `pytest` run: `pytest.ini` deliberately
has no coverage flags, so local runs stay fast. Ask for it explicitly
(needs `pytest-cov`, which is in `requirements-test.txt`):
```bash
# Coverage is automatically shown when running pytest
pytest
# Terminal summary
pytest --cov=src --cov=web_interface --cov-report=term test/ --ignore=test/plugins
# The output will show something like:
# ----------- coverage: platform linux, python 3.11.5 -----------
# Name Stmts Miss Cover Missing
# ---------------------------------------------------------------------
# src/display_controller.py 450 120 73% 45-67, 89-102
# HTML report in htmlcov/
pytest --cov=src --cov=web_interface --cov-report=html test/ --ignore=test/plugins
```
### Generate HTML Coverage Report
```bash
# HTML report is automatically generated in htmlcov/
pytest
# Then open the report in your browser
# On Linux:
xdg-open htmlcov/index.html
# On macOS:
open htmlcov/index.html
# On Windows:
start htmlcov/index.html
```
The HTML report shows:
- Line-by-line coverage
- Files with low coverage highlighted
- Interactive navigation
Then open `htmlcov/index.html` in your browser (`xdg-open` on Linux, `open`
on macOS, `start` on Windows).
### Coverage Threshold
The tests are configured to fail if coverage drops below 30%. To change this, edit `pytest.ini`:
```ini
--cov-fail-under=30 # Change this value
```
The only threshold is in CI: the core unit-test job in
[`.github/workflows/test.yml`](../.github/workflows/test.yml) runs with
`--cov-fail-under=52`. To check it locally, add that flag to the command
above.
## Common Test Scenarios
### Run Tests After Making Changes
```bash
# Quick test run (just unit tests)
pytest -m unit
# Quick run: just the tests for the area you changed
pytest test/test_config_manager.py
# Full test suite
pytest
@@ -283,8 +258,8 @@ test/
If you see import errors:
```bash
# Make sure you're in the project root
cd /home/chuck/Github/LEDMatrix
# Make sure you're in the project root (wherever you cloned it)
cd ~/LEDMatrix
# Check Python path
python -c "import sys; print(sys.path)"
@@ -325,18 +300,18 @@ If coverage reports aren't generating:
# Make sure pytest-cov is installed
pip install pytest-cov
# Run with explicit coverage
pytest --cov=src --cov-report=html
# Coverage is opt-in; ask for it explicitly
pytest --cov=src --cov=web_interface --cov-report=html
```
## Continuous Integration
The repo runs the pytest suite via
[`.github/workflows/test.yml`](../.github/workflows/test.yml) on every
push and pull request: a plugin-safety job (harness, visual rendering
and plugin-matrix tests) plus a unit-test job that runs an explicit
allowlist of suites — new test files must be added to that list to run
in CI. Release version consistency is checked by
push and pull request: a plugin-safety job that runs `test/plugins/`, and a
core unit-test job that runs the whole `test/` tree except `test/plugins/`
with `-m "not hardware"` and enforces coverage (`--cov-fail-under=52`). New
test files are picked up automatically. Release version consistency is checked by
[`.github/workflows/release-version-check.yml`](../.github/workflows/release-version-check.yml).
Bandit, flake8, mypy and gitleaks run as pre-commit hooks (see
`.pre-commit-config.yaml`), not in CI.
@@ -345,17 +320,17 @@ Bandit, flake8, mypy and gitleaks run as pre-commit hooks (see
1. **Run tests before committing**:
```bash
pytest -m unit # Quick check
pytest test/test_<area>.py # Quick check of what you touched
```
2. **Run full suite before pushing**:
```bash
pytest # Full test suite with coverage
pytest # Full test suite (add --cov flags for coverage)
```
3. **Fix failing tests immediately** - Don't let them accumulate
4. **Keep coverage above threshold** - Aim for 70%+ coverage
4. **Keep coverage above threshold** - CI fails below 52%
5. **Write tests for new features** - Add tests when adding new functionality
@@ -363,9 +338,9 @@ Bandit, flake8, mypy and gitleaks run as pre-commit hooks (see
```bash
# Most common commands
pytest # Run all tests with coverage
pytest # Run all tests (no coverage)
pytest -v # Verbose output
pytest -m unit # Run only unit tests
pytest test/test_x.py # Run one file
pytest -k "test_name" # Run tests matching pattern
pytest --cov=src # Generate coverage report
pytest -x # Stop on first failure