xccov: Diff and Merge Swift(iOS) Code Coverage
Apple has released a new command line tool xccov last year for inspecting the contents of Xcode code coverage reports. With xccov , we can generate Xcode code coverage reports in the human-readable format as well as machine representable format like JSON without using third-party tools. In our previous post, we looked into how to generate code coverage report using xccov tool. In this post, we will explore the new features release with Xcode 10.2.
Code Coverage Path Changed (Xcode10)
We have created a demo repository on Github to explore xccov features. First, let’s build the app and generate the derived data in the Build directory inside the project.
1 2 3 |
$ xcodebuild -project XCCov-Demo.xcodeproj/ -scheme XCCov-Demo -derivedDataPath Build/ -destination 'platform=iOS Simulator,OS=12.2,name=iPhone Xʀ' -enableCodeCoverage YES clean build test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO |
After running above command, we will get the test report and code coverage reports. This used to generate the code coverage data at path Build/Logs/Test but now reports are generated with the timestamp. e.g
1 2 3 |
Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-33-02-+0100.xcresult/3_Test/*.xccovreport |
We will see code coverage with .xccovreport and .xccovarchive extension.
The real power of xccov comes when it can generate the code coverage reports in the JSON format. As per Apple’s documentation on the man page, its machine representable format. We can hook these JSON results anywhere we like or build another tool on top of this. We can generate JSON reports using the following command.
1 2 3 |
$ xcrun xccov view --json Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport |
We have just added the flag --json at the end of the command to get the JSON reports.
Diff Code Coverage
As we keep developing apps and adding more source code, Xcode now keeps all the code coverage reports in the different directory with timestamps. In our case, the code coverage reports are stored in the directory
Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-33-02-+0100.xcresult/3_Test
Now that, we got reports from the specific timestamp, we can diff the reports with a different timestamp to get an idea of what has been changed in terms of code coverage.
As per the documentation, followed the steps but couldn’t generate diff. Following commands tried:
Attempt One:
1 2 3 4 5 |
$ xcrun xccov diff --json Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport, Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-52-58-+0100.xcresult/3_Test/action.xccovreport Error: Error Domain=XCCovErrorDomain Code=0 "Failed to load coverage report at path Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport," UserInfo={NSLocalizedDescription=Failed to load coverage report at path Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport,, NSUnderlyingError=0x7f93dec23600 {Error Domain=NSCocoaErrorDomain Code=260 "The file “action.xccovreport,” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/shashi/workspace/XCCov-Demo/Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport,, NSUnderlyingError=0x7f93dec23110 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}}} |
Attempt Two:
1 2 3 4 5 |
$ xcrun xccov diff --json --path-equivalence Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport, Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-52-58-+0100.xcresult/3_Test/action.xccovreport Error: Must supply the path to two coverage reports to diff |
Attempt Three:
1 2 3 4 5 |
$xcrun xccov diff --json from --path-equivalence Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-33-02-+0100.xcresult/3_Test/action.xccovreport,to Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-52-58-+0100.xcresult/3_Test/action.xccovreport Error: Error Domain=XCCovErrorDomain Code=0 "Failed to load coverage report at path from" UserInfo={NSLocalizedDescription=Failed to load coverage report at path from, NSUnderlyingError=0x7fc2da631430 {Error Domain=NSCocoaErrorDomain Code=260 "The file “from” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Users/shashi/workspace/XCCov-Demo/from, NSUnderlyingError=0x7fc2da606680 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}}} |
Attempt Four:
1 2 3 4 5 |
xcrun xccov diff --json --path-equivalence from Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-33-02-+0100.xcresult/3_Test/action.xccovreport,to Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-52-58-+0100.xcresult/3_Test/action.xccovreport fish: 'xcrun xccov diff --json --path-…' terminated by signal SIGSEGV (Address boundary error) |
As of now, I couldn’t generate the diff from the two code coverage reports. However, I can view both reports when running following command
1 2 3 |
$ xcrun xccov view --json Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport |
It would be great if there would be an example of how to generate the diff of the source code.
Merge Code Coverage Report
With Xcode 10.2, we can even merge two code coverage reports. We have to provide the path of both code coverage reports and code coverage archive. We also need to specify the path of output. in our case, we ran following command
1 2 3 |
$ xcrun xccov merge --outReport ~/Desktop/out.xccovreport --outArchive ~/Desktop/out.acarchive Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovreport Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-40-58-+0100.xcresult/3_Test/action.xccovarchive/ Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-52-58-+0100.xcresult/3_Test/action.xccovreport Build/Logs/Test/Run-XCCov-Demo-2019.04.03_07-52-58-+0100.xcresult/3_Test/action.xccovarchive/ |
This command successfully generated out.acarchive and out.xccovreport file on the desktop.
Source Code
The sample code for this post is available on Github XCCov-Demo. You can also see the build data and derived data in the Build directory.
Conclusion
With Xcode.102, you can now create diff files or merge the code coverage from different targets. This would be useful for displaying the code coverage changes on Continuous Integration servers.