skip to Main Content

I have a UITableview with custom view that appears in the viewForHeaderInSection delegate method. It appears and functions fine when running the app.

While doing UITests, I’ve noticed that this custom view identifier doesn’t appear in the view hierarchy (unless they’re on screen OR nearly on screen). As a result, I cannot UITest headers that are further down in the tableview.

I’ve found this article from a few years ago https://tiyachows.medium.com/xcuitest-and-its-nuances-3db6fac6f5dc and it says

If the header element is offscreen and then later scrolled into view. The app hierarchy is not refreshed with the id of that header and the UI tests will not be able to access that element.

which doesn’t give me confidence that I’m able to UITest my headers.

Is this a known issue? Are there any known work arounds besides manually scrolling to a header?

3

Answers


  1. This is not an issue per se to have to work around it. Afaik this is a good practice when developing mobile applications not to load all the elements that can be presented on an app page to save memory. Since you are doing UI tests you should try to simulate what a real user would do with your interactions – in this case if the element is offscreen it is recommended that you scroll to it. Imagine that the page cannot be scrolled for some reason – a test will never catch that if you are able to interact with and validate elements offscreen directly.

    Login or Signup to reply.
  2. You’ll need to manually scroll to them. When using a standard table, XCUITest is smart enough to scroll to items not yet visible, but once you get custom you’ll need to get custom with your actions.

    I’d suggest a scrollTo(label: String, maxScrolls: Int) function. If you see the thing, you’re done! If you don’t, scroll again unless you’ve hit your max threshold (you don’t want to scroll forever if something doesn’t exist in the table at all).

    If you’re tapping once you reach your item you should know this can be flaky; depending on scroll speed and screen size, you may run into a case where something is barely on screen, resulting in it being visible to XCUITest, but not able to be tapped on yet (barely appearing on screen). To account for this case I check if something is tappable before attempting . If it isn’t (and has already passed the visible check) I’ll perform a tiny, tiny, tiny scroll. If you’re not tapping, ignore this paragraph.

    Login or Signup to reply.
  3. Yes. I encountered this too when I started working on XCTest.

    The solution is to do the following:

    1. Make a custom swipe function (extension) -> this is needed because Apple often changes the size of their swipe function and it would mess up the custom scroll function otherwise. It could have an option to scroll in any of the following directions: .up, .down, .right, .left -> though .down should be default.
    2. Make a scrollsIntoView function (extension). for _ in 0...maxSwipes and then check if item exists && isHittable. If not keep scrolling and swipeCount += 1. If so, return true. If we don’t find the element in the maxSwipes, then return false. Returning a bool allows you to check if you see something in only a few swipes and pivot to a different action if it’s not there without failing the test. But you could also assert against the bool value directly in the test case.
    3. If you want to get more advanced, you can account for the scrollDomain, which is basically the area of the app that we’re scrolling on. This is helpful for horizontal scrolling in a carousel or something.

    Also worth pointing out that the swipe direction is the opposite of the scroll direction.

    Good luck!

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