Skip to content

Fix cobertura coverage statistics when filtering packages or targets #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions Sources/Core/Filters/PackagesFilter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,31 @@ public extension Xccov.Filters.Packages {

let targetsToKeep = coverageReport.targets.map { target -> TargetCoverageReport in
let filesToKeep = target.files.filter { !$0.path.contains(elementsOf: packagesToExclude) }
return TargetCoverageReport(buildProductPath: target.buildProductPath,
coveredLines: target.coveredLines,
executableLines: target.executableLines,
files: filesToKeep,
lineCoverage: target.lineCoverage,
name: target.name)
let adjusted = filesToKeep.reduce(into: (coveredLines: 0, executableLines: 0)) {
$0.coveredLines += $1.coveredLines
$0.executableLines += $1.executableLines
}
return TargetCoverageReport(
buildProductPath: target.buildProductPath,
coveredLines: adjusted.coveredLines,
executableLines: adjusted.executableLines,
files: filesToKeep,
lineCoverage: Double(adjusted.coveredLines) / Double(adjusted.executableLines),
name: target.name
)
}

let filteredCoverageReport = CoverageReport(executableLines: coverageReport.executableLines,
targets: targetsToKeep,
lineCoverage: coverageReport.lineCoverage,
coveredLines: coverageReport.coveredLines)
let adjusted = targetsToKeep.reduce(into: (coveredLines: 0, executableLines: 0)) {
$0.coveredLines += $1.coveredLines
$0.executableLines += $1.executableLines
}
let filteredCoverageReport = CoverageReport(
executableLines: adjusted.executableLines,
targets: targetsToKeep,
lineCoverage: Double(adjusted.coveredLines) / Double(adjusted.executableLines),
coveredLines: adjusted.coveredLines
)

return filteredCoverageReport
}
}
15 changes: 11 additions & 4 deletions Sources/Core/Filters/TargetsFilter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ public extension Xccov.Filters.Targets {
guard !targetsToExclude.isEmpty else { return coverageReport }

let targetsToKeep = coverageReport.targets.filter { !$0.name.contains(elementsOf: targetsToExclude) }
let filteredCoverageReport = CoverageReport(executableLines: coverageReport.executableLines,
targets: targetsToKeep,
lineCoverage: coverageReport.lineCoverage,
coveredLines: coverageReport.coveredLines)
let adjusted = targetsToKeep.reduce(into: (coveredLines: 0, executableLines: 0)) {
$0.coveredLines += $1.coveredLines
$0.executableLines += $1.executableLines
}
let filteredCoverageReport = CoverageReport(
executableLines: adjusted.executableLines,
targets: targetsToKeep,
lineCoverage: Double(adjusted.coveredLines) / Double(adjusted.executableLines),
coveredLines: adjusted.coveredLines
)

return filteredCoverageReport
}
}
18 changes: 9 additions & 9 deletions Tests/CoreTests/Filters/PackagesFilterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ import XCTest
final class PackagesFilterTests: XCTestCase {
func testFilter_removes_packages_to_exclude() {
// Given: an input coverageReport with 4 different packages
let file1 = FileCoverageReport(coveredLines: 0, executableLines: 0, functions: [], lineCoverage: 0, name: "1", path: "/common/file1")
let file2 = FileCoverageReport(coveredLines: 0, executableLines: 0, functions: [], lineCoverage: 0, name: "2", path: "/client1/file2")
let file3 = FileCoverageReport(coveredLines: 0, executableLines: 0, functions: [], lineCoverage: 0, name: "3", path: "/client2/file3")
let file4 = FileCoverageReport(coveredLines: 0, executableLines: 0, functions: [], lineCoverage: 0, name: "4", path: "/common/file4")
let file5 = FileCoverageReport(coveredLines: 0, executableLines: 0, functions: [], lineCoverage: 0, name: "5", path: "/client3/file5")
let file6 = FileCoverageReport(coveredLines: 0, executableLines: 0, functions: [], lineCoverage: 0, name: "6", path: "/client1/file6")
let file1 = FileCoverageReport(coveredLines: 10, executableLines: 10, functions: [], lineCoverage: 1, name: "1", path: "/common/file1")
let file2 = FileCoverageReport(coveredLines: 0, executableLines: 20, functions: [], lineCoverage: 0, name: "2", path: "/client1/file2")
let file3 = FileCoverageReport(coveredLines: 0, executableLines: 30, functions: [], lineCoverage: 1, name: "3", path: "/client2/file3")
let file4 = FileCoverageReport(coveredLines: 40, executableLines: 40, functions: [], lineCoverage: 1, name: "4", path: "/common/file4")
let file5 = FileCoverageReport(coveredLines: 50, executableLines: 50, functions: [], lineCoverage: 1, name: "5", path: "/client3/file5")
let file6 = FileCoverageReport(coveredLines: 0, executableLines: 60, functions: [], lineCoverage: 0, name: "6", path: "/client1/file6")

let target1 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [file1, file2, file3], lineCoverage: 0, name: "1")
let target2 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [file4, file5, file6], lineCoverage: 0, name: "2")
let coverageReport = CoverageReport(executableLines: 0, targets: [target1, target2], lineCoverage: 0, coveredLines: 0)

let expectedTarget1 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [file1], lineCoverage: 0, name: "1")
let expectedTarget2 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [file4, file5], lineCoverage: 0, name: "2")
let expectedReport = CoverageReport(executableLines: 0, targets: [expectedTarget1, expectedTarget2], lineCoverage: 0, coveredLines: 0)
let expectedTarget1 = TargetCoverageReport(buildProductPath: "", coveredLines: 10, executableLines: 10, files: [file1], lineCoverage: 1, name: "1")
let expectedTarget2 = TargetCoverageReport(buildProductPath: "", coveredLines: 90, executableLines: 90, files: [file4, file5], lineCoverage: 1, name: "2")
let expectedReport = CoverageReport(executableLines: 100, targets: [expectedTarget1, expectedTarget2], lineCoverage: 1, coveredLines: 100)

// When: filtering the coverage report by excluding packages client1 and client2
let receivedReport = Xccov.Filters.Packages.filter(coverageReport: coverageReport, packagesToExclude: ["client1", "client2"])
Expand Down
10 changes: 5 additions & 5 deletions Tests/CoreTests/Filters/TargetsFilterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import XCTest
final class TargetsFilterTests: XCTestCase {
func testFilter_removes_targets_to_exclude() {
// Given: an input coverageReport with target 1, 2 and 3
let target1 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [], lineCoverage: 0, name: "1")
let target2 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [], lineCoverage: 0, name: "2")
let target3 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 0, files: [], lineCoverage: 0, name: "3")
let coverageReport = CoverageReport(executableLines: 0, targets: [target1, target2, target3], lineCoverage: 0, coveredLines: 0)
let expectedReport = CoverageReport(executableLines: 0, targets: [target1], lineCoverage: 0, coveredLines: 0)
let target1 = TargetCoverageReport(buildProductPath: "", coveredLines: 10, executableLines: 10, files: [], lineCoverage: 0, name: "1")
let target2 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 20, files: [], lineCoverage: 1, name: "2")
let target3 = TargetCoverageReport(buildProductPath: "", coveredLines: 0, executableLines: 30, files: [], lineCoverage: 1, name: "3")
let coverageReport = CoverageReport(executableLines: 40, targets: [target1, target2, target3], lineCoverage: 0.25, coveredLines: 10)
let expectedReport = CoverageReport(executableLines: 10, targets: [target1], lineCoverage: 1, coveredLines: 10)

// When: filtering the coverage report by excluding targets 2 and 3
let receivedReport = Xccov.Filters.Targets.filter(coverageReport: coverageReport, targetsToExclude: ["2", "3"])
Expand Down