my-ios-app-swift-testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited my-ios-app-swift-testing (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Swift Testing is the modern testing framework for Swift (Xcode 16+, Swift 6+). Prefer it over XCTest for all new unit tests. Use XCTest only for UI tests, performance benchmarks, and snapshot tests.
@Test Traits@Suite and Test Organizationimport Testing
@Test("User can update their display name")
func updateDisplayName() {
var user = User(name: "Alice")
user.name = "Bob"
#expect(user.name == "Bob")
}@Test Traits@Test("Validates email format") // display name
@Test(.tags(.validation, .email)) // tags
@Test(.disabled("Server migration in progress")) // disabled
@Test(.enabled(if: ProcessInfo.processInfo.environment["CI"] != nil)) // conditional
@Test(.bug("https://github.com/org/repo/issues/42")) // bug reference
@Test(.timeLimit(.minutes(1))) // time limit
@Test("Timeout handling", .tags(.networking), .timeLimit(.seconds(30))) // combined// #expect records failure but continues execution
#expect(result == 42)
#expect(name.isEmpty == false)
#expect(items.count > 0, "Items should not be empty")
// #expect with error type checking
#expect(throws: ValidationError.self) {
try validate(email: "not-an-email")
}
// #expect with specific error value
#expect {
try validate(email: "")
} throws: { error in
guard let err = error as? ValidationError else { return false }
return err == .empty
}
// #require records failure AND stops test (like XCTUnwrap)
let user = try #require(await fetchUser(id: 1))
#expect(user.name == "Alice")
// #require for optionals -- unwraps or fails
let first = try #require(items.first)
#expect(first.isValid)Rule: Use `#require` when subsequent assertions depend on the value. Use `#expect` for independent checks.
@Suite and Test OrganizationSee references/testing-patterns.md for suite organization, confirmation patterns, known-issue handling, and execution-model details.
Swift Testing runs tests in parallel by default. Do not assume test order, shared suite instances, or exclusive access to mutable state unless you explicitly design for it.
@Suite(.serialized)
struct KeychainTests {
@Test func storesToken() throws { /* ... */ }
@Test func deletesToken() throws { /* ... */ }
}Use .serialized when a test or suite must run one-at-a-time because it touches shared external state. It does not make unrelated tests outside that scope run serially.
Rules:
@Suite(.serialized) is for exclusive execution, not for expressing logical ordering between tests.Swift Testing unit tests do not inherit from XCTestCase. Declare @Test on free functions, global functions, or methods on suite types such as struct, class, or actor; use static or class methods when instance fixtures are not needed.
When reviewing migration code or plans, do not collapse every XCTest construct into #expect. Include a compact assertion-mapping note or table in the answer so required unwraps and unconditional manual failures are not lost, even when the user only says "replace every XCTAssert with #expect."
State coexistence explicitly: XCTest and Swift Testing can coexist during migration. Keep UI automation, performance benchmarks, and common snapshot-test flows on XCTest/XCUITest or snapshot tooling, and separate files or targets when that makes runner expectations clearer.
Migration defaults:
XCTAssert* -> #expect(...)XCTUnwrap or any value required by later checks -> try #require(...)XCTFail("...") or manual unconditional issues -> Issue.record("...")@available on individual @Test functions, not on suite types or their containing types.let user = try #require(optionalUser)
#expect(user.isActive)
guard featureFlag.isEnabled else {
Issue.record("Expected feature flag to be enabled")
return
}See references/testing-patterns.md for migration examples and references/testing-advanced.md for Swift/Xcode version gates.
Mark expected failures so they do not cause test failure:
withKnownIssue("Propane tank is empty") {
#expect(truck.grill.isHeating)
}
// Intermittent / flaky failures
withKnownIssue(isIntermittent: true) {
#expect(service.isReachable)
}
// Conditional known issue
withKnownIssue {
#expect(foodTruck.grill.isHeating)
} when: {
!hasPropane
}If no known issues are recorded, Swift Testing records a distinct issue notifying you the problem may be resolved.
See references/testing-patterns.md for parameterized tests, tags and suites, async testing, traits, and execution-model details.
Attach diagnostic data to test results for debugging failures. See references/testing-patterns.md for full examples.
@Test func generateReport() async throws {
let report = try generateReport()
Attachment.record(report.data, named: "report.json")
#expect(report.isValid)
}Image attachments require Swift 6.3 / Xcode 26.4 or newer. Import Testing plus the relevant UI framework, then record the platform image value directly:
import Testing
import UIKit
@Test func renderedChart() async throws {
let image = renderer.image { ctx in chartView.drawHierarchy(in: bounds, afterScreenUpdates: true) }
Attachment.record(image, named: "chart", as: .png)
}Test code that calls exit(), fatalError(), or preconditionFailure(). Exit testing requires Swift 6.2 / Xcode 26.0 or newer and is supported on macOS, Linux, FreeBSD, OpenBSD, and Windows runtime targets, not iOS, tvOS, or watchOS. When correcting exit-test code, name both the toolchain floor and runtime support. See references/testing-patterns.md for details.
@Test func invalidInputCausesExit() async {
await #expect(processExitsWith: .failure) {
processInvalidInput() // calls fatalError()
}
}For advanced Swift Testing APIs, check the toolchain before recommending them. When reviewing user code that mentions one of these APIs, name the gate for each API you correct:
Sendable and Codable.Test.cancel(_:), Issue.record(_:severity:), and image attachment recording require Swift 6.3 / Xcode 26.4-era support as noted in references/testing-advanced.md.Test.cancel(_:) sample, state both shape and gate: the test must be throws or async throws, and Test.cancel(_:) requires Swift 6.3 / Xcode 26.4-era support.@Test func exitsWithCapturedCode() async {
let expectedCode: Int32 = 42
await #expect(processExitsWith: .failure) { [expectedCode] in
exit(expectedCode)
}
}When reviewing stale or beta-era Swift Testing samples, include the exact correction and the gate for every API the prompt mentions:
| User code to correct | Current guidance |
|---|---|
#expect(exitsWith:) | Use await #expect(processExitsWith: .failure) { ... }. Exit testing requires Swift 6.2 / Xcode 26.0 or newer and is supported on macOS, Linux, FreeBSD, OpenBSD, and Windows runtime targets, not iOS, tvOS, or watchOS. For an iOS app target, test fatal-path logic through a smaller non-exiting API or a supported host/tool target. |
| Exit-test closure reads outer values | Add an explicit capture list, for example { [expectedCode] in ... }. Exit-test capture lists require the Swift 6.3 compiler; captured values must be Sendable and Codable. |
Test.cancel() in a test that awaits work | Make the test async throws and call try Test.cancel("reason"). Test.cancel(_:) requires Swift 6.3 / Xcode 26.4-era support. |
Issue.record(..., severity: .warning) | Use Issue.record("message", severity: .warning). Warning severity is reported but does not fail the test, and requires Swift 6.3 / Xcode 26.4-era support. |
Attachment(image, named:).record() | Use Attachment.record(image, named: "name", as: .png). Import Testing plus the relevant image framework; Apple-platform image values include UIImage, CGImage, CIImage, and NSImage. Image attachment recording requires Swift 6.3 / Xcode 26.4-era support. |
confirmation with expected counts, not sleep calls.init() in @Suite.confirmation, clock injection, or withKnownIssue.Task cancellation, verify it cancels cleanly.@MainActor..serialized only when exclusive execution is required.@Test, #expect), not XCTest assertionsfetchUserReturnsNilOnNetworkError not testFetchUser)confirmation(), not Task.sleep.critical, .slow).serialized used only for truly exclusive state, not to model workflow sequencing~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.