تست SwiftUI (Testing SwiftUI)
اینجا یاد می گیری «تست SwiftUI» یعنی بررسی رفتار رابط. «تست واحد (Unit Test)» منطق را می سنجد. «تست رابط (UI Test)» جریان کلی را چک می کند. مثل تصحیح تکلیف و همچنین اجرای نمایشی در کلاس.
تست واحد ViewModel با XCTest
ViewModel منطق کسب وکار است. «XCTest» چارچوب تست اپل است. ما با «XCTAssert» انتظارها را بررسی می کنیم. پس نتیجه ها دقیق می مانند.
- یک ViewModel ساده بساز.
- یک Case از XCTest ایجاد کن.
- تابع را صدا بزن و مقدار را Assert کن.
import SwiftUI
import Combine
final class CounterViewModel: ObservableObject {
@Published private(set) var count: Int = 0
func increment() {
count += 1
}
}
struct CounterView: View {
@StateObject private var vm: CounterViewModel = CounterViewModel()
var body: some View {
VStack(spacing: 12) {
Text("Count: \(vm.count)")
Button("Increment") {
vm.increment()
}
}
}
}
import SwiftUI
struct ContentView: View {
var body: some View {
CounterView()
}
}
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
import XCTest
final class CounterViewModelTests: XCTestCase {
func testIncrement() {
let vm: CounterViewModel = CounterViewModel()
vm.increment()
XCTAssertEqual(vm.count, 1)
}
}
پیش نیازهای تست رابط کاربری (UI Testing)
- Target نوع UI Testing Bundle بساز.
- شناسه دسترس پذیری بده؛ جستجو دقیق تر می شود.
- آرگومان و محیط اجرا بده؛ وضعیت تست کنترل شود.
تست رابط SwiftUI با XCUIApplication
در «UI Test»، برنامه با «XCUIApplication» اجرا می شود. سپس دکمه ها را با شناسه می یابیم. بعد رویدادها را شبیه سازی می کنیم. مانند تمرین تئاتر روی صحنه.
- برای اجزا شناسه بگذار.
- اپ را با آرگومان تست اجرا کن.
- Tap بزن و برچسب را Assert کن.
import SwiftUI
struct UITestDemo: View {
@State private var count: Int = 0
var body: some View {
VStack(spacing: 12) {
Text("Count: \(count)")
.accessibilityIdentifier("countLabel")
Button("Increment") {
count += 1
}
.accessibilityIdentifier("incrementButton")
}
}
}
import SwiftUI
struct ContentView: View {
var body: some View {
UITestDemo()
}
}
import SwiftUI
@main
struct MyApp: App {
init() {
let args: [String] = ProcessInfo.processInfo.arguments
let env: [String : String] = ProcessInfo.processInfo.environment
if args.contains("-ui-testing") || env["UITEST_RESET"] == "1" {
// اینجا وضعیت را برای تست تنظیم کن.
// داده را ریست کن یا سرویس ساختگی بده.
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
import XCTest
final class MyUITests: XCTestCase {
func testIncrementButton() {
let app: XCUIApplication = XCUIApplication()
app.launchArguments = ["-ui-testing"]
app.launchEnvironment = ["UITEST_RESET": "1"]
app.launch()
let button: XCUIElement = app.buttons["incrementButton"]
XCTAssertTrue(button.waitForExistence(timeout: 2.0))
button.tap()
let label: XCUIElement = app.staticTexts["countLabel"]
XCTAssertTrue(label.waitForExistence(timeout: 2.0))
XCTAssertTrue(label.label.contains("Count: 1"))
}
}
جمع بندی سریع
- منطق در ViewModel تست شود.
- شناسه دسترس پذیری فراموش نشود.
- از launchArguments برای حالت تست استفاده کن.
- از waitForExistence برای پایداری استفاده کن.
نکته: مسیر بعدی: معماری MVVM را ببین. همچنین AppStorage و SceneStorage را بررسی کن. برای دسترسی سریع، تست SwiftUI را نشانه گذاری کن.