SwiftUI’ni testlash
Xatti-harakat va jarayonlarni tekshirish uchun view model’lar uchun unit testlar, SwiftUI view’lar uchun esa UI testlar yozing.
ViewModel’ni unit test qilish
Biznes mantiqni ViewModel’ga joylashtiring va uni XCTestCase yordamida tekshiring.
Sintaksis:
final class MyTests: XCTestCase { ... }XCTAssertEqual,XCTAssertTruekabi tasdiqlashlar (assertions)
Misol
import SwiftUI
import Combine
final class CounterViewModel: ObservableObject {
@Published private(set) var count = 0
func increment() { count += 1 }
}
struct CounterView: View {
@StateObject private var vm = 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()
vm.increment()
XCTAssertEqual(vm.count, 1)
}
}
Ushbu misol increment() chaqirilishi e’lon qilingan (published) count qiymatini yangilashini tekshiradi.
Dastlabki talablar (UI Testing target’i)
- UI Testing Bundle target’ini qo‘shing (File → New → Target → UI Testing Bundle).
- Elementlarni ko‘rinadigan matn bo‘yicha emas, balki accessibility identifikatorlari bo‘yicha topishni afzal ko‘ring.
- Testlar uchun ilova holatini boshqarish maqsadida ishga tushirish argumentlari va environment qiymatlarini uzating (masalan, ma’lumotlarni tozalash, soxta obyektlardan (fakes) foydalanish).
SwiftUI view’ni UI test qilish
Ilovani XCUIApplication yordamida boshqaring va elementlarni accessibility orqali toping.
Sintaksis:
let app = XCUIApplication(); app.launch()app.buttons["Label"].tap()
Misol
import SwiftUI
struct UITestDemo: View {
@State private var count = 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 = ProcessInfo.processInfo.arguments
let env = ProcessInfo.processInfo.environment
if args.contains("-ui-testing") || env["UITEST_RESET"] == "1" {
// Reset state, use mock stores/services, disable animations, etc.
// UIView.setAnimationsEnabled(false) can be used where applicable.
}
}
var body: some Scene { WindowGroup { ContentView() } }
}
import XCTest
final class MyUITests: XCTestCase {
func testIncrementButton() {
let app = XCUIApplication()
app.launchArguments = ["-ui-testing"]
app.launchEnvironment = ["UITEST_RESET": "1"]
app.launch()
let button = app.buttons["incrementButton"]
XCTAssertTrue(button.waitForExistence(timeout: 2))
button.tap()
let label = app.staticTexts["countLabel"]
XCTAssertTrue(label.waitForExistence(timeout: 2))
XCTAssertTrue(label.label.contains("Count: 1"))
}
}
Ushbu misol ilovani ishga tushiradi, tugmani bosadi va yorliq mavjudligini uning accessibility identifikatori orqali tasdiqlaydi.
Maslahat: Unit testlashni osonlashtirish uchun mantiqni view model’larda saqlang; navigatsiya va o‘zaro ta’sir jarayonlari uchun UI testlardan foydalaning.
Testlarni ishonchliroq qilish uchun waitForExistence dan foydalaning va oldindan aniq (deterministik) holatni o‘rnatish uchun ishga tushirish bayroqlarini uzating.
W3Schools Pathfinder
Yutuqlaringizni kuzating – bu bepul!
