--- name: patch-coverage description: >- Procedure and guidelines for verifying and maintaining 100% patch test coverage on all modified and added lines across Keymaster PRs and branches. --- # Patch Coverage & Test Completeness Guide This skill provides step-by-step instructions for ensuring every change or bugfix introduced in Keymaster achieves thorough **patch test coverage** (exercising all modified/added lines) and satisfies repository quality gates. ## Core Principles 1. **Patch Coverage & Quality Gates**: - The repository configures an overall project test coverage floor of **>= 80%** in `pyproject.toml` (`[tool.coverage.report] fail_under = 80`). - Every new line or modified execution branch in a pull request should be accompanied by automated tests to ensure no regressions or untested branches. 2. **Branch & Edge Case Completeness**: - Cover both success (`True`, result objects) and failure branches (`False`, `None`, exceptions). - Test fallback and default paths (e.g. `_node_id` fallbacks when `_node` is `None`, disconnected clients, missing entities). - Test warning and error logging paths with pytest's `caplog` fixture to verify diagnostic log statements fire when intended. --- ## Workflow for Verifying Patch Coverage ### 1. Identify Changed Files and Lines Check your current git diff against the base branch (`upstream/main` or `main`): ```bash git diff upstream/main...HEAD --stat git diff upstream/main...HEAD custom_components/ ``` ### 2. Run Targeted Tests with Missing Line Reporting When running targeted tests on a single file or module, override `addopts` and pass `--cov-fail-under=0` so pytest scopes the terminal table to the target module without failing on the global 80% project threshold: ```bash # Example for provider modifications: pytest tests/providers/test_.py \ -o addopts="-m 'not slow and not perf'" \ --cov=custom_components.keymaster.providers. \ --cov-report=term-missing \ --cov-fail-under=0 # Example for coordinator modifications: pytest tests/test_coordinator.py \ -o addopts="-m 'not slow and not perf'" \ --cov=custom_components.keymaster.coordinator \ --cov-report=term-missing \ --cov-fail-under=0 ``` Inspect the `Missing` column in the terminal output to confirm that no newly added or edited line numbers in your diff are left uncovered. ### 3. Common Uncovered Line Patterns & Solutions - **`if not self._node: return None/False`**: - *Cause*: No test exercised the method when the provider is uninitialized or disconnected. - *Solution*: Add `test__no_node` asserting `None` or `False` when `provider._node = None`. - **`except Exception as e: _LOGGER.warning(...)`**: - *Cause*: Exception handling block was never triggered. - *Solution*: Add a unit test with `side_effect=RuntimeError("test")` and assert `caplog.text`. - **`node.node_id if node else self._node_id`**: - *Cause*: Ternary fallback branch when `node` is `None` not reached. - *Solution*: Add a test asserting `get_node_id()` returns `self._node_id` when `_node` is `None`. - **Verification retry branch**: - *Cause*: Logic handling transient write result or non-empty slot readback not tested. - *Solution*: Mock get/readback returning uncleared value and verify warning log + return `False`. ### 4. Assert Diagnostic Logging with `caplog` When testing diagnostic logging (especially `DEBUG` or `WARNING` messages), ensure `caplog.set_level` is set appropriately. Note that provider-specific fixtures (such as `zwave_provider` and `mock_zwave_node`) are defined within their respective test modules (e.g. `tests/providers/test_zwave_js.py`): ```python import logging from zwave_js_server.const import NodeStatus async def test_operation_skips_when_node_dead(zwave_provider, mock_zwave_node, caplog): """Test operation logs debug message and returns False when node is dead.""" caplog.set_level(logging.DEBUG) mock_zwave_node.status = NodeStatus.DEAD zwave_provider._node = mock_zwave_node result = await zwave_provider.async_clear_usercode(1) assert result is False assert "[ZWaveJSProvider] Node 14 is dead, skipping command" in caplog.text ``` ### 5. Final Full-Suite Verification Run the entire suite to verify overall coverage threshold and cross-module compatibility: ```bash pytest --cov=custom_components/keymaster --cov-report=term-missing ``` Or run via tox: ```bash tox -e py314 ```