swift-testing — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited 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.
Check CLAUDE.md for Testing Mode:
enterprise → consult references/enterprise.md for strict rulesindie → consult references/indie.md for pragmatic rulesAsk if not already clear:
Always test:
Never test:
| Scenario | Framework |
|---|---|
| New unit tests (Swift 5.9+, iOS 16+) | Swift Testing (@Test, #expect) |
| Legacy or team convention on XCTest | XCTest (XCTestCase, XCTAssert*) |
| UI / end-to-end tests | XCTest + XCUITest |
| Async unit tests | Both support async — use await |
Do NOT mix Swift Testing and XCTest in the same test target.
Naming (both frameworks):
test_when_<Condition>_should_<ExpectedOutcome>()Structure — Swift Testing:
import Testing
@testable import MyApp
@MainActor
struct LoginViewModelTests {
@Test func test_when_credentialsAreValid_should_setIsLoggedIn() async throws {
// Arrange
let authService = MockAuthService(willSucceed: true)
let sut = LoginViewModel(authService: authService)
// Act
await sut.login(email: "[email protected]", password: "secret")
// Assert
#expect(sut.isLoggedIn == true)
#expect(sut.error == nil)
}
@Test func test_when_credentialsAreInvalid_should_setError() async throws {
// Arrange
let authService = MockAuthService(willSucceed: false)
let sut = LoginViewModel(authService: authService)
// Act
await sut.login(email: "[email protected]", password: "wrong")
// Assert
#expect(sut.isLoggedIn == false)
#expect(sut.error != nil)
}
}Structure — XCTest:
import XCTest
@testable import MyApp
@MainActor
final class LoginViewModelTests: XCTestCase {
func test_when_credentialsAreValid_should_setIsLoggedIn() async throws {
// Arrange
let authService = MockAuthService(willSucceed: true)
let sut = LoginViewModel(authService: authService)
// Act
await sut.login(email: "[email protected]", password: "secret")
// Assert
XCTAssertTrue(sut.isLoggedIn)
XCTAssertNil(sut.error)
}
}Always generate a mock alongside any test that needs one:
// Always inject via protocol, never use real implementations in unit tests
final class MockAuthService: AuthServiceProtocol {
let willSucceed: Bool
private(set) var loginCallCount = 0
init(willSucceed: Bool) {
self.willSucceed = willSucceed
}
func login(email: String, password: String) async throws -> User {
loginCallCount += 1
if willSucceed {
return User(id: "1", email: email)
} else {
throw AuthError.invalidCredentials
}
}
}Before finalizing, verify every test:
sleep() or pollingDate or a clock protocol)sut instance per testsetUp/tearDown only when truly necessaryUser says: "Write tests for my ProductListViewModel that fetches products from an API"
Actions:
ProductListViewModel.swift to understand state and dependenciesProductRepositoryProtocol or create it if missingMockProductRepository with stubbable resultsUser says: "Test my PriceFormatter that converts cents to currency string"
Actions:
PriceFormatter.swift@Test functions for: zero cents, typical value, large value, locale edge casesAsync tests fail intermittently: You are using sleep() or polling. Replace with async/await and mocked async dependencies that resolve immediately.
Tests break on refactoring: You are testing implementation details (private properties, internal call counts). Refocus on observable output state only.
ViewModel is untestable: Dependencies are created inside the type (NetworkService()). Inject them via init. This is an architecture issue — see swift-architecture-audit skill.
"Cannot find type X in scope": Add @testable import YourModule at the top of the test file.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.