Skip to content

fix(coverage): collect coverage from multiprocess child processes#1123

Open
vringar wants to merge 1 commit intomasterfrom
subprocess-coverage
Open

fix(coverage): collect coverage from multiprocess child processes#1123
vringar wants to merge 1 commit intomasterfrom
subprocess-coverage

Conversation

@vringar
Copy link
Contributor

@vringar vringar commented Feb 19, 2026

Summary

  • OpenWPM uses the third-party multiprocess library (a dill-based fork of stdlib multiprocessing), so coverage.py's built-in concurrency and patch settings don't instrument child processes
  • Additionally, multiprocess uses os._exit() after Process.run(), which skips atexit handlers and prevents coverage from saving data
  • Adds coverage.process_startup() and explicit cov.stop()/cov.save() in the Process wrapper, using a template method pattern (run/run_impl) so the logic lives in one place
  • Adds a pytest fixture to set COVERAGE_PROCESS_START and COVERAGE_FILE env vars during coverage runs
  • BrowserManager now uses the common Process wrapper and overrides run_impl() instead of run()

Fixes #1121

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements coverage collection for child processes spawned using the third-party multiprocess library. Since OpenWPM uses multiprocess (a dill-based fork of stdlib multiprocessing) rather than the standard library, coverage.py's built-in concurrency settings don't automatically instrument child processes. Additionally, multiprocess uses os._exit() which bypasses atexit handlers, preventing coverage data from being saved normally.

Changes:

  • Added a pytest fixture to set COVERAGE_PROCESS_START and COVERAGE_FILE environment variables during coverage runs
  • Implemented a template method pattern in the Process wrapper, with run() handling coverage startup/shutdown and subclasses overriding run_impl()
  • Updated BrowserManager to use the common Process wrapper and override run_impl() instead of run()

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
test/conftest.py Added session-scoped autouse fixture to configure coverage environment variables for child processes
openwpm/utilities/multiprocess_utils.py Implemented template method pattern with coverage.process_startup() at the start and explicit cov.stop()/cov.save() in finally block; added run_impl() method for subclasses
openwpm/browser_manager.py Changed BrowserManager to import Process from multiprocess_utils and renamed run() to run_impl() to work with the template method pattern

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link

codecov bot commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 25.00000% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 56.24%. Comparing base (8be0aeb) to head (792ea97).

Files with missing lines Patch % Lines
openwpm/utilities/multiprocess_utils.py 16.66% 15 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #1123       +/-   ##
===========================================
+ Coverage   37.32%   56.24%   +18.91%     
===========================================
  Files          35       36        +1     
  Lines        3475     3540       +65     
===========================================
+ Hits         1297     1991      +694     
+ Misses       2178     1549      -629     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

OpenWPM uses the third-party multiprocess library (not stdlib
multiprocessing), so coverage.py built-in concurrency and patch
settings do not instrument child processes. Additionally, multiprocess
uses os._exit() after Process.run(), which skips atexit handlers and
prevents coverage from saving data.

Fix by:
- Calling coverage.process_startup() at the start of each child process
- Explicitly saving coverage data in a finally block before os._exit()
- Using a template method pattern (run/run_impl) so coverage logic
  lives in one place in the Process wrapper
- Adding a pytest fixture to set COVERAGE_PROCESS_START and
  COVERAGE_FILE environment variables during test runs
- Having BrowserManager use the common Process wrapper and override
  run_impl() instead of run()
@vringar vringar force-pushed the subprocess-coverage branch from 2c281ad to 22e5e8f Compare February 19, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code coverage should cover all processes

1 participant

Comments