
Ios Testing
- 22 installs
- 60 repo stars
- Updated June 14, 2026
- ahmed3elshaer/everything-claude-code-mobile
ios-testing is a Claude Code skill providing XCTest unit, async, and UI testing patterns for Swift and SwiftUI apps.
About
ios-testing is a Claude Code skill with iOS testing patterns using XCTest. A developer uses it to write unit tests, mocks, async tests, and XCUITest UI tests for Swift and SwiftUI apps. It shows setUp/tearDown structure, protocol-based mocking, and property-style validation tests.
- XCTest unit tests with protocol-based mocking and given/when/then structure
- Async testing with expectations and async/await
- XCUITest UI tests with launch arguments and accessibility identifiers
Ios Testing by the numbers
- 22 all-time installs (skills.sh)
- Ranked #1,413 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
ios-testing capabilities & compatibility
- Capabilities
- ios testing · xctest · ui testing · mocking
- Use cases
- testing
What ios-testing says it does
iOS testing with XCTest. Unit tests, UI tests, mocks, and test patterns for Swift/SwiftUI.
Testing patterns for Swift and SwiftUI apps.
npx skills add https://github.com/ahmed3elshaer/everything-claude-code-mobile --skill ios-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 22 |
|---|---|
| repo stars | ★ 60 |
| Last updated | June 14, 2026 |
| Repository | ahmed3elshaer/everything-claude-code-mobile ↗ |
What it does
Write XCTest unit, async, and UI tests for a Swift/SwiftUI iOS app.
Who is it for?
iOS developers writing XCTest unit and UI tests
Skip if: Android or Kotlin test frameworks
When should I use this skill?
You are writing unit, async, or UI tests for a Swift/SwiftUI app
By the numbers
- Covers unit, async, property, and UI test styles
- Uses given/when/then structure
Files
iOS Testing
Testing patterns for Swift and SwiftUI apps.
Unit Tests
Basic Unit Test
import XCTest
@testable import MyApp
class UserViewModelTests: XCTestCase {
var sut: UserViewModel!
var mockService: MockUserService!
override func setUp() {
super.setUp()
mockService = MockUserService()
sut = UserViewModel(service: mockService)
}
override func tearDown() {
sut = nil
mockService = nil
super.tearDown()
}
func testLoadUsers_whenSuccessful_populatesUsers() async throws {
// Given
let expectedUsers = [User.mock1, User.mock2]
mockService.usersToReturn = expectedUsers
// When
await sut.loadUsers()
// Then
XCTAssertEqual(sut.users, expectedUsers)
XCTAssertFalse(sut.isLoading)
XCTAssertNil(sut.errorMessage)
}
func testLoadUsers_whenFailure_setsErrorMessage() async throws {
// Given
mockService.shouldThrowError = true
// When
await sut.loadUsers()
// Then
XCTAssertTrue(sut.users.isEmpty)
XCTAssertNotNil(sut.errorMessage)
}
}Mocking
// ✅ Protocol-based mocking
protocol UserServiceProtocol {
func getUsers() async throws -> [User]
}
class MockUserService: UserServiceProtocol {
var usersToReturn: [User] = []
var shouldThrowError = false
var getUsersCalled = false
func getUsers() async throws -> [User] {
getUsersCalled = true
if shouldThrowError {
throw NetworkError.noConnection
}
return usersToReturn
}
}
// ✅ Verify method calls
func testRefreshButton_callsService() async {
// When
await sut.refresh()
// Then
XCTAssertTrue(mockService.getUsersCalled)
}Async Testing
func testAsyncOperation_completesSuccessfully() async throws {
// Given
let expectation = expectation(description: "Async completes")
// When
Task {
await sut.asyncOperation()
expectation.fulfill()
}
// Then
await fulfillment(of: [expectation], timeout: 1.0)
}
// ✅ Swift async/await
func testAsyncFetch_returnsUsers() async throws {
let users = try await sut.fetchUsers()
XCTAssertFalse(users.isEmpty)
}Property Testing
func testUserValidation_validEmails() {
let validEmails = [
"test@example.com",
"user.name@example.co.uk",
"user+tag@example.com"
]
for email in validEmails {
XCTAssertTrue(Validator.isValidEmail(email), "Failed for: \(email)")
}
}
func testUserValidation_invalidEmails() {
let invalidEmails = [
"invalid",
"@example.com",
"user@",
"user @example.com"
]
for email in invalidEmails {
XCTAssertFalse(Validator.isValidEmail(email), "Passed for: \(email)")
}
}UI Tests
Basic UI Test
import XCTest
class LoginUITests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
continueAfterFailure = false
app = XCUIApplication()
app.launchArguments = ["--uitesting"]
app.launch()
}
func testLoginButton_enabledWhenFieldsFilled() {
// When
let emailField = app.textFields["emailField"]
let passwordField = app.secureTextFields["passwordField"]
let loginButton = app.buttons["loginButton"]
// Then
XCTAssertFalse(loginButton.isEnabled)
// When
emailField.tap()
emailField.typeText("test@example.com")
passwordField.tap()
passwordField.typeText("password123")
// Then
XCTAssertTrue(loginButton.isEnabled)
}
func testSuccessfulLogin_navigatesToHome() {
// Given
app.textFields["emailField"].tap()
app.textFields["emailField"].typeText("test@example.com")
app.secureTextFields["passwordField"].tap()
app.secureTextFields["passwordField"].typeText("password123")
// When
app.buttons["loginButton"].tap()
// Then
XCTAssertTrue(app.staticTexts["welcomeMessage"].exists)
}
}Snapshot Testing
// ✅ Using View snapshot testing
import SwiftUI
import XCTest
struct UserCard_Previews: PreviewProvider {
static var previews: some View {
UserCard(user: .mock)
}
}
// Snapshot test
func testUserCard_snapshot() {
let view = UserCard(user: .mock)
assertSnapshot(matching: view, as: .image(layout: .sizeThatFits))
}Testing SwiftUI Views
import XCTest
import ViewInspector // https://github.com/nalexn/ViewInspector
class UserRowTests: XCTestCase {
func testUserRow_displaysUserName() throws {
let user = User(id: "1", name: "John Doe", email: "john@example.com")
let view = UserRow(user: user)
let text = try view.inspect().find(ViewType.Text.self).string()
XCTAssertEqual(text, "John Doe")
}
func testUserRow_tapping_callsAction() throws {
let user = User(id: "1", name: "John", email: "john@example.com")
var tapped = false
let view = UserRow(user: user, onTap: { tapped = true })
try view.inspect().find(ViewType.Button.self).tap()
XCTAssertTrue(tapped)
}
}Test Helpers
// ✅ Test doubles
extension User {
static let mock1 = User(id: "1", name: "John", email: "john@example.com")
static let mock2 = User(id: "2", name: "Jane", email: "jane@example.com")
}
// ✅ Wait helpers
func waitForElementToExist(
_ element: XCUIElement,
timeout: TimeInterval = 5.0
) -> Bool {
let existsPredicate = NSPredicate(format: "exists == true")
let expectation = expectation(for: existsPredicate, evaluatedWith: element)
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
return result == .completed
}Performance Tests
func testUserParsing_performance() {
let jsonData = largeUserJSONData
measure {
_ = try? JSONDecoder().decode([User].self, from: jsonData)
}
}Test Organization
Tests/
├── Unit/
│ ├── ViewModels/
│ │ ├── HomeViewModelTests.swift
│ │ └── ProfileViewModelTests.swift
│ ├── Services/
│ │ ├── UserServiceTests.swift
│ │ └── NetworkServiceTests.swift
│ └── Models/
│ └── UserTests.swift
├── UI/
│ ├── LoginUITests.swift
│ └── HomeUITests.swift
└── Mocks/
├── MockUserService.swift
└── MockNetworkService.swift---
Remember: Tests are your safety net. Write them first (TDD) or alongside your code, but always maintain them.
Related skills
FAQ
Does it cover UI tests?
Yes. It includes XCUITest examples with launch arguments and accessibility identifiers for buttons and fields.
How does it handle async?
It shows both XCTest expectations with fulfillment and direct async/await test methods.