A utility to convert data from Xcode 11's code coverage facility into the lcov
file format, intended for upload to Coveralls.io.
Usage:
$ xccov2lcov <inputFilename>
Arguments:
inputFilename - Input filename (output of `xccov view --report --json file.xcresult`)
Options:
--trim-path [default: ] - Path to trim from start of paths in input file
--include-targets [default: []] - Targets to include in output (default: all targets)
--mode [default: simple] - Output mode: 'simple' includes only DA records, 'full' includes 'FN*' records
To track coverage changes over time, we want to upload our coverage data to coveralls.io. Here's the flow:
Code coverage is enabled in the standard way, by setting the value of "Code Coverage" to "on" in the test plan.
When the test run is complete, Xcode generates an xcresult
bundle which contains all of the coverage data. To more easily find the xcresult
file, I find it easier to tell xcodebuild
where to put it via the -resultBundlePath
argument:
xcodebuild clean test \
-project Project.xcodeproj \
-scheme Scheme \
-resultBundlePath coverage/result.xcresult
Before we can upload the data to Coveralls, we need to convert it to a format it understands. Coveralls has an API and a defined format for upload, but for expediency I found a Coveralls Github Action already created that can perform the upload. However, rather than expecting data in Coveralls' upload format, it expects to find a file in the LCOV format. So we first need to convert xcresult
data to LCOV format. We do this in a two-step process:
-
Convert
xcresult
to JSONXcode includes a tool (
xccov
) that helps us to export coverage data in a JSON format.xcrun xccov view --report --json coverage/result.xcresult > cov.json
-
Convert JSON to LCOV
This is where the
xccov2lcov
tool comes in:swift run xccov2lcov cov.json > lcov.info
Finally, uploading to Coveralls happens during the automated build via the already mentioned Coveralls Github Action by adding the following to .github/workflows/main.yml
:
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}