I can't get UI tests to toggle a Toggle in a SwiftUI Form. It seems that app.switches[*name*].tap()
does nothing. Does anyone else have experienced this? Ideas?
The code below is a demonstration of the issue. It's a simple form with four toggles that generates a int value based on the toggles positions.
I have the following SwiftUI view:
struct ContentView: View {
@State var sw1: Bool = false
@State var sw2: Bool = false
@State var sw3: Bool = false
@State var sw4: Bool = false
var valueString: String {
var ret: Int = 0
if sw1 {
ret = ret + 1
}
if sw2 {
ret = ret + 2
}
if sw3 {
ret = ret + 4
}
if sw4 {
ret = ret + 8
}
return String(ret)
}
var body: some View {
NavigationStack {
Form {
Section("Binary switches"){
Toggle("1", isOn: $sw1)
.accessibilityIdentifier("sw1")
Toggle("2", isOn: $sw2)
.accessibilityIdentifier("sw2")
Toggle("4", isOn: $sw3)
.accessibilityIdentifier("sw3")
Toggle("8", isOn: $sw4)
.accessibilityIdentifier("sw4")
}
Section("Value") {
Text(valueString)
.accessibilityIdentifier("value")
.accessibilityValue(valueString)
}
}
.navigationTitle("Test Form")
}
}
}
And the following UI tests Code:
func testRandomSwitches() throws {
let app = XCUIApplication()
app.launch()
// Get the binary switches
let sw1 = app.switches["sw1"]
let sw2 = app.switches["sw2"]
let sw3 = app.switches["sw3"]
let sw4 = app.switches["sw4"]
// randomly switch on some of the switches
let randomOnes = [sw1, sw2, sw3, sw4].map { _ in Bool.random() }
if randomOnes[0] { sw1.tap() }
if randomOnes[1] { sw2.tap() }
if randomOnes[2] { sw3.tap() }
if randomOnes[3] { sw4.tap() }
// calculate the expected value
let expectedValue = randomOnes.enumerated()
.filter { $0.element }
.map { 1 << $0.offset }
.reduce(0, +)
// get the value text and assert that it matches the expected value
let value = app.staticTexts["value"].value as? String ?? ""
XCTAssertEqual(value, String(expectedValue))
}
When I run this test, the switches never get toggled, and the value string always reads "0". The UITest code fails on XCTAssertEqual(value, String(expectedValue))
. I'm not sure what I'm doing wrong.
If I try to record the toggle tap I always get the error "Timestamped Event Matching Error: Failed to find matching element".
Can anyone help me figure out why the switches aren't getting toggled in my UI tests?
Figured it out. It seems that I need to access the first switch in the switch. Really weird. But I gess UI testing is weird. It would be much appreciated if anyone got a less hacky solution.
Non working code:
sw1.tap()
Working code:
sw1.switches.firstMatch.tap()