关于 xcuitest-skill
xcuitest-skill 为 iOS QA 工程师提供 XCUITest 自动化测试指引,涵盖本地模拟器与 TestMu AI 云端执行,并整理 Swift 测试模式和实践建议。
主要功能
- 01Swift 测试与元素查询
- 02点击、输入及手势操作
- 03断言与系统弹窗处理
- 04页面对象模式及反模式
- 05本地与 TestMu AI 云端运行
适用场景
- 01编写 iOS 登录界面测试
- 02等待并验证界面元素
- 03处理权限弹窗
- 04从 Xcode 或命令行运行测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ lambdatest/ agent-skills --skill xcuitest-skill安装后在 Claude Code 中输入/xcuitest-skill确认已加载。
附带文件reference/advanced-patterns.mdreference/playbook.md
详细介绍
XCUITest 自动化技能
你是一名专攻 XCUITest 的资深 iOS QA 工程师。
步骤 1 — 执行目标
├─ Mentions "cloud", "TestMu", "LambdaTest", "device farm"?
│ └─ TestMu AI cloud (upload IPA + test runner)
│
├─ Mentions "simulator", "local", "Xcode"?
│ └─ Local: Xcode Test Navigator or xcodebuild
│
└─ Default → Local simulator
核心模式 — Swift
基本测试
import XCTest
class LoginTests: XCTestCase {
let app = XCUIApplication()
override func setUpWithError() throws {
continueAfterFailure = false
app.launch()
}
func testLoginWithValidCredentials() {
let emailField = app.textFields["emailInput"]
XCTAssertTrue(emailField.waitForExistence(timeout: 5))
emailField.tap()
emailField.typeText("[email protected]")
let passwordField = app.secureTextFields["passwordInput"]
passwordField.tap()
passwordField.typeText("password123")
app.buttons["loginButton"].tap()
let dashboard = app.staticTexts["Welcome"]
XCTAssertTrue(dashboard.waitForExistence(timeout: 10))
}
func testLoginWithInvalidCredentials() {
app.textFields["emailInput"].tap()
app.textFields["emailInput"].typeText("[email protected]")
app.secureTextFields["passwordInput"].tap()
app.secureTextFields["passwordInput"].typeText("wrong")
app.buttons["loginButton"].tap()
let error = app.staticTexts["Invalid credentials"]
XCTAssertTrue(error.waitForExistence(timeout: 5))
}
}
元素查询
// By accessibility identifier (best)
app.buttons["loginButton"]
app.textFields["emailInput"]
// By label text
app.staticTexts["Welcome back"]
app.buttons["Submit"]
// By predicate
app.buttons.matching(NSPredicate(format: "label CONTAINS 'Login'")).firstMatch
// By index
app.cells.element(boundBy: 0)
// Existence check
let element = app.buttons["submit"]
XCTAssertTrue(element.waitForExistence(timeout: 10))
操作
element.tap() // Tap
element.doubleTap() // Double tap
element.press(forDuration: 2) // Long press
element.typeText("hello") // Type (field must be focused)
element.swipeUp() // Swipe
element.swipeDown()
element.swipeLeft()
element.swipeRight()
element.pinch(withScale: 2, velocity: 1) // Zoom in
element.rotate(CGFloat.pi, withVelocity: 1) // Rotate
断言
XCTAssertTrue(element.exists)
XCTAssertTrue(element.isHittable)
XCTAssertTrue(element.isEnabled)
XCTAssertEqual(element.label, "Expected Label")
XCTAssertEqual(element.value as? String, "Expected Value")
XCTAssertTrue(element.waitForExistence(timeout: 10))
处理系统弹窗
// Auto-handle permission dialogs
addUIInterruptionMonitor(withDescription: "Permission Alert") { alert in
if alert.buttons["Allow"].exists {
alert.buttons["Allow"].tap()
return true
}
return false
}
app.tap() // Trigger the monitor
页面对象模式
protocol Page {
var app: XCUIApplication { get }
}
class LoginPage: Page {
let app: XCUIApplication
init(app: XCUIApplication) { self.app = app }
var emailField: XCUIElement { app.textFields["emailInput"] }
var passwordField: XCUIElement { app.secureTextFields["passwordInput"] }
var loginButton: XCUIElement { app.buttons["loginButton"] }
var errorLabel: XCUIElement { app.staticTexts["errorMessage"] }
func login(email: String, password: String) -> DashboardPage {
emailField.tap()
emailField.typeText(email)
passwordField.tap()
passwordField.typeText(password)
loginButton.tap()
return DashboardPage(app: app)
}
}
反模式
| 不推荐 | 推荐 | 原因 |
|---|---|---|
sleep(5) | waitForExistence(timeout:) | 不可靠 |
| 未等待就查询元素 | 始终先调用 waitForExistence | 竞态条件 |
| 硬编码点击坐标 | 无障碍标识符 | 屏幕尺寸各不相同 |
| 在一个庞大的方法中测试 | 编写小而专注的测试方法 | 隔离性更好 |
TestMu AI Cloud
# 1. Create .ipa from Xcode: Product → Archive → Distribute → Ad Hoc
# 2. Upload app and test runner
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
-X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
-F "[email protected]" -F "type=ios"
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
-X POST "https://manual-api.lambdatest.com/app/upload/realDevice" \
-F "[email protected]" -F "type=ios"
# 3. Execute on real devices
curl -u "$LT_USERNAME:$LT_ACCESS_KEY" \
-X POST "https://mobile-api.lambdatest.com/framework/v1/xcui/build" \
-H "Content-Type: application/json" \
-d '{
"app": "lt://APP123",
"testSuite": "lt://TEST456",
"device": ["iPhone 16-18", "iPhone 15 Pro-17"],
"build": "XCUITest Cloud Build",
"video": true, "deviceLog": true
}'
快速参考
| 任务 | 命令 |
|---|---|
| 从 Xcode 运行 | ⌘U 或 Product → Test |
| 从 CLI 运行 | xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16' |
| 运行特定测试 | xcodebuild test -only-testing:MyAppUITests/LoginTests/testLogin |
| 截图 | let screenshot = XCUIScreen.main.screenshot() |
| 附件 | let attachment = XCTAttachment(screenshot: screenshot) |
| 启动参数 | app.launchArguments = ["--uitesting"] |
| 启动环境变量 | app.launchEnvironment = ["ENV": "test"] |
深入模式
有关高级模式、调试指南、CI/CD 集成和最佳实践,
请参阅 reference/playbook.md。
评论
支持 Markdown