Skip to content

Commit

Permalink
Merge pull request #3 from weibel/main
Browse files Browse the repository at this point in the history
Added target filters and total breakdown for coverage report
  • Loading branch information
a7ex authored Dec 24, 2021
2 parents 9977b9f + 2e29a68 commit 6f282a7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
32 changes: 31 additions & 1 deletion xcresultparser/XCResultFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct XCResultFormatter {
private let invocationRecord: ActionsInvocationRecord
private let codeCoverage: CodeCoverage?
private let outputFormatter: XCResultFormatting
private let coverageTargets: Set<String>

private var numFormatter: NumberFormatter = {
let numFormatter = NumberFormatter()
Expand All @@ -32,7 +33,8 @@ struct XCResultFormatter {
// MARK: - Initializer

init?(with url: URL,
formatter: XCResultFormatting
formatter: XCResultFormatting,
coverageTargets: [String] = []
) {
resultFile = XCResultFile(url: url)
guard let record = resultFile.getInvocationRecord() else {
Expand All @@ -41,6 +43,7 @@ struct XCResultFormatter {
invocationRecord = record
outputFormatter = formatter
codeCoverage = resultFile.getCodeCoverage()
self.coverageTargets = codeCoverage?.targets(filteredBy: coverageTargets) ?? []

//if let logsId = invocationRecord?.actions.last?.actionResult.logRef?.id {
// let testLogs = resultFile.getLogs(id: logsId)
Expand Down Expand Up @@ -202,8 +205,13 @@ struct XCResultFormatter {
guard let codeCoverage = codeCoverage else {
return lines
}
var executableLines: Int = 0
var coveredLines: Int = 0
for target in codeCoverage.targets {
guard coverageTargets.contains(target.name) else { continue }
let covPercent = percentFormatter.unwrappedString(for: (target.lineCoverage * 100))
executableLines += target.executableLines
coveredLines += target.coveredLines
lines.append(
outputFormatter.codeCoverageTargetSummary(
"\(target.name): \(covPercent)% (\(target.coveredLines)/\(target.executableLines))"
Expand Down Expand Up @@ -257,10 +265,32 @@ struct XCResultFormatter {
)
}
}
// Append the total coverage below the header
guard executableLines > 0 else { return lines }
let fraction = Double(coveredLines) / Double(executableLines)
let covPercent: String = percentFormatter.unwrappedString(for: fraction * 100)
let line = outputFormatter.codeCoverageTargetSummary("Total coverage: \(covPercent)% (\(coveredLines)/\(executableLines))")
lines.insert(line, at: 1)
return lines
}
}

private extension CodeCoverage {
func targets(filteredBy filter: [String]) -> Set<String> {
let targetNames = targets.map { $0.name }
guard !filter.isEmpty else {
return Set(targetNames)
}
let filterSet = Set(filter)
let filtered = targetNames.filter { thisTarget in
// Clean up target.name. Split on '.' because the target.name is appended with .framework or .app
guard let stripped = thisTarget.split(separator: ".").first else { return true }
return filterSet.contains(String(stripped))
}
return Set(filtered)
}
}

private extension NumberFormatter {
func unwrappedString(for input: Double?) -> String {
return string(for: input) ?? ""
Expand Down
20 changes: 15 additions & 5 deletions xcresultparser/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ struct xcresultparser: ParsableCommand {
@Option(name: .shortAndLong, help: "The name of the project root. If present paths and urls are relative to the specified directory.")
var projectRoot: String?

@Option(name: [.customShort("t"), .customLong("coverage-targets")], help: "Specify which targets to calculate coverage from")
var coverageTargets: [String] = []

@Flag(name: .shortAndLong, help: "Whether to print coverage data.")
var coverage: Int

@Flag(name: .shortAndLong, help: "Whether to print test results.")
var noTestResult: Int

@Flag(name: .shortAndLong, help: "Quiet. Don't print status output.")
var quiet: Int

Expand Down Expand Up @@ -63,14 +69,18 @@ struct xcresultparser: ParsableCommand {

private func outputDescription() throws {
guard let resultParser = XCResultFormatter(
with: URL(fileURLWithPath: xcresultFile),
formatter: outputFormatter) else {
with: URL(fileURLWithPath: xcresultFile),
formatter: outputFormatter,
coverageTargets: coverageTargets
) else {
throw ParseError.argumentError
}
writeToStdOutLn(resultParser.documentPrefix(title: "XCResults"))
writeToStdOutLn(resultParser.summary)
writeToStdOutLn(resultParser.divider)
writeToStdOutLn(resultParser.testDetails)
if noTestResult == 0 {
writeToStdOutLn(resultParser.summary)
writeToStdOutLn(resultParser.divider)
writeToStdOutLn(resultParser.testDetails)
}
if coverage == 1 {
writeToStdOutLn(resultParser.coverageDetails)
}
Expand Down

0 comments on commit 6f282a7

Please sign in to comment.