diff --git a/Sources/DBXCResultParser/Formatter.swift b/Sources/DBXCResultParser/Formatter.swift deleted file mode 100644 index 705e209..0000000 --- a/Sources/DBXCResultParser/Formatter.swift +++ /dev/null @@ -1,215 +0,0 @@ -// -// Formatter.swift -// -// -// Created by Алексей Берёзка on 31.12.2021. -// - -import Foundation - -class Formatter { - static var locale: Locale? - - static func format(_ report: ReportModel, - filters: [Parser.Filter] = [], - format: Parser.Format) -> String { - let files = report.modules - .flatMap { Array($0.files) } - .sorted { $0.name < $1.name } - - switch format { - case .list: - let slowTestsDuration = filters.slowTestsDuration - let singleTestsMeasurementFormatter = MeasurementFormatter.singleTestDurationFormatter - let filesReports = files.compactMap { file in - file.report(filters: filters, - formatter: singleTestsMeasurementFormatter, - slowTestsDuration: slowTestsDuration) - } - return filesReports.joined(separator: "\n\n") - case .count: - let numberFormatter = NumberFormatter.testsCountFormatter - let totalTestsMeasurementFormatter = MeasurementFormatter.totalTestsDurationFormatter - let tests = files.flatMap { $0.repeatableTests.filtered(filters: filters) } - let count = tests.count - let duration = tests.totalDuration - let addDuration = filters != [.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 Array where Element == ReportModel.Module.File.RepeatableTest { - var totalDuration: Duration { - assert(map { $0.totalDuration.unit }.elementsAreEqual) - let value = map { $0.totalDuration.value }.sum() - let unit = first?.totalDuration.unit ?? ReportModel.Module.File.RepeatableTest.Test.defaultDurationUnit - return .init(value: value, unit: unit) - } -} - -extension ReportModel.Module.File { - func report(filters: [Parser.Filter], - formatter: MeasurementFormatter, - slowTestsDuration: Duration?) -> String? { - let tests = repeatableTests.filtered(filters: filters).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, - slowThresholdDuration: slowTestsDuration - ) - } - - rows.insert(name, at: 0) - - return rows.joined(separator: "\n") - } -} - -fileprivate extension ReportModel.Module.File.RepeatableTest { - private func reportIcons(_ slowThresholdDuration: Duration?) -> String { - [ - combinedStatus.icon, - slowThresholdDuration.flatMap { slowIcon($0) } - ] - .compactMap { $0 } - .joined(separator: "") - } - - private func slowIcon(_ slowThresholdDuration: Duration) -> String? { - isSlow(slowThresholdDuration) ? "🕢" : nil - } - - private func reportDuration(formatter: MeasurementFormatter, slowThresholdDuration: Duration) -> String { - formatter.string( - from: averageDuration.converted(to: slowThresholdDuration.unit) - ).wrappedInBrackets - } - - private func slowReportDuration( - formatter: MeasurementFormatter, - slowThresholdDuration: Duration - ) -> String? { - guard isSlow(slowThresholdDuration) else { - return nil - } - return reportDuration(formatter: formatter, slowThresholdDuration: slowThresholdDuration) - } - - func report(formatter: MeasurementFormatter, slowThresholdDuration: Duration?) -> String { - [ - reportIcons(slowThresholdDuration), - slowThresholdDuration.flatMap { slowReportDuration(formatter:formatter, slowThresholdDuration: $0) }, - name - ] - .compactMap { $0 } - .joined(separator: " ") - } -} - -fileprivate extension ReportModel.Module.File.RepeatableTest.Test.Status { - var icon: String { - switch self { - case .success: - return "✅" - case .failure: - return "❌" - case .skipped: - return "⏭" - case .mixed: - return "⚠️" - case .expectedFailure: - return "🤡" - case .unknown: - return "🤷" - } - } -} - -extension Set where Element == ReportModel.Module.File.RepeatableTest { - func filtered(filters: [Parser.Filter]) -> Set { - guard !filters.isEmpty else { - return self - } - - let results = filters - .flatMap { filter -> Set in - switch filter { - case .succeeded: - return self.succeeded - case .failed: - return self.failed - case .mixed: - return self.mixed - case .skipped: - return self.skipped - case .slow(let duration): - return self.slow(duration) - } - } - - return Set(results) - } -} - -extension String { - var wrappedInBrackets: Self { - "(" + self + ")" - } -} - -extension MeasurementFormatter { - static var singleTestDurationFormatter: MeasurementFormatter { - let formatter = MeasurementFormatter() - formatter.locale = Formatter.locale - formatter.unitOptions = [.providedUnit] - formatter.numberFormatter.maximumFractionDigits = 0 - return formatter - } - - static var totalTestsDurationFormatter: MeasurementFormatter { - let formatter = MeasurementFormatter() - formatter.locale = Formatter.locale - formatter.unitOptions = [.naturalScale] - formatter.numberFormatter.maximumFractionDigits = 0 - return formatter - } -} - -extension NumberFormatter { - static var testsCountFormatter: NumberFormatter { - let formatter = NumberFormatter() - formatter.locale = Formatter.locale - formatter.maximumFractionDigits = 0 - return formatter - } -} - -extension Array where Element == Parser.Filter { - var slowTestsDuration: Duration? { - var duration: Duration? - - forEach { filter in - switch filter { - case .slow(let value): - duration = value - default: - return - } - } - - return duration - } -} diff --git a/Sources/DBXCResultParser/Formatters/FormatterProtocol.swift b/Sources/DBXCResultParser/Formatters/FormatterProtocol.swift new file mode 100644 index 0000000..7f1d643 --- /dev/null +++ b/Sources/DBXCResultParser/Formatters/FormatterProtocol.swift @@ -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 +} diff --git a/Sources/DBXCResultParser/Formatters/TextFormatter.swift b/Sources/DBXCResultParser/Formatters/TextFormatter.swift new file mode 100644 index 0000000..4ce5666 --- /dev/null +++ b/Sources/DBXCResultParser/Formatters/TextFormatter.swift @@ -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 + } +} diff --git a/Sources/DBXCResultParser/Models/ReportModel+Convenience.swift b/Sources/DBXCResultParser/Models/ReportModel+Convenience.swift new file mode 100644 index 0000000..ec59b32 --- /dev/null +++ b/Sources/DBXCResultParser/Models/ReportModel+Convenience.swift @@ -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(from: xcresultPath) + .filter { !$0.name.contains("TestHelpers") && !$0.name.contains("Tests") } + + self = try ReportModel( + overviewReportDTO: overviewReport, + detailedReportDTO: detailedReport, + coverageDTOs: coverageDTOs ?? [] + ) + } +} diff --git a/Sources/DBXCResultParser/Models/ReportModel.swift b/Sources/DBXCResultParser/Models/ReportModel.swift index 722c8fe..45206c8 100644 --- a/Sources/DBXCResultParser/Models/ReportModel.swift +++ b/Sources/DBXCResultParser/Models/ReportModel.swift @@ -126,16 +126,20 @@ extension ReportModel.Module.File.RepeatableTest { } extension ReportModel.Module.File.RepeatableTest.Test { - public enum Status: Equatable { + public enum Status: Equatable, CaseIterable { case success case failure case expectedFailure case skipped case mixed - case unknown(rawValue: String) + case unknown } } +extension Array where Element == ReportModel.Module.File.RepeatableTest.Test.Status { + static let allCases = ReportModel.Module.File.RepeatableTest.Test.Status.allCases +} + extension ReportModel { init(overviewReportDTO: OverviewReportDTO, detailedReportDTO: DetailedReportDTO, @@ -212,6 +216,32 @@ fileprivate extension String { } extension Set where Element == ReportModel.Module.File.RepeatableTest { + public func filtered(testResults: [ReportModel.Module.File.RepeatableTest.Test.Status]) -> Set { + guard !testResults.isEmpty else { + return self + } + + let results = testResults + .flatMap { testResult -> Set in + switch testResult { + case .success: + return self.succeeded + case .failure: + return self.failed + case .mixed: + return self.mixed + case .skipped: + return self.skipped + case .expectedFailure: + return self.expectedFailed + case .unknown: + return self.unknown + } + } + + return Set(results) + } + var succeeded: Self { filter { $0.combinedStatus == .success } } @@ -220,6 +250,10 @@ extension Set where Element == ReportModel.Module.File.RepeatableTest { filter { $0.combinedStatus == .failure } } + var expectedFailed: Self { + filter { $0.combinedStatus == .expectedFailure } + } + var skipped: Self { filter { $0.combinedStatus == .skipped } } @@ -228,8 +262,8 @@ extension Set where Element == ReportModel.Module.File.RepeatableTest { filter { $0.combinedStatus == .mixed } } - func slow(_ duration: Duration) -> Self { - filter { $0.isSlow(duration) } + var unknown: Self { + filter { $0.combinedStatus == .unknown } } } @@ -245,7 +279,7 @@ extension ReportModel.Module.File.RepeatableTest.Test { case "Expected Failure": status = .expectedFailure default: - status = .unknown(rawValue: test.testStatus._value) + status = .unknown } guard let duration = Double(test.duration._value) else { @@ -285,3 +319,31 @@ extension Set where Element == ReportModel.Module { first { $0.name == name } } } + +extension Array where Element == ReportModel.Module.File.RepeatableTest { + var totalDuration: Duration { + assert(map { $0.totalDuration.unit }.elementsAreEqual) + let value = map { $0.totalDuration.value }.sum() + let unit = first?.totalDuration.unit ?? ReportModel.Module.File.RepeatableTest.Test.defaultDurationUnit + return .init(value: value, unit: unit) + } +} + +extension ReportModel.Module.File.RepeatableTest.Test.Status { + var icon: String { + switch self { + case .success: + return "✅" + case .failure: + return "❌" + case .skipped: + return "⏭" + case .mixed: + return "⚠️" + case .expectedFailure: + return "🤡" + case .unknown: + return "🤷" + } + } +} diff --git a/Sources/DBXCResultParser/Parser.swift b/Sources/DBXCResultParser/Parser.swift deleted file mode 100644 index ff96765..0000000 --- a/Sources/DBXCResultParser/Parser.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Foundation - -public class Parser { - public private(set) var report: 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(from: xcresultPath) - .filter { !$0.name.contains("TestHelpers") && !$0.name.contains("Tests") } - - report = try ReportModel(overviewReportDTO: overviewReport, - detailedReportDTO: detailedReport, - coverageDTOs: coverageDTOs ?? []) - } - - public func parse(filters: [Filter] = [], format: Format) throws -> String { - Formatter.format(report, filters: filters, format: format) - } -} - -extension Parser { - public enum Filter: Equatable { - case skipped - case failed - case mixed - case succeeded - case slow(duration: Duration) - } - - public enum Format { - case list - case count - } -} diff --git a/Sources/DBXCResultParser/XCResultSeeker.swift b/Sources/DBXCResultParser/XCResultSeeker.swift index 34ddac2..55f11ba 100644 --- a/Sources/DBXCResultParser/XCResultSeeker.swift +++ b/Sources/DBXCResultParser/XCResultSeeker.swift @@ -18,6 +18,6 @@ public class XCResultSeeker { return try FileManager .default .contentsOfDirectory(at: path, includingPropertiesForKeys: nil) - .filter{ $0.pathExtension == "xcresult" } + .filter { $0.pathExtension == "xcresult" } } } diff --git a/Tests/DBXCResultParserTests/IntegrationTests.swift b/Tests/DBXCResultParserTests/IntegrationTests.swift deleted file mode 100644 index 85272e6..0000000 --- a/Tests/DBXCResultParserTests/IntegrationTests.swift +++ /dev/null @@ -1,157 +0,0 @@ -import XCTest -@testable import DBXCResultParser - -final class IntegrationTests: XCTestCase { - override func setUpWithError() throws { - try super.setUpWithError() - Formatter.locale = Locale(identifier: "en-US") - } - - override func tearDownWithError() throws { - Formatter.locale = nil - try super.tearDownWithError() - } - - func test_parse_failed_list () throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.failed], format: .list) - let expectedResult = """ - CartHeaderCellSpec - ❌ CartHeaderCell__regular_state_with_delivery_amount__should_snapshot() - ❌ CartHeaderCell__regular_state_with_delivery_amount__when_translation_is_very_long__should_fit() - ❌ CartHeaderCell__simple_state__should_snapshot() - """ - XCTAssertEqual(String(result.prefix(expectedResult.count)), expectedResult) - } - - func test_parse_slow_3s_list () throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.slow(duration: .init(value: 3, unit: .seconds))], format: .list) - let expectedResult = """ - ContactsViewControllerSpec - ✅🕢 (3 sec) ContactsViewController__load_view__when_feedback_block_are_visible__when_chat_enabled__should_snapshot() - ✅🕢 (3 sec) ContactsViewController__load_view__when_location_button_is_visible__should_snapshot() - """ - XCTAssertEqual(String(result.prefix(expectedResult.count)), expectedResult) - } - - func test_parse_slow_3s_count() throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.slow(duration: .init(value: 3, unit: .seconds))], format: .count) - XCTAssertEqual(result, "2 (7 sec)") - } - - func test_parse_failed_count() throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.failed], format: .count) - XCTAssertEqual(result, "77 (9 sec)") - } - - func test_parse_failed_slow_3s_count() throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.failed, .slow(duration: .init(value: 3, unit: .seconds))], format: .count) - XCTAssertEqual(result, "79 (16 sec)") - } - - func test_parse_any_count() throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(format: .count) - XCTAssertEqual(result, "3708 (2 min)") - } - - func test_parse_skipped_count() throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.skipped], format: .count) - XCTAssertEqual(result, "3") - } - - func test_parse_skipped_list() throws { - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.skipped], format: .list) - XCTAssertEqual(result, """ - StateSaveServiceTests - ⏭ test_whenAutoPromocodeIsAppliedForRestaurant_thenShouldShowNotification() - ⏭ test_when_actualize_realRestApp_isON_and_receivedOrderType_carryout_should_resetState() - ⏭ test_when_save_realRestApp_isON_and_receivedOrderType_carryout_should_resetState() - """) - } - - func test_parse_mixed_list() throws { - let result = try Parser(xcresultPath: Constants.e2eTestsReportPath).parse(filters: [.mixed], format: .list) - XCTAssertEqual(result, """ - DeepLinksTests - ⚠️ test_promocode_is_invalid_deeplink() - """) - } - - func test_parse_slow_list() throws { - let slowThreshold = Duration(value: 100, unit: .milliseconds) - let result = try Parser(xcresultPath: Constants.unitTestsReportPath).parse(filters: [.slow(duration: slowThreshold)], format: .list) - let expectedResult = """ - AlertViewSpec - ✅🕢 (449 ms) EmailSubscriptionCell__snapshot() - - AnalyticsAuthorizationServiceSpec - ✅🕢 (313 ms) AnalyticsAuthorizationServiceSpec__when_logged__should_send_event_to_mindbox() - """ - - XCTAssertEqual( - String(result.prefix(expectedResult.count)), - expectedResult - ) - } - - func test_parse_failedMixed_list() throws { - let result = try Parser(xcresultPath: Constants.e2eTestsReportPath).parse(filters: [.failed, .mixed], format: .list) - XCTAssertEqual(result, """ - DeepLinksTests - ❌ test_open_order_by_deeplink() - ❌ test_pizza_halves_screen_deeplink() - ⚠️ test_promocode_is_invalid_deeplink() - """) - } - - func test_parse_warning_count() throws { - let parser = try Parser(xcresultPath: Constants.unitTestsWithCoverageReportPath) - XCTAssertEqual(parser.report.warningCount, 325) - } - - func test_parse_coverage() throws { - let parser = try Parser(xcresultPath: Constants.unitTestsWithCoverageReportPath) - for module in parser.report.modules { - XCTAssertNotNil(module.coverage) - } - } - - func test_parse_coverage_model() throws { - let parser = try Parser(xcresultPath: Constants.unitTestsWithCoverageReportPath) - let missionsModuleCoverage = parser.report.modules.first { $0.name == "MissionsTests" }?.coverage - XCTAssertNotNil(missionsModuleCoverage) - XCTAssertEqual(missionsModuleCoverage, .testMake(name: "Missions.framework", - coveredLines: 843, - totalLines: 1964, - coverage: 0.42922606924643586)) - } - - func test_total_coverage() throws { - let parser = try Parser(xcresultPath: Constants.unitTestsWithCoverageReportPath) - XCTAssertEqual(parser.report.totalCoverage!, 0.4164, accuracy: 0.0001) - } - - func test_totalCoverage_whenZeroModules_shouldReturnNil() { - let report = ReportModel(modules: []) - XCTAssertNil(report.totalCoverage) - } - - func test_totalCoverage_whenOneModule_shouldReturnTheModulesCoverage() { - let moduleWithCoverage: ReportModel.Module = .testMake(coverage: .testMake(coveredLines: 456, - totalLines: 789, - coverage: 0.234)) - let report = ReportModel(modules: [moduleWithCoverage]) - XCTAssertEqual(report.totalCoverage!, 0.5779, accuracy: 0.0001) - } - - func test_totalCoverage_shouldReturnModulesAvgCoverage() { - let moduleWithCoverage1: ReportModel.Module = .testMake(name: "1", - coverage: .testMake(coveredLines: 1, - totalLines: 2)) - let moduleWithCoverage2: ReportModel.Module = .testMake(name: "2", - coverage: .testMake(coveredLines: 19, - totalLines: 20)) - let report = ReportModel(modules: [moduleWithCoverage1, moduleWithCoverage2]) - XCTAssertEqual(report.totalCoverage!, 0.9, accuracy: 0.01) - } -} - diff --git a/Tests/DBXCResultParserTests/ParserTests.swift b/Tests/DBXCResultParserTests/ParserTests.swift deleted file mode 100644 index 8dbbd36..0000000 --- a/Tests/DBXCResultParserTests/ParserTests.swift +++ /dev/null @@ -1,10 +0,0 @@ -import XCTest -@testable import DBXCResultParser - -final class ParserTests: XCTestCase { - - func test() throws { - XCTAssertNoThrow(try Parser(xcresultPath: Constants.unitTestsReportPath)) - } -} - diff --git a/Tests/DBXCResultParserTests/FormatterTests.swift b/Tests/DBXCResultParserTests/TextFormatterTests.swift similarity index 79% rename from Tests/DBXCResultParserTests/FormatterTests.swift rename to Tests/DBXCResultParserTests/TextFormatterTests.swift index 79a5993..ad54761 100644 --- a/Tests/DBXCResultParserTests/FormatterTests.swift +++ b/Tests/DBXCResultParserTests/TextFormatterTests.swift @@ -2,18 +2,20 @@ import XCTest @testable import DBXCResultParser final class FormatterTests: XCTestCase { + var locale: Locale! override func setUpWithError() throws { try super.setUpWithError() - Formatter.locale = Locale(identifier: "en-US") + locale = Locale(identifier: "en-US") } override func tearDownWithError() throws { - Formatter.locale = nil + locale = nil try super.tearDownWithError() } - func test_filter_any_list() { - let result = Formatter.format(generalReport, format: .list) + func test_testResult_any_list() { + let formatter = TextFormatter(format: .list, locale: locale) + let result = formatter.format(generalReport) XCTAssertEqual(result, """ @@ -34,8 +36,10 @@ NotificationsSetupServiceTests """) } - func test_filter_success_list() { - let result = Formatter.format(generalReport, filters: [.succeeded], format: .list) + func test_testResult_success_list() { + let formatter = TextFormatter(format: .list, locale: locale) + let result = formatter.format(generalReport, testResults: [.success]) + XCTAssertEqual(result, """ AuthSpec @@ -46,52 +50,19 @@ NetworkSpec """) } - func test_filter_any_count() { - let result = Formatter.format(generalReport, format: .count) + func test_testResult_any_count() { + let formatter = TextFormatter(format: .count, locale: locale) + let result = formatter.format(generalReport) + XCTAssertEqual(result, "7 (0 sec)") } - func test_filter_failure_count() { - let result = Formatter.format(generalReport, filters: [.failed], format: .count) + func test_testResult_failure_count() { + let formatter = TextFormatter(format: .count, locale: locale) + let result = formatter.format(generalReport, testResults: [.failure]) + XCTAssertEqual(result, "3 (0 sec)") } - - func test_filter_slow_list_milliseconds() { - let duration = Duration(value: 100, unit: .milliseconds) - let result = Formatter.format(slowReport(duration: duration), - filters: [.slow(duration: duration)], format: .list) - XCTAssertEqual(result, """ -WriterSpec -✅🕢 (100 ms) Check file exists -✅🕢 (200 ms) Read from file -⚠️🕢 (125 ms) Write to file -""") - } - - func test_filter_slow_list_minutes() { - let duration = Duration(value: 8, unit: .minutes) - let result = Formatter.format(slowReport(duration: duration), - filters: [.slow(duration: duration)], format: .list) - XCTAssertEqual(result, """ -WriterSpec -✅🕢 (8 min) Check file exists -✅🕢 (16 min) Read from file -⚠️🕢 (10 min) Write to file -""") - } - - func test_filter_failed_slow_list_minutes() { - let duration = Duration(value: 8, unit: .minutes) - let result = Formatter.format(slowReport(duration: duration), - filters: [.failed,.slow(duration: duration)], format: .list) - XCTAssertEqual(result, """ -WriterSpec -✅🕢 (8 min) Check file exists -❌ Check folder exists -✅🕢 (16 min) Read from file -⚠️🕢 (10 min) Write to file -""") - } } extension FormatterTests {