skip to Main Content

I have a button with a foreground image in a ZStack:

Button(action: {
    self.highlighted = !self.highlighted
}) {
    ZStack {
        Text("Text")
        if self.highlighted {
            Image("highlighted").resizable()
        }
    }
}

The foreground image ("highlighted") is only visible if the variable is true. A button click flips the highlighted variable. So if the button is clicked it is highlighted and if it is clicked again it is not highlighted anymore. I now want to have a UiTest in which the button is clicked and the test checks if the Image "highlighted" exists. This is what I have as UiTest, but it fails at the last assertion:

func test_highlight() {
    let app = XCUIApplication()
    let button = app.buttons["my_button"]
    XCTAssertTrue(button.exists)
    button.tap()
    XCTAssertTrue(button.images["highlighted"].exists) // <-- Fails here
}

Is this possible in UiTests. If yes, how? If not, what is the alternative?

2

Answers


  1. Accessibility engine does not see internals of button, but if you change like

    Button(action: {
        self.highlighted = !self.highlighted
    }) {
        if self.highlighted {
            Image("highlighted").resizable()
        } else {
           Text("Text")
        }
    }
    

    then you can verify toggle by UT (tested with Xcode 12.1 / iOS 14.1)

    func test_highlight() {
        let app = XCUIApplication()
        app.launch()
        let button = app.buttons["Text"]     // << fits button label
        XCTAssertTrue(button.exists)
        button.tap()
    
        let highlighted_button = app.buttons["highlighted"] // fits button image name
        XCTAssertTrue(highlighted_button.exists)
    }
    

    Update: possible variant for transparent image

    struct DemoView: View {
        @State private var highlighted = false
        var body: some View {
            Button(action: {
                 self.highlighted = !self.highlighted
            }) {
                 ZStack {
                      Text("Text")
                      if self.highlighted {
                            Image("flag-1").resizable()
                      }
                 }
            }
            .accessibility(identifier: highlighted ? "highlighted" : "button" )
        }
    }
    
    func test_highlight() {
         let app = XCUIApplication()
         app.launch()
         let button = app.buttons["button"]
         XCTAssertTrue(button.exists)
         button.tap()
    
         let highlighted = app.buttons["highlighted"]
         XCTAssertTrue(highlighted.exists)
    }
    
    Login or Signup to reply.
  2. Okay that works. But to be honest I don’t really like to write code in the project files just to make tests work. This is a pity, if this is the only way to test it

    I agree and I wouldn’t utilise the identifier. However, to be fair, what you’re asking for isn’t something I think you commonly test at UI test level 🧐 ?

    Perhaps test resources and business logic (I.e your bool) via unit and UI-looks-good via snapshot testing?

    Personally I would here verify UI by accessibility/values/labels etc of elements along user integration flow.

    Example

    If you configure the button to be properly accessible, you can verify the ‘selected’ state of the button.

    let localisedstring = “localised-text”
    
    Button(action: {
        self.highlighted = !self.highlighted
    }) {
        ZStack {
            Text(localisedstring)
            if self.highlighted {
                Image("highlighted").resizable()
            }
        }
    }
    .accessibilityTraits(isHighlighted ? [.button, .selected] : [.button])
    .accessibilityLabel(localisedString)
    

    Then in a test you can do:

    // Given base button 
    let button = app.buttons[“button-id”]
    XCTAssertFalse(button.isSelected) 
    
    // When user taps 
    button.tap()
    
    // Then button should be selected
    XCTAssertTrue(button.isSelected) 
    
    // And whatever-else that button should do 
    

    In a similar way to the utilising the identifier, you’ve made it testable, and also better supported accessibility users like voice over!

    Edit: written on my iPad so please take as pseudo 🙇‍♂️

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search