Skip to content

Implement LCOV format reporting - #70

Merged
jaltmayerpizzorno merged 6 commits into
plasma-umass:mainfrom
amartani:lcov-report
Jul 30, 2026
Merged

Implement LCOV format reporting#70
jaltmayerpizzorno merged 6 commits into
plasma-umass:mainfrom
amartani:lcov-report

Conversation

@amartani

@amartani amartani commented Nov 9, 2025

Copy link
Copy Markdown
Contributor

Implements generating coverage reporting in LCOV format, controlled by the flag --lcov.

Changes:

  • Added lcovreport.py module with LcovReporter class for generating LCOV format output
  • Integrated LCOV reporting into slipcover.py with print_lcov() function
  • Added --lcov command-line flag to __main__.py for selecting LCOV output
  • Added --lcov-test-name and --lcov-comment, common in other LCOV tools
  • Added tests for LCOV reporting (with and without branches)

The LCOV format includes:

  • TN: Test name (optional)
  • SF: Source file path
  • BRDA: Branch coverage data (when --branch is used)
  • BRF/BRH: Branch statistics
  • DA: Line coverage data
  • LF/LH: Line statistics
  • end_of_record marker

Usage examples:

  python -m slipcover --lcov --out coverage.lcov script.py
  python -m slipcover --branch --lcov --out coverage.lcov script.py

No specific issue is tracking this, but LCOV is a widely-used report format for tooling like genhtml, Coveralls, and Codecov (see #30, a closed issue asking generally about Codecov compatibility) -- flagging in case it's relevant to anyone following those threads.

Implements generating coverage reporting in LCOV format, controlled by the flag `--lcov`.

Changes:
- Added lcovreport.py module with LcovReporter class for generating LCOV format output
- Integrated LCOV reporting into slipcover.py with print_lcov() function
- Added --lcov command-line flag to __main__.py for selecting LCOV output
- Added --lcov-test-name and --lcov-comment, common in other LCOV tools
- Exported print_lcov in __init__.py to make it accessible
- Added tests for LCOV reporting (with and without branches)

The LCOV format includes:
- TN: Test name (optional)
- SF: Source file path
- BRDA: Branch coverage data (when --branch is used)
- BRF/BRH: Branch statistics
- DA: Line coverage data
- LF/LH: Line statistics
- end_of_record marker

Usage examples:
  python -m slipcover --lcov --out coverage.lcov script.py
  python -m slipcover --branch --lcov --out coverage.lcov script.py
@amartani
amartani marked this pull request as ready for review November 9, 2025 05:16
@emeryberger
emeryberger requested a review from Copilot January 14, 2026 18:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 LCOV format coverage reporting for slipcover, enabling output compatible with tools that consume LCOV format. The implementation adds a new LcovReporter class and integrates it into the CLI with --lcov flag support, along with optional test name and comment features.

Changes:

  • Added LCOV format reporting with line and branch coverage support
  • Integrated LCOV output option into CLI with --lcov, --lcov-test-name, and --lcov-comment flags
  • Added comprehensive test coverage for LCOV functionality including branches, test names, and comments

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/slipcover/lcovreport.py New module implementing LCOV format reporter with line and branch coverage
src/slipcover/slipcover.py Added print_lcov() function to expose LCOV reporting API
src/slipcover/main.py Integrated LCOV CLI flags and output handling in both merge and normal execution modes
src/slipcover/init.py Exported print_lcov in public API
tests/test_coverage.py Added test suite for LCOV reporting covering various scenarios

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

Comment thread src/slipcover/lcovreport.py Outdated
Comment thread src/slipcover/lcovreport.py Outdated
Comment thread src/slipcover/lcovreport.py Outdated
Comment thread src/slipcover/lcovreport.py Outdated
Comment thread src/slipcover/lcovreport.py Outdated
@amartani

Copy link
Copy Markdown
Contributor Author

@emeryberger addressed Copilot's findings and merged updated main. ptal! Thanks!

jaltmayerpizzorno and others added 3 commits July 30, 2026 14:04
…d tests

SF: entries used the raw coverage-dict key, which on Windows contains
backslashes (PathSimplifier renders WindowsPath natively) -- normalize
to '/' as xmlreport.py already does, for genhtml/lcov tooling
compatibility.

get_branch_info() took a missing_arcs parameter (built by
get_missing_branch_arcs()) that it never used -- it recomputed
is_taken independently via an O(n) list-membership check per branch.
Replaced with a proper O(1) set lookup instead of just deleting the
dead code, normalizing branch tuples first since --merge round-trips
coverage data through JSON, which deserializes branch arcs as
unhashable lists rather than tuples.

Added tests for: Windows path normalization, empty/100%/0% coverage
files, --merge --lcov (previously untested, and the JSON round-trip
issue above only surfaces through this path), and a test asserting
exact per-branch BRDA taken/not-taken values -- the existing branch
test only checks aggregate BRF/BRH counts, which stay identical even
if taken/not-taken were fully inverted, since this fixture happens to
have a symmetric 2-taken/2-missing split.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Backslashes inside an f-string expression part (`{...}`) are only
allowed since Python 3.12 (PEP 701); on 3.9-3.11 this was a hard
SyntaxError at import time, breaking every job in that range in CI.
Move the .replace() call to a separate statement before the f-string.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
An empty module compiles to a single line-1 entry on Python 3.9/3.10
(findlinestarts -> (0, 1)) but to (0, 0) on 3.11+, which slipcover's
own line-collection already filters out as non-real. So an empty .py
file legitimately has 1 trivially-executed line on 3.9/3.10 and 0 on
3.11+ -- both correct, and not something to "fix" in slipcover itself.
The test's hardcoded LF:0/LH:0 assumption only held on 3.11+. Assert
the actual invariant instead: no DA: line reports a zero hit count,
i.e. nothing is missing, regardless of the exact (version-dependent)
line count.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jaltmayerpizzorno
jaltmayerpizzorno merged commit d5bab6e into plasma-umass:main Jul 30, 2026
28 checks passed
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.

3 participants