[SOLVED] No code coverage in Swift 5.6 XCode 13 project

I am getting 0% code coverage in my Swift 5.6 which is using Xcode 13.4. I am uploading to SonarCloud so I am running with the latest version there and I am using the latest version of the scanner for macos. I have been searching this forum and looking over quite a few threads that seem to report problems with getting coverage data in Xcode 13 and swift. What is confusing is that there seems to be conflicting info on what options should be used to upload code coverage for swift depending which thread I read. Official documentation is currently not aligned to fairly recent threads here so it’s hard to tell how this is supposed to work. For starters, here is what I am doing.

I build the code and run tests with code coverage enabled. Note, I am using swift to build, not xcodebuild command:

swift test --enable-code-coverage

This produces a llvm-cov JSON file containing coverage data. From here on, things get confusing. First question, which option is the one to use for coverage info?

  • sonar.swift.coverage.reportPath?
  • sonar.swift.coverage.reportPaths?
  • sonar.coverageReportPaths?

I tried the first 2, they don’t work. They don’t seem to be in the documentation anymore so I am guessing these are old, or they worked for older Xcode versions? For the first one, I get a warning stating deprecation, the scanner seems to suggest it is parsing the file but I get no coverage data in the scan (I redacted sensitive info from the output):

WARN: Property 'sonar.swift.coverage.reportPath' is deprecated and will be soon ignored, use 'sonar.swift.coverage.reportPaths' instead.
INFO: Parse coverage report (***/x86_64-apple-macosx/debug/codecov/SonosClient.json)

Second option, no warning, same parsing message, no coverage data.

So, I am arriving at the last option which leaves me with a question on how to convert llvm-cov format produced by swift into the generic that Sonar can accept. I tried the advertised conversion script in this project: sonar-scanning-examples/swift-coverage at master · SonarSource/sonar-scanning-examples · GitHub as instructed by the documentation but this script seems to assume there is Info.plist file which is no longer produced in XCode13.

coverage version="1">
error: Info.plist at ***/coverage/Info.plist does not exist, the result bundle might be corrupted or the provided path is not a result bundle
Failed to execute xcrun xcresulttool get

I feel like I am entering unsupported territory. Note, based on what I have read, new Xcode 13 projects exhibit this behavior. I’d love to get feedback or help here to see if we can make this work. It seems like Sonar can do llvm-cov format which is what swift is putting out for coverage report but I suspect since my project is a swift library project, not a typical Xcode project, and we’re not producing xcresult archive, this doesn’t work. Any feedback here is welcome.

1 Like

I solved it. Here is what works in Xcode 13. Turns out that using llvm to generate the report is the way to go, which is the method that also works with Xcode 8 - 9.2, as documented here: sonar-scanning-examples/swift-coverage at master · SonarSource/sonar-scanning-examples · GitHub.

Build and run tests:

swift test --enable-code-coverage

Generate coverage report and save to a file:

xcrun llvm-cov show -instr-profile=.build/debug/codecov/default.profdata .build/debug/MyPackageTests.xctest/Contents/MacOS/MyPackageTests > coverage.report

Run the scan:

sonar-scanner -Dsonar.swift.coverage.reportPaths=coverage.report
2 Likes