Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ jobs:
coverage-rate-reduction-failure: false
pycobertura-exception-failure: false
togglable-report: false
# Test case for report-low-coverage-only: file_full_coverage.py (100%) should be excluded
- path: test-low-coverage-only.xml
threshold: 70
fail: false
publish: true
diff: false
diff-branch: main
diff-storage: _xml_coverage_reports_low_coverage_only
coverage-summary-title: "Code Coverage Summary (low coverage only)"
exclude-detailed-coverage: false
uncovered-statements-increase-failure: false
new-uncovered-statements-failure: false
coverage-rate-reduction-failure: false
pycobertura-exception-failure: true
togglable-report: false
report-low-coverage-only: true
steps:
- name: Checkout Code 🛎
uses: actions/checkout@v4
Expand All @@ -302,3 +318,4 @@ jobs:
coverage-rate-reduction-failure: ${{ matrix.reports.coverage-rate-reduction-failure }}
pycobertura-exception-failure: ${{ matrix.reports.pycobertura-exception-failure }}
togglable-report: ${{ matrix.reports.togglable-report }}
report-low-coverage-only: ${{ matrix.reports.report-low-coverage-only }}
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,15 @@ Inisghts Engineering

* `togglable-report`:

_Description_: Make the code coverage report togglable.
_Description_: Wrap the detailed coverage report in a collapsible `<details>` block in the PR comment, so it is hidden by default and can be expanded on demand.

_Required_: `false`

_Default_: `False`

* `report-low-coverage-only`:

_Description_: When `true`, the detailed coverage report will only include files where coverage is less than 100%. Files with full coverage are omitted to keep the report focused on files that need attention. The `TOTAL` summary line is always included regardless of this setting. Has no effect when `exclude-detailed-coverage` is `true`.

_Required_: `false`

Expand Down
13 changes: 13 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ inputs:
description: Make the code coverage report togglable.
required: false
default: false
report-low-coverage-only:
description: |
When true, the detailed coverage report will only include files where
coverage is less than 100%. The TOTAL summary line is always included.
required: false
default: false
exclude-detailed-coverage:
description: |
Whether a detailed coverage report should be excluded from the PR comment.
Expand Down Expand Up @@ -121,6 +127,13 @@ runs:
mkdir -p coverage-action
cp ${{ inputs.path }} coverage-action/
pycobertura show ${{ inputs.path }} --output .coverage-output
if [[ "${{ inputs.report-low-coverage-only }}" == "true" ]]
then {
# Keep header lines, the TOTAL line, and any file with missed lines (Miss != 0)
awk 'NR<=2 || /^TOTAL / || $3 != 0' .coverage-output > .coverage-output.filtered
mv .coverage-output.filtered .coverage-output
}
fi
cat .coverage-output
shell: bash

Expand Down
12 changes: 9 additions & 3 deletions fixtures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,15 @@ This directory contains test fixtures for the Code Coverage Report Action. Each

#### `test-togglable-report.xml`
- **Purpose**: Tests `togglable-report` flag
- **Coverage**: 85% line coverage
- **Coverage**: 85% line coverage (single file: `togglable_test_file.py`)
- **Scenario**: Normal coverage report
- **Expected**: Should generate collapsible report format when flag is enabled
- **Expected**: When `togglable-report: true`, the detailed coverage table is wrapped in a collapsible `<details>` block in the PR comment

#### `test-low-coverage-only.xml`
- **Purpose**: Tests `report-low-coverage-only` flag
- **Coverage**: 75% overall (3 files: `file_full_coverage.py` at 100%, `file_partial_coverage.py` at 60%, `file_low_coverage.py` at 30%)
- **Scenario**: Mix of fully-covered and partially-covered files
- **Expected**: When `report-low-coverage-only: true`, only `file_partial_coverage.py` and `file_low_coverage.py` appear in the report; `file_full_coverage.py` is omitted; the TOTAL line is always shown

### Comprehensive Testing

Expand All @@ -111,7 +117,7 @@ The test matrix in `.github/workflows/test.yaml` includes test cases for:
3. **Positive cases**: Scenarios where failure flags should NOT trigger
4. **Combined scenarios**: Multiple flags enabled together
5. **Exception handling**: Both enabled and disabled exception failure modes
6. **Report formatting**: Togglable reports with and without detailed coverage
6. **Report formatting**: Togglable reports (collapsible `<details>`) with and without detailed coverage
7. **Edge cases**: Comprehensive testing with multiple files and varying coverage

## Usage
Expand Down
57 changes: 57 additions & 0 deletions fixtures/test-low-coverage-only.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" ?>
<coverage branch-rate="0" line-rate="0.75" timestamp="1460488624050" version="4.0.3">
<sources>
<source></source>
</sources>
<packages>
<package branch-rate="0" complexity="0" line-rate="0.75" name=".">
<classes>
<class branch-rate="0" complexity="0" filename="file_full_coverage.py" line-rate="1.0" name="file_full_coverage.py">
<methods/>
<lines>
<line hits="1" number="1" branch="false"/>
<line hits="1" number="2" branch="false"/>
<line hits="1" number="3" branch="false"/>
<line hits="1" number="4" branch="false"/>
<line hits="1" number="5" branch="false"/>
<line hits="1" number="6" branch="false"/>
<line hits="1" number="7" branch="false"/>
<line hits="1" number="8" branch="false"/>
<line hits="1" number="9" branch="false"/>
<line hits="1" number="10" branch="false"/>
</lines>
</class>
<class branch-rate="0" complexity="0" filename="file_partial_coverage.py" line-rate="0.6" name="file_partial_coverage.py">
<methods/>
<lines>
<line hits="1" number="1" branch="false"/>
<line hits="1" number="2" branch="false"/>
<line hits="0" number="3" branch="false"/>
<line hits="0" number="4" branch="false"/>
<line hits="1" number="5" branch="false"/>
<line hits="1" number="6" branch="false"/>
<line hits="0" number="7" branch="false"/>
<line hits="0" number="8" branch="false"/>
<line hits="1" number="9" branch="false"/>
<line hits="1" number="10" branch="false"/>
</lines>
</class>
<class branch-rate="0" complexity="0" filename="file_low_coverage.py" line-rate="0.3" name="file_low_coverage.py">
<methods/>
<lines>
<line hits="1" number="1" branch="false"/>
<line hits="0" number="2" branch="false"/>
<line hits="0" number="3" branch="false"/>
<line hits="0" number="4" branch="false"/>
<line hits="1" number="5" branch="false"/>
<line hits="0" number="6" branch="false"/>
<line hits="0" number="7" branch="false"/>
<line hits="0" number="8" branch="false"/>
<line hits="1" number="9" branch="false"/>
<line hits="0" number="10" branch="false"/>
</lines>
</class>
</classes>
</package>
</packages>
</coverage>
Loading