Any one out there who uses XCUITest for their automated UI tests and tried to test whether a string has certain attributes given through an instance of NSAttributedString might have wondered how that is possible. I myself have done some web research and after a while I even found a solution to the problem. Unfortunately, that solution for some reason did not work for me. But I kept experimenting and was finally able to test NSAttributedStrings through XCUITest. How did I do that, you might ask. Well, here is the answer. Or at least an answer.

In my Shoptimizer app, there are two places where I use NSAttributedStrings:

  1. In the detail view of a shopping list: Done items are struck through with a green line. That green line is added to the strings through the NSAttributedString class.
  2. In the supplies view: Supplies items that are low or out have their name coloured in orange and red, respectively. That color is added to the strings through the NSAttributedString class.

Since I have just recently started being serious about automated UI tests, I quickly came across the problem as to how I can assert that a displayed string has some attribute. Well, the rather disappointing answer is: It is not possible. Or at least not directly possible.

To understand this, one should keep in mind that XCUITest makes heavy use of the accessibility features that are built into iOS. These features allow, for example, resizing fonts or letting the phone read out what is displayed on the screen. So, for example, for a string “ABC” that is attributed with a green stroke as an identifier that the item is done, the system would not read “ABC with green stroke.” It would rather read what is stored in the string’s accessibility label. That is a property defined in UIKit and is therefore part of all UI elements. In the example that label could be defined as “ABC is done” and the system would read just that. The point is: Just like the user, the accessibility elements do not have direct access to the attributes of strings. Instead a solution that works around this restriction must be found.

In the aforementioned solution I found, it was suggested to set an accessibility label on the string itself and then test for that string in the UI test. But, as stated, that did not work for me. Fortunately, there is another property: The accessibility identifier. And that one is exactly what I use in my UI tests. I also do not set it directly on the string. Since the elements of the shopping lists and the supplies items are UITableViewCells, I can set and test the identifier there. I did not try it, but I expect that this approach can be transferred to other types of UI elements.

And how is that done? There are only a few steps to be followed:

  1. In the actual app code (not the test code) when configuring the UITableViewCell, assuming that cell is the name of the variable that holds the UITableViewCell to be configured, simply set the property like so: cell.accessibilityIdentifier = "some string".
  2. In the test code, check if the identifier is set: First you get the cell you want to test with something like let cell = XCUIApplication().cells.containing(NSPredicate(format: "label CONTAINS %@", label)), where label is some string that is displayed in the cell. Then you assert that the cell’s identifier is correct with XCTAssert(cell.identifier == "some string").

Basically, that is already it. Of course, there are a few enhancements to be made. For example you should store the constant “some string” in a centralized place since it is used in two different files. Also you should extract the identifier check into a separate function, in case there are changes on the check in the future of your project. And, finally, “some string” is not the best possible identifier. 😉

I hope I could help you out with this challenge or at least point you in the right direction. If you have any suggestions, corrections, enhancements (or congratulations 😉 ), I am looking forwarding to reading about it in the comments.

Advertisements