بنقرة واحدة
swift-testing
Swift testing: XCTest, Swift Testing framework, async patterns.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Swift testing: XCTest, Swift Testing framework, async patterns.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Planning lifecycle: specs, requirements, pre-plan ambiguity resolution, file-backed plans, plan validation, pause/resume, session handoff.
Fresh-subagent-per-task execution with two-stage review gates.
Comprehensive 3-wave review of all repo source files, producing a prioritized issue backlog.
Business operations: strategy, technology, growth, competitive intelligence, support, finance, HR, legal, operations, sales, productivity, product management.
Customer support workflows — ticket triage, response drafting, knowledge base articles, escalation handling, customer research. Use when triaging support tickets, drafting customer responses, creating KB articles, managing escalations, or researching customer context.
Finance and accounting: journal entries, reconciliation, variance analysis, financial statements, audit support, month-end close, SOX testing.
| name | swift-testing |
| promoted_to | swift |
| description | Swift testing: XCTest, Swift Testing framework, async patterns. |
| user-invocable | false |
| context | fork |
| agent | swift-general-engineer |
| routing | {"triggers":["swift testing","XCTest","Swift Testing framework","async test swift"],"not_for":"general Swift development (use swift-general-engineer agent) — this skill covers Swift testing: XCTest, Swift Testing framework, test patterns","category":"swift","pairs_with":["swift-concurrency","test-driven-development"]} |
XCTest is Apple's foundational testing framework. Every test class inherits from XCTestCase and uses setUp/tearDown for lifecycle management.
import XCTest
@testable import MyApp
final class UserServiceTests: XCTestCase {
var sut: UserService!
var mockStore: MockUserStore!
override func setUp() {
super.setUp()
mockStore = MockUserStore()
sut = UserService(store: mockStore)
}
override func tearDown() {
sut = nil
mockStore = nil
super.tearDown()
}
func testFetchUser_withValidID_returnsUser() {
mockStore.stubbedUser = User(id: "1", name: "Alice")
let user = sut.fetchUser(id: "1")
XCTAssertNotNil(user)
XCTAssertEqual(user?.name, "Alice")
}
func testFetchUser_withInvalidID_returnsNil() {
mockStore.stubbedUser = nil
let user = sut.fetchUser(id: "unknown")
XCTAssertNil(user)
}
}
The Swift Testing framework replaces XCTest with a more expressive, macro-driven approach. Use @Test for individual tests, #expect for assertions, and @Suite for grouping.
import Testing
@testable import MyApp
@Suite("User Service")
struct UserServiceTests {
let mockStore = MockUserStore()
@Test("fetches user by valid ID")
func fetchValidUser() {
mockStore.stubbedUser = User(id: "1", name: "Alice")
let service = UserService(store: mockStore)
let user = service.fetchUser(id: "1")
#expect(user?.name == "Alice")
}
@Test("returns nil for unknown ID")
func fetchUnknownUser() {
mockStore.stubbedUser = nil
let service = UserService(store: mockStore)
#expect(service.fetchUser(id: "unknown") == nil)
}
}
Swift Testing supports parameterized tests natively, eliminating boilerplate for table-driven patterns.
@Test("validates email formats", arguments: [
("alice@example.com", true),
("bob@", false),
("", false),
("valid+tag@sub.domain.com", true),
])
func emailValidation(email: String, isValid: Bool) {
#expect(EmailValidator.isValid(email) == isValid)
}
XCTest supports async test methods directly. For callback-based APIs, use XCTestExpectation.
// Direct async/await support
func testFetchProfile_async() async throws {
let service = ProfileService(client: MockHTTPClient())
let profile = try await service.fetchProfile(userID: "1")
XCTAssertEqual(profile.name, "Alice")
}
// Callback-based APIs with expectations
func testFetchProfile_callback() {
let expectation = expectation(description: "Profile fetched")
let service = ProfileService(client: MockHTTPClient())
service.fetchProfile(userID: "1") { result in
switch result {
case .success(let profile):
XCTAssertEqual(profile.name, "Alice")
case .failure(let error):
XCTFail("Unexpected error: \(error)")
}
expectation.fulfill()
}
waitForExpectations(timeout: 5)
}
@Test("fetches profile asynchronously")
func fetchProfileAsync() async throws {
let service = ProfileService(client: MockHTTPClient())
let profile = try await service.fetchProfile(userID: "1")
#expect(profile.name == "Alice")
}
UI tests use XCUIApplication to interact with the app as a user would. Always prefer accessibility identifiers over text matching for resilient tests.
final class LoginUITests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
super.setUp()
continueAfterFailure = false
app.launchArguments = ["--uitesting"]
app.launch()
}
func testSuccessfulLogin() {
let emailField = app.textFields["login.emailField"]
let passwordField = app.secureTextFields["login.passwordField"]
let loginButton = app.buttons["login.submitButton"]
emailField.tap()
emailField.typeText("alice@example.com")
passwordField.tap()
passwordField.typeText("password123")
loginButton.tap()
let welcomeLabel = app.staticTexts["home.welcomeLabel"]
XCTAssertTrue(welcomeLabel.waitForExistence(timeout: 5))
XCTAssertEqual(welcomeLabel.label, "Welcome, Alice")
}
}
Set accessibility identifiers in production code:
emailTextField.accessibilityIdentifier = "login.emailField"
passwordTextField.accessibilityIdentifier = "login.passwordField"
submitButton.accessibilityIdentifier = "login.submitButton"
Swift's protocol-oriented design makes mocking straightforward. Define dependencies as protocols, then provide mock implementations in tests.
// Production protocol
protocol HTTPClient {
func data(from url: URL) async throws -> (Data, URLResponse)
}
// Production implementation
struct URLSessionHTTPClient: HTTPClient {
let session: URLSession
func data(from url: URL) async throws -> (Data, URLResponse) {
try await session.data(from: url)
}
}
// Test double
final class MockHTTPClient: HTTPClient {
var stubbedData: Data = Data()
var stubbedResponse: URLResponse = HTTPURLResponse()
var capturedURLs: [URL] = []
func data(from url: URL) async throws -> (Data, URLResponse) {
capturedURLs.append(url)
return (stubbedData, stubbedResponse)
}
}
Inject dependencies through initializers to make classes testable:
final class ProfileService {
private let client: HTTPClient
init(client: HTTPClient) {
self.client = client
}
func fetchProfile(userID: String) async throws -> Profile {
let url = URL(string: "https://api.example.com/users/\(userID)")!
let (data, _) = try await client.data(from: url)
return try JSONDecoder().decode(Profile.self, from: data)
}
}
testFetchUser_withExpiredToken_throwsAuthError is better than testFetch2.@Test and #expect when targeting Swift 5.9+; fall back to XCTest for older targets or UI tests.