-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Separated text formatter * Formatter → TextFormatter * Removed duplicated tests * Removed Parser * Introduced FormatterProtocol * Renamed Filters to TestResults * Replaced TestResult with ReportModel.Module.File.RepeatableTest.Test.Status * Moved common code out of formatter * Removed unused code * Minr change
- Loading branch information
Showing
10 changed files
with
251 additions
and
471 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
15 changes: 15 additions & 0 deletions
15
Sources/DBXCResultParser/Formatters/FormatterProtocol.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// FormatterProtocol.swift | ||
// | ||
// | ||
// Created by Aleksey Berezka on 15.12.2023. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol FormatterProtocol { | ||
func format( | ||
_ report: ReportModel, | ||
testResults: [ReportModel.Module.File.RepeatableTest.Test.Status] | ||
) -> String | ||
} |
125 changes: 125 additions & 0 deletions
125
Sources/DBXCResultParser/Formatters/TextFormatter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// | ||
// TextFormatter.swift | ||
// | ||
// | ||
// Created by Алексей Берёзка on 31.12.2021. | ||
// | ||
|
||
import Foundation | ||
|
||
extension TextFormatter { | ||
public enum Format { | ||
case list | ||
case count | ||
} | ||
} | ||
|
||
class TextFormatter: FormatterProtocol { | ||
public let format: Format | ||
public let locale: Locale? | ||
|
||
public init( | ||
format: Format, | ||
locale: Locale? = nil | ||
) { | ||
self.format = format | ||
self.locale = locale | ||
} | ||
|
||
public func format( | ||
_ report: ReportModel, | ||
testResults: [ReportModel.Module.File.RepeatableTest.Test.Status] = .allCases | ||
) -> String { | ||
let files = report.modules | ||
.flatMap { Array($0.files) } | ||
.sorted { $0.name < $1.name } | ||
|
||
switch format { | ||
case .list: | ||
let singleTestsMeasurementFormatter = MeasurementFormatter.singleTestDurationFormatter | ||
singleTestsMeasurementFormatter.locale = locale | ||
let filesReports = files.compactMap { file in | ||
file.report(testResults: testResults, | ||
formatter: singleTestsMeasurementFormatter) | ||
} | ||
return filesReports.joined(separator: "\n\n") | ||
case .count: | ||
let numberFormatter = NumberFormatter.testsCountFormatter | ||
numberFormatter.locale = locale | ||
let totalTestsMeasurementFormatter = MeasurementFormatter.totalTestsDurationFormatter | ||
totalTestsMeasurementFormatter.locale = locale | ||
let tests = files.flatMap { $0.repeatableTests.filtered(testResults: testResults) } | ||
let count = tests.count | ||
let duration = tests.totalDuration | ||
let addDuration = testResults != [.skipped] // don't add 0ms duration if requested only skipped tests | ||
return [ | ||
numberFormatter.string(from: NSNumber(value: count)) ?? String(count), | ||
addDuration ? totalTestsMeasurementFormatter.string(from: duration).wrappedInBrackets : nil | ||
] | ||
.compactMap{ $0 } | ||
.joined(separator: " ") | ||
} | ||
} | ||
} | ||
|
||
extension ReportModel.Module.File { | ||
func report(testResults: [ReportModel.Module.File.RepeatableTest.Test.Status], | ||
formatter: MeasurementFormatter) -> String? { | ||
let tests = repeatableTests.filtered(testResults: testResults).sorted { $0.name < $1.name } | ||
|
||
guard !tests.isEmpty else { | ||
return nil | ||
} | ||
|
||
var rows = tests | ||
.sorted { $0.name < $1.name } | ||
.map { test in | ||
test.report(formatter: formatter) | ||
} | ||
|
||
rows.insert(name, at: 0) | ||
|
||
return rows.joined(separator: "\n") | ||
} | ||
} | ||
|
||
fileprivate extension ReportModel.Module.File.RepeatableTest { | ||
func report(formatter: MeasurementFormatter) -> String { | ||
[ | ||
combinedStatus.icon, | ||
name | ||
] | ||
.compactMap { $0 } | ||
.joined(separator: " ") | ||
} | ||
} | ||
|
||
extension String { | ||
var wrappedInBrackets: Self { | ||
"(" + self + ")" | ||
} | ||
} | ||
|
||
extension MeasurementFormatter { | ||
static var singleTestDurationFormatter: MeasurementFormatter { | ||
let formatter = MeasurementFormatter() | ||
formatter.unitOptions = [.providedUnit] | ||
formatter.numberFormatter.maximumFractionDigits = 0 | ||
return formatter | ||
} | ||
|
||
static var totalTestsDurationFormatter: MeasurementFormatter { | ||
let formatter = MeasurementFormatter() | ||
formatter.unitOptions = [.naturalScale] | ||
formatter.numberFormatter.maximumFractionDigits = 0 | ||
return formatter | ||
} | ||
} | ||
|
||
extension NumberFormatter { | ||
static var testsCountFormatter: NumberFormatter { | ||
let formatter = NumberFormatter() | ||
formatter.maximumFractionDigits = 0 | ||
return formatter | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
Sources/DBXCResultParser/Models/ReportModel+Convenience.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// ReportModel+Convenience.swift | ||
// | ||
// | ||
// Created by Aleksey Berezka on 15.12.2023. | ||
// | ||
|
||
import Foundation | ||
|
||
extension ReportModel { | ||
public init(xcresultPath: URL) throws { | ||
let overviewReport = try OverviewReportDTO(from: xcresultPath) | ||
let detailedReport = try DetailedReportDTO(from: xcresultPath, | ||
refId: overviewReport.testsRefId) | ||
|
||
let coverageDTOs = try? Array<CoverageDTO>(from: xcresultPath) | ||
.filter { !$0.name.contains("TestHelpers") && !$0.name.contains("Tests") } | ||
|
||
self = try ReportModel( | ||
overviewReportDTO: overviewReport, | ||
detailedReportDTO: detailedReport, | ||
coverageDTOs: coverageDTOs ?? [] | ||
) | ||
} | ||
} |
Oops, something went wrong.