Generating coverage reports & badges for SwiftPM apps
The age plugin for Apple’s Secure Enclave is a small, platform-independent Swift CLI app, built using the Swift Package Manager. Because it does not use Xcode for building, you can’t use the Xcode IDE for collecting and browsing test coverage of your source files. I therefore wrote a small (self-contained, dependencyless, cross-platform) Swift script to transform SwiftPM’s raw coverage data into annotated source code, together with an SVG badge to put on your project page.
Running the script
To create a coverage report, first run the unit tests with coverage tracking enabled:
$ swift test --enable-code-coverage
Building for debugging...
[25/25] Linking AgeSecureEnclavePluginPackageTests
Build complete! (23.38s)
Test Suite 'All tests' started at 2024-04-20 21:51:18.947.
...
Test Suite 'All tests' passed at 2024-04-20 21:51:19.017.
Executed 79 tests, with 0 failures (0 unexpected) in 0.064 (0.069) seconds
Then, you can run the script on the coverage data, and output the HTML and SVG:
$ ./Scripts/ProcessCoverage.swift \
`swift test --show-codecov-path` .build/coverage.json \
.build/coverage.html .build/coverage.svg
Code coverage (lines):
Sources/Base64.swift 30/30 (100.0%)
Sources/Bech32.swift 160/175 (91.4%)
Sources/CLI.swift 59/133 (44.4%)
Sources/Crypto.swift 4/15 (26.7%)
Sources/Plugin.swift 378/381 (99.2%)
Sources/Stream.swift 0/8 (0.0%)
---
TOTAL 631/742 (85.0%)
A summary is printed as well, which is useful for quick testing or for logging in CI.
The layout of the generated HTML is heavily inspired by Go’s go tool cover -html
output.
Publishing the coverage report on GitHub
When you use GitHub, you can use a GitHub action to publish the resulting HTML (and badge) to GitHub Pages.
For example, the following workflow steps publish the HTML to https://<username>.github.io/<project>/ci/coverage.html
, and the SVG badge to https://<username>.github.io/<project>/ci/coverage.svg
:
steps:
...
- name: Copy coverage report & badge
run: |
mkdir -p .build/site/ci
cp .build/coverage.svg .build/coverage.html .build/site/ci
shell: bash
- name: Upload pages
uses: actions/upload-pages-artifact@v1
with:
path: .build/site
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
You can then include an inline badge image with a link to the coverage report in your README.md
for your project page (as seen here):
[![Coverage](https://<username>.github.io/<project>/ci/coverage.svg)](https://<username>.github.io/<project>/ci/coverage.html)
Alternatives
Besides adding an Xcode project, you can also use a combination of llvm-cov export
and LCOV on the coverage
data to get source code reports. However, I had problems getting llvm-cov
and LCOV installed and working on my machine (I didn’t even try on GitHub), and I also prefer to avoid unnecessary dependencies when I can.