如何为 SwiftUI InputField 编写 UI 测试

How can I write UI tests for a SwiftUI InputField

我有这个 SwiftUI 视图(将删除 non-relevant 部分)

struct LoginView: View {
    
    var body: some View {
        VStack {
            Spacer()
            InputField(title: "Email", text: $email)
            InputField(title: "Password", text: $password, showingSecureField: true)
            InputField(title: "Store", text: $userStore)
            CallToActionButton(
                title: newUser ? "Register User" : "Log In",
                action: userAction
            )
            Button(action: { newUser.toggle() }) {
                HStack {
                    CheckBox(title: "Create Account", isChecked: $newUser)
                    Spacer()
                }
            }
            Spacer()
        }
    }

我可以使用以下代码为该按钮编写 UI 测试:

    func testClickLoginButton() throws {
        let app = XCUIApplication()
        app.launch()
                  
        let startButton = app.buttons["Log In"]
        XCTAssertTrue(startButton.waitForExistence(timeout: 1))
        XCTAssertTrue(startButton.isEnabled)
        startButton.tap()
    }

它起作用了,因为屏幕上有一个带有该标题的按钮。

但后来我想自动在这些 InputText 中放入一些文本并对其进行测试,但找不到它们,因为它们既不是 UITextField 也不是 UITextView。我怎样才能做到这一点?谢谢!

    func testAddEmail() throws {
        let app = XCUIApplication()
        app.launch()

        // fails as can't find any text field containing "Email"
                           
        let emailText = app.textFields["Email"]
        XCTAssertTrue(emailText.waitForExistence(timeout: 1))
        emailText.typeText("testemail@realm.com")
        XCTAssertEqual(emailText.value as! String, "testemail@realm.com")
    }

如何添加:

 InputField(title: "Email", text: $email)
        .accessibility(identifier: "email_input")

对于您想从 UI 测试中测试的任何其他元素也是如此吗?

我不是专家,也见过在 SwiftUI 中执行 UITest 的不同方法。快照等可能有更好的方法,但为了好玩我很快重新创建了您的示例并添加了可访问性标识符:

struct InputField: View {
    var title: String
    @Binding var email: String

    var body: some View {
        VStack(alignment: .leading) {
            Text("Enter your email ")
            TextField(title, text: $email)
                .accessibility(identifier: "Email")

        }
        .padding()
    }
}

struct ContentView: View {
    @State private var email: String = ""

    var body: some View {
            InputField(title: "Email: ", email: $email)
    }
}

此外,有时可能需要在输入电子邮件或文本之前添加点击。因此它给我一个错误。
UItest 看起来像这样并且正在通过 :)

    func testAddEmail() throws {
        let app = XCUIApplication()
        app.launch()

        let emailText = app.textFields["Email"]
        XCTAssertTrue(emailText.waitForExistence(timeout: 1))
        emailText.tap() 
        emailText.typeText("testemail@realm.com")

        XCTAssertEqual(emailText.value as! String, "testemail@realm.com")
    }

我学到的一个很酷的技巧是像这样放置一个断点:

并在调试器中按提示输入以下内容:

(lldb) po XCUIApplication().textFields

这样您就得到了列表,您可以查看是否缺少标识符。按钮和静态文本等也是如此