arisguimera/mobiai-core/mobiai-ios-testing

Claude Code and agent skill by arisguimera/mobiai-core

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when writing or running tests in an iOS project — unit tests, UI tests, snapshot tests, choosing the right framework.

Install

npx vskill@latest install arisguimera/mobiai-core/mobiai-ios-testing

SKILL.md

iOS Testing

Community contribution welcome! Help improve this skill with your XCTest patterns, mocking strategies, and testing tips.

Guide to writing and running tests in iOS projects.

When to Use

  • Writing unit tests for Swift code
  • Setting up test infrastructure
  • Running and debugging test suites

Test Types

TypeTargetFrameworkSpeed
UnitMyAppTestsXCTestFast
UIMyAppUITestsXCUITestSlow
SnapshotMyAppTestsSnapshotTesting (pointfree)Medium

Unit Testing (XCTest)

File Location
  • Source: MyApp/Feature/MyViewModel.swift
  • Test: MyAppTests/Feature/MyViewModelTests.swift
Test Structure
swift
import XCTest
@testable import MyApp
final class MyViewModelTests: XCTestCase {
private var sut: MyViewModel!
private var mockRepository: MockRepository!
override func setUp() {
super.setUp()
mockRepository = MockRepository()
sut = MyViewModel(repository: mockRepository)
}
override func tearDown() {
sut = nil
mockRepository = nil
super.tearDown()
}
func testLoadData_setsStateToSuccess_whenRepositoryReturnsData() async {
// Given
mockRepository.stubbedResult = [Item(id: "1", name: "Test")]
// When
await sut.loadData()
// Then
XCTAssertEqual(sut.state, .success([Item(id: "1", name: "Test")]))
}
func testLoadData_setsStateToError_whenRepositoryThrows() async {
// Given
mockRepository.stubbedError = NSError(domain: "", code: -1)
// When
await sut.loadData()
// Then
if case .error = sut.state {
// Expected
} else {
XCTFail("Expected error state")
}
}
}
Naming Conventions
swift
// Pattern: testMethodName_expectedBehavior_whenCondition
func testCalculateTotal_returnsZero_whenCartIsEmpty() { ... }
func testFormatPrice_throws_whenAmountIsNegative() { ... }
Async Testing
swift
// async/await
func testFetchData_returnsItems() async throws {
let items = try await sut.fetchData()
XCTAssertFalse(items.isEmpty)
}
// Combine
func testPublisher_emitsValue() {
let expectation = expectation(description: "Value emitted")
var received: String?
sut.publisher
.sink { value in
received = value
expectation.fulfill()
}
.store(in: &cancellables)
sut.trigger()
wait(for: [expectation], timeout: 1.0)
XCTAssertEqual(received, "expected")
}
Manual Mocking (No Framework)
swift
class MockRepository: RepositoryProtocol {
var stubbedResult: [Item] = []
var stubbedError: Error?
var fetchDataCallCount = 0
func fetchData() async throws -> [Item] {
fetchDataCallCount += 1
if let error = stubbedError { throw error }
return stubbedResult
}
}

XCUITest (UI Testing)

swift
final class MyAppUITests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
super.setUp()
continueAfterFailure = false
app.launch()
}
func testLogin_navigatesToHome() {
app.textFields["Email"].tap()
app.textFields["Email"].typeText("test@test.com")
app.secureTextFields["Password"].tap()
app.secureTextFields["Password"].typeText("password")
app.buttons["Login"].tap()
XCTAssertTrue(app.staticTexts["Welcome"].waitForExistence(timeout: 5))
}
}

Running Tests

bash
# All unit tests
xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15 Pro' -quiet
# Specific test class
xcodebuild test -scheme MyApp -destination '...' -only-testing:MyAppTests/MyViewModelTests
# Specific test method
xcodebuild test -scheme MyApp -destination '...' -only-testing:MyAppTests/MyViewModelTests/testLoadData_setsStateToSuccess
# UI tests
xcodebuild test -scheme MyApp -destination '...' -only-testing:MyAppUITests

Quick/Nimble (BDD Style)

swift
import Quick
import Nimble
@testable import MyApp
class MyViewModelSpec: QuickSpec {
override class func spec() {
describe("MyViewModel") {
var sut: MyViewModel!
beforeEach { sut = MyViewModel() }
context("when data loads successfully") {
it("sets state to success") {
expect(sut.state).toEventually(equal(.success))
}
}
}
}
}

Want to improve this skill? Add your testing patterns, mocking strategies, and CI tips via a PR.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
391
Repository forks
12
7-day trend score
30

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/arisguimera/mobiai-core/mobiai-ios-testing/badge)](https://verified-skill.com/skills/arisguimera/mobiai-core/mobiai-ios-testing)

Something wrong with this skill or its page? Tell us.