-
Notifications
You must be signed in to change notification settings - Fork 1
Add unit test coverage reports to CI for macOS tests #172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
f9c71dd
Initial plan for adding code coverage reporting
Copilot c0f92fd
Add code coverage reporting to CI for Swift 6.2 tests
Copilot befff89
Add documentation comment for CODECOV_TOKEN
Copilot 1e2cb1e
Add comprehensive coverage documentation
Copilot 03ca1b7
Generalize coverage to all platforms: macOS and Ubuntu, Swift 6.1 andβ¦
Copilot f524a94
Revert coverage to macOS only, remove Ubuntu coverage
Copilot f1277f6
Filter coverage to only include project source files, exclude dependeβ¦
Copilot 74049ed
Fix Codecov upload: use single flag, upload filtered JSON, recalculatβ¦
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -142,7 +142,82 @@ jobs: | |
| - name: Decompress Build | ||
| run: unzip build.zip | ||
| - name: Test JBird | ||
| run: swift test | ||
| run: swift test --enable-code-coverage | ||
| - name: Generate Coverage Report | ||
| run: | | ||
| COVERAGE_JSON=$(swift test --show-codecov-path) | ||
| echo "Coverage report location: $COVERAGE_JSON" | ||
|
|
||
| # Create filtered coverage JSON with only project source files | ||
| # This excludes Swift package dependencies from the coverage report | ||
| FILTERED_JSON="${COVERAGE_JSON}.filtered" | ||
| jq '.data[0].files |= map(select(.filename | contains("/Sources/")))' "$COVERAGE_JSON" > "$FILTERED_JSON" | ||
|
|
||
| # Recalculate totals from filtered data | ||
| jq '.data[0].totals = { | ||
| lines: { | ||
| count: ([.data[0].files[].summary.lines.count] | add // 0), | ||
| covered: ([.data[0].files[].summary.lines.covered] | add // 0), | ||
| percent: (([.data[0].files[].summary.lines.covered] | add // 0) * 100.0 / ([.data[0].files[].summary.lines.count] | add // 1)) | ||
| }, | ||
| functions: { | ||
| count: ([.data[0].files[].summary.functions.count] | add // 0), | ||
| covered: ([.data[0].files[].summary.functions.covered] | add // 0), | ||
| percent: (([.data[0].files[].summary.functions.covered] | add // 0) * 100.0 / ([.data[0].files[].summary.functions.count] | add // 1)) | ||
| }, | ||
| regions: { | ||
| count: ([.data[0].files[].summary.regions.count] | add // 0), | ||
| covered: ([.data[0].files[].summary.regions.covered] | add // 0), | ||
| percent: (([.data[0].files[].summary.regions.covered] | add // 0) * 100.0 / ([.data[0].files[].summary.regions.count] | add // 1)) | ||
| } | ||
| }' "$FILTERED_JSON" > "${FILTERED_JSON}.tmp" && mv "${FILTERED_JSON}.tmp" "$FILTERED_JSON" | ||
|
|
||
| # Extract coverage statistics from filtered data | ||
| LINES_PERCENT=$(jq -r '.data[0].totals.lines.percent' "$FILTERED_JSON") | ||
| LINES_COVERED=$(jq -r '.data[0].totals.lines.covered' "$FILTERED_JSON") | ||
| LINES_TOTAL=$(jq -r '.data[0].totals.lines.count' "$FILTERED_JSON") | ||
|
|
||
| FUNCTIONS_PERCENT=$(jq -r '.data[0].totals.functions.percent' "$FILTERED_JSON") | ||
| FUNCTIONS_COVERED=$(jq -r '.data[0].totals.functions.covered' "$FILTERED_JSON") | ||
| FUNCTIONS_TOTAL=$(jq -r '.data[0].totals.functions.count' "$FILTERED_JSON") | ||
|
|
||
| REGIONS_PERCENT=$(jq -r '.data[0].totals.regions.percent' "$FILTERED_JSON") | ||
| REGIONS_COVERED=$(jq -r '.data[0].totals.regions.covered' "$FILTERED_JSON") | ||
| REGIONS_TOTAL=$(jq -r '.data[0].totals.regions.count' "$FILTERED_JSON") | ||
|
|
||
| # Round percentages to 2 decimal places | ||
| LINES_PERCENT=$(printf "%.2f" "$LINES_PERCENT") | ||
| FUNCTIONS_PERCENT=$(printf "%.2f" "$FUNCTIONS_PERCENT") | ||
| REGIONS_PERCENT=$(printf "%.2f" "$REGIONS_PERCENT") | ||
|
|
||
| # Create markdown summary | ||
| cat >> $GITHUB_STEP_SUMMARY << EOF | ||
| ## π Code Coverage Report (macOS, Swift ${{ matrix.swift }}) | ||
|
|
||
| | Metric | Coverage | Covered | Total | | ||
| |--------|----------|---------|-------| | ||
| | **Lines** | **${LINES_PERCENT}%** | ${LINES_COVERED} | ${LINES_TOTAL} | | ||
| | **Functions** | **${FUNCTIONS_PERCENT}%** | ${FUNCTIONS_COVERED} | ${FUNCTIONS_TOTAL} | | ||
| | **Regions** | **${REGIONS_PERCENT}%** | ${REGIONS_COVERED} | ${REGIONS_TOTAL} | | ||
|
|
||
| β¨ Coverage report generated successfully! | ||
| EOF | ||
|
|
||
| echo "Lines Coverage: ${LINES_PERCENT}%" | ||
| echo "Functions Coverage: ${FUNCTIONS_PERCENT}%" | ||
| echo "Regions Coverage: ${REGIONS_PERCENT}%" | ||
|
|
||
| # Save filtered coverage path for Codecov upload | ||
| echo "COVERAGE_JSON=$FILTERED_JSON" >> $GITHUB_ENV | ||
| - name: Upload Coverage to Codecov | ||
| uses: codecov/codecov-action@v5 | ||
| with: | ||
| files: ${{ env.COVERAGE_JSON }} | ||
| flag: swift-${{ matrix.swift }} | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fails because the |
||
| name: macos-swift-${{ matrix.swift }} | ||
| fail_ci_if_error: false | ||
| env: | ||
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | ||
| build-ubuntu-spm: | ||
| name: Build JBird (Ubuntu) | ||
| strategy: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| # Code Coverage Documentation | ||
|
|
||
| This document describes the code coverage reporting setup for the JBird project. | ||
|
|
||
| ## Overview | ||
|
|
||
| Code coverage is automatically generated and reported for all commits and pull requests for macOS test configurations: | ||
| - macOS Swift 6.1 and 6.2 | ||
|
|
||
| The coverage data is collected using Swift's built-in code coverage support and is visualized in two ways: | ||
|
|
||
| 1. **GitHub Actions Summary**: A formatted table showing coverage metrics directly in the CI job output for each Swift version | ||
| 2. **Codecov.io**: Detailed coverage reports, PR comments, and trend tracking with consolidated data from all platforms | ||
|
|
||
| ## Coverage Metrics | ||
|
|
||
| The following metrics are tracked: | ||
|
|
||
| - **Lines Coverage**: Percentage of executable lines that were executed during tests | ||
| - **Functions Coverage**: Percentage of functions that were called during tests | ||
| - **Regions Coverage**: Percentage of code regions that were executed during tests | ||
|
|
||
| ## Viewing Coverage Reports | ||
|
|
||
| ### GitHub Actions Summary | ||
|
|
||
| After each test run, you can view the coverage summary by: | ||
|
|
||
| 1. Go to the "Actions" tab in the GitHub repository | ||
| 2. Select a workflow run | ||
| 3. Click on "Test JBird (macOS)" for a Swift version | ||
| 4. Scroll down to view the coverage table in the summary section | ||
|
|
||
| The summary shows: | ||
| ``` | ||
| ## π Code Coverage Report (macOS, Swift 6.2) | ||
|
|
||
| | Metric | Coverage | Covered | Total | | ||
| |--------|----------|---------|-------| | ||
| | **Lines** | **XX.XX%** | XXXX | XXXX | | ||
| | **Functions** | **XX.XX%** | XXX | XXX | | ||
| | **Regions** | **XX.XX%** | XXXX | XXXX | | ||
| ``` | ||
|
|
||
| Each Swift version produces its own coverage report. | ||
|
|
||
| ### Codecov Integration | ||
|
|
||
| Codecov provides additional features by consolidating coverage data from all Swift versions: | ||
|
|
||
| - **PR Comments**: Automatic comments on pull requests showing coverage changes | ||
| - **Coverage Trends**: Historical tracking of coverage over time | ||
| - **File-level Coverage**: Detailed line-by-line coverage for each file | ||
| - **Coverage Badge**: Optional badge for the README | ||
|
|
||
| Visit https://codecov.io/gh/vsanthanam/JBird to view detailed reports. | ||
|
|
||
| ## Running Coverage Locally | ||
|
|
||
| To generate coverage reports locally: | ||
|
|
||
| ```bash | ||
| # Run tests with coverage enabled | ||
| swift test --enable-code-coverage | ||
|
|
||
| # View the coverage JSON path | ||
| swift test --show-codecov-path | ||
|
|
||
| # The coverage data is stored at: | ||
| # .build/<platform>/debug/codecov/JBird.json | ||
| ``` | ||
|
|
||
| You can then examine the JSON file to see detailed coverage information. | ||
|
|
||
| ## Coverage Configuration | ||
|
|
||
| ### CI Configuration | ||
|
|
||
| Code coverage is enabled in `.github/workflows/ci.yml` for macOS test jobs: | ||
| - macOS Swift 6.1 and 6.2 | ||
|
|
||
| ```yaml | ||
| - name: Test JBird | ||
| run: swift test --enable-code-coverage | ||
| ``` | ||
|
|
||
| The coverage report filters results to only include project source files (those in `/Sources/` directory), excluding Swift package dependencies. This ensures accurate coverage metrics for the project's own code. The filtered JSON is then uploaded to Codecov to ensure consistency across all platforms. | ||
|
|
||
| ### Codecov Configuration | ||
|
|
||
| The Codecov token is stored as a repository secret (`CODECOV_TOKEN`). For public repositories, this token is optional but recommended for better reliability and rate limits. | ||
|
|
||
| Coverage data from all Swift versions is uploaded with a single flag per upload: | ||
| - `swift-6.1` - macOS with Swift 6.1 | ||
| - `swift-6.2` - macOS with Swift 6.2 | ||
|
|
||
| To configure the token: | ||
| 1. Sign up at https://codecov.io | ||
| 2. Add the repository | ||
| 3. Copy the upload token | ||
| 4. Add it as `CODECOV_TOKEN` in repository secrets | ||
|
|
||
| ## Future Enhancements | ||
|
|
||
| The coverage system supports several potential enhancements: | ||
|
|
||
| - **Coverage Thresholds**: Set minimum coverage percentages to fail CI | ||
| - **HTML Reports**: Generate browsable HTML coverage reports | ||
| - **Coverage Badges**: Add coverage badges to README | ||
| - **Differential Coverage**: Show coverage only for changed files | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Coverage data not generated | ||
|
|
||
| Ensure you're running tests with `--enable-code-coverage`: | ||
| ```bash | ||
| swift test --enable-code-coverage | ||
| ``` | ||
|
|
||
| ### Codecov upload fails | ||
|
|
||
| - Verify `CODECOV_TOKEN` secret is set (if using private repo) | ||
| - Check the codecov action logs for specific errors | ||
| - Note: `fail_ci_if_error: false` prevents CI failure on upload errors | ||
|
|
||
| ### Coverage appears low | ||
|
|
||
| - Coverage is only collected from executed test code | ||
| - Some generated code (like resource accessors) may not be covered | ||
| - Consider adding tests for uncovered code paths |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still gives me dramatically different results for Swift 6.1 vs Swift 6.2 Your filtering is clearly not working.