diff --git a/articles/_release-notes/v0.13.x.md b/articles/_release-notes/v0.13.x.md index dd8bc92..12641d7 100644 --- a/articles/_release-notes/v0.13.x.md +++ b/articles/_release-notes/v0.13.x.md @@ -6,6 +6,32 @@ list_title: Versions 0.13.x # Release Notes - Versions 0.13.x +## Version 0.13.22 + +### New Features +* Coverage is now collected from the Python subprocesses a covered task spawns, + and from anything those spawn in turn. PyBuilder plants a startup hook into + the site directories of the VEnvs it builds and hands the active + *coverage.py* configuration over through the environment, so a process that + starts from one of those VEnvs measures itself from its own startup. Code + that only ever runs in a subprocess - a build backend invoked by `pip`, a + program under test started with `subprocess` - is no longer reported as + uncovered. Nested PyBuilder builds started from an integration test plant the + hook into their own VEnvs, so the whole process tree is measured. Controlled + by the new `coverage_subprocesses` property, on by default, and settable per + task as `ut_coverage_subprocesses` / `it_coverage_subprocesses`. With + `--no-venvs` nothing is planted into the Python you started the build with; + subprocess measurement rides on *coverage.py*'s own startup hook there. +* Measurement in the unit test tool process now starts at interpreter startup + rather than once the tool has loaded, so imports and module level code are + measured too. + +### Changed Features +* The `coverage` plugin now requires *coverage.py* 7.13 or newer. The + configuration hand-off needs `COVERAGE_PROCESS_CONFIG` and + `CoverageConfig.serialize`, and `--no-venvs` builds additionally need + *coverage.py*'s own startup hook, which is what 7.13 adds. + ## Version 0.13.21 ### New Features diff --git a/documentation/manual.md b/documentation/manual.md index 1f121d6..16b5c93 100644 --- a/documentation/manual.md +++ b/documentation/manual.md @@ -529,12 +529,45 @@ override: - A `CoverageTool` is registered with the reactor - The Python environment for the covered task is overridden to inject a coverage shim script into the subprocess + - A startup hook is planted into the site directories of the VEnvs PyBuilder built, + and the active coverage configuration is handed to the task through the + environment, so that further subprocesses measure themselves - The covered task (e.g. `run_unit_tests`) is re-executed with coverage active - Coverage data is collected from the subprocess via `coverage.combine()` 3. **After execution**: Coverage data from all covered tasks is aggregated, thresholds are checked, and reports are generated. +### Subprocess Measurement + +Code that only ever runs in a subprocess - a build backend `pip` invokes, a program +under test started with `subprocess`, a worker started with `os.system()` - would +otherwise report as entirely uncovered: the VEnvs PyBuilder builds into have no +`coverage` installed, and nothing running at interpreter startup to switch it on. + +The startup hook PyBuilder plants closes that gap. Any Python process started from one +of those VEnvs picks the hook up from its own `site` processing, imports `coverage` +from PyBuilder's plugin VEnv without leaving it on the path, and starts measuring +before the process runs a line of its own code. That also means imports and module +level code are measured, not just what runs once the test harness has control. The +collected data is written alongside the covered task's own data and combined into it. + +The hand-off is inherited, so this applies to the whole process tree, including the +VEnvs created by a nested PyBuilder build running inside an integration test. + +With `--no-venvs` there are no VEnvs of PyBuilder's making, and PyBuilder plants nothing +into the Python you started the build with. Subprocesses are still measured there, by +*coverage.py*'s own startup hook, which that Python has because `--no-venvs` installs +`coverage` into it. + +Set `coverage_subprocesses` to `False` to turn this off, either for the whole project +or for a single task (`ut_coverage_subprocesses`, `it_coverage_subprocesses`). +Measuring every process in the tree is not free, and that includes processes you may +not care about, such as `pip`. + +This requires *coverage.py* 7.13 or newer, which is where its own startup hook - the +only thing that can act on the hand-off under `--no-venvs` - arrived. + ### Thresholds Coverage enforces three independent threshold types: diff --git a/documentation/plugins.md b/documentation/plugins.md index b6cc0f6..de9898d 100644 --- a/documentation/plugins.md +++ b/documentation/plugins.md @@ -142,6 +142,13 @@ Use the ```python.coverage``` module to activate coverage.
ut_coverage_subprocesses for unit tests or it_coverage_subprocesses for integration tests.