The PeekieSDK package provides a Swift module for parsing .xcresult files generated by Xcode to produce a structured report of build and test results. It supports both XCTest and Swift Testing frameworks, and works with the modern .xcresult format (without requiring the --legacy flag). It allows developers to programmatically access detailed information about test cases, code coverage, and warnings from their CI/CD pipelines or automated scripts.
- Supports XCTest and Swift Testing frameworks.
- Parses modern
.xcresultformat (usesxcresulttoolwithout--legacyflag). - Parses
.xcresultfiles to create a typed model of the test results and code coverage. - Filters out coverage data related to test helpers and test cases.
- Provides a detailed breakdown of modules, files, and repeatable tests.
- Extracts build warnings from
.xcresultfiles (Swift Compiler Warnings only). - Calculates total and average test durations, as well as combined test statuses.
- Supports identifying slow tests based on average duration.
- Includes utility functions for filtering tests based on status.
- Can be executed as a command-line tool to generate test reports directly from the terminal.
To use PeekieSDK in your Swift package, add it to the dependencies for your Package.swift file:
let package = Package(
name: "YourPackageName",
dependencies: [
.package(url: "https://github.com/dodobrands/DBXCResultParser", .upToNextMajor(from: "3.0.0"))
],
targets: [
.target(
name: "YourTargetName",
dependencies: ["PeekieSDK"]
)
]
)To parse an .xcresult file and access the report data, initialize a Report with the path to the .xcresult file:
import PeekieSDK
let xcresultPath = URL(fileURLWithPath: "/path/to/your.xcresult")
let reportModel = try await Report(xcresultPath: xcresultPath)
// Access different parts of the report:
let modules = reportModel.modules
let coverage = reportModel.coverage // Coverage value from 0.0 to 1.0
let warnings = reportModel.warnings // Array of build warnings
// Access warnings:
for warning in warnings {
print("Warning: \(warning.message)")
print(" Location: \(warning.sourceURL)")
print(" Class: \(warning.className)")
}
// Iterate over modules, files, and tests:
for module in modules {
print("Module: \(module.name)")
for file in module.files {
print(" File: \(file.name)")
for repeatableTest in file.repeatableTests {
print(" Repeatable Test: \(repeatableTest.name)")
for test in repeatableTest.tests {
print(" Test: \(test.status.icon) - Duration: \(test.duration)")
}
}
}
}The TextFormatter class provides a way to format the data from a Report into a human-readable string. It supports two output formats: a detailed list of test results and a summary count of test results.
To format your test report data, create an instance of TextFormatter:
import PeekieSDK
// Assuming you have already created a `Report` instance as `reportModel`
let reportModel: Report = ...
// Create a text formatter
let formatter = TextFormatter()
// Format the report data into a string
let formattedOutput = formatter.format(reportModel)
// Print the formatted output
print("Formatted Output:\n\(formattedOutput)")The format method can also take an array of Report.Module.File.RepeatableTest.Test.Status to filter which test results are included in the output. By default, it includes all test statuses.
Filtering by status:
// Only show failures
let failuresOnly = formatter.format(reportModel, include: [.failure])
// Show both failures and skipped tests
let failuresAndSkipped = formatter.format(reportModel, include: [.failure, .skipped])
// Show only successful tests
let successesOnly = formatter.format(reportModel, include: [.success])Using count format:
// Get summary count instead of detailed list
let summary = formatter.format(reportModel, format: .count)
// Output: "12 tests (1m 23s)"
// Count only failures
let failureCount = formatter.format(reportModel, include: [.failure], format: .count)
// Output: "3 tests (45s)"Outputs a detailed list of test results, including the name of each file and the status of each test.
Basic Test Statuses:
β- Successβ- FailureβοΈ- Skippedπ€‘- Expected Failureβ οΈ- Mixed (flaky test with different results across retries)π€·- Unknown
Example output:
FileA.swift
β
test_success()
β test_failure() (Failure message)
βοΈ test_skip() (Skip message)
π€‘ test_expectedFailure() (Failure is expected)
β οΈ test_flacky() (Flacky failure message)
FileB.swift
β
test_success()
Parameterized Tests (Swift Testing): Each argument from parameterized tests is displayed as a separate test line with its own status:
FakeSUITests
β
success()
β failure() (GenerateXCResultTests.swift:56: Issue recorded: Failure message)
βοΈ disabled() (Test 'disabled()' skipped: Disabled reason)
π€‘ expectedFailure()
β οΈ flacky() (GenerateXCResultTests.swift:75: Issue recorded: Flacky failure message)
β
flackyParameterized(value:) (true)
β flackyParameterized(value:) (false)
β
somethingWithWarning()
Outputs a summary count of test results, including the total number of tests and their combined duration.
12 tests (1m 23s)
When filtering by status (e.g., only failures), duration is omitted if only skipped tests are included:
5 tests
The TextFormatter allows you to specify a locale when formatting the report. This locale is used to format numbers and measurements according to the provided locale's conventions.
let formatter = TextFormatter()
let output = formatter.format(reportModel, locale: Locale(identifier: "fr_FR"))
print(output) // Will output numbers and durations formatted in FrenchThe package includes a command-line tool that can be executed to generate test reports. Here is an example of how to run it:
swift run peekie --xcresult-path path/to/tests.xcresultExamples:
# Default: list format with all test statuses
swift run peekie --xcresult-path path/to/tests.xcresult
# Count format (summary)
swift run peekie --xcresult-path path/to/tests.xcresult --format count
# Show only failures
swift run peekie --xcresult-path path/to/tests.xcresult --include failure
# Show failures and skipped tests
swift run peekie --xcresult-path path/to/tests.xcresult --include failure,skipped
# Use specific locale for formatting
swift run peekie --xcresult-path path/to/tests.xcresult --locale ru-RU
# Combine options: count format with only failures, using French locale
swift run peekie --xcresult-path path/to/tests.xcresult --format count --include failure --locale fr-FRAvailable options:
--xcresult-path: Specifies the path to the.xcresultfile (required).--format: Determines the output format (listorcount). Default:list.--locale: Sets the locale for number and measurement formatting (e.g., "en-GB", "ru-RU", "fr-FR"). Default: system locale.--include: Filters the test results to include only certain statuses. Comma-separated list of:success,failure,skipped,expectedFailure,mixed,unknown. Default: all statuses.
This code is released under the Apache License. See LICENSE for more information.