2

Here is my use case...

My application has a number of menu items that have their state toggled between on and off based on a boolean that is also tied to a user default. That is, when the user clicks the menu item it not only toggles the state, it also saves that in the user defaults.

This is all working well but I'm trying to add tests to my XCUIApplication tests to check that the state is indeed saved from one application run to another. However I am unable to determine how to actually test the state of the menu item.

I find the menu item and confirm that it exists, has the correct title, and is enabled, as seen here:

let item = app.menuItems["viewHighlightChanges"]
XCTAssertTrue(item.exists)
XCTAssertEqual(item.title, "Highlight Changes")
XCTAssertTrue(item.isEnabled)

I can then toggle the item by clicking it:

item.click()

And I can confirm visually that this is all working.

But what I cannot figure out is how to determine if the menu item is check (state is on) or not checked (state is off). I had thought that it may be encoded in item.value but that is returning nil both before and after the click. I also thought it may be in item.isSelected but selected is not the same as state and in this case is always false both before and after the click.

My goal is to record the state after clicking, then exit and restart the app, and test the state again to see that it properly retained itself. I know that it is working because I can verify the state visually as the test runs, but the whole purpose of an automated test is that the computer should tell me if it worked.

Any ideas?

Steven W. Klassen
  • 1,401
  • 12
  • 26
  • Can you add a breakpoint and then run a `po item.debugDescription()`? Will tell us what kind of information you can get on it. – Mike Collins Aug 12 '20 at 16:04
  • Here is the short bit: `Printing description of item: Attributes: MenuItem, {{0.0, 73.0}, {194.0, 19.0}}, identifier: 'viewHighlightChanges', title: 'Highlight Changes' Element subtree: →MenuItem, 0x600003b4d6c0, {{0.0, 73.0}, {194.0, 19.0}}, identifier: 'viewHighlightChanges', title: 'Highlight Changes' ` Of course it also prints the whole query chain which gives the entire menu, but that is large and I doubt you would find it useful. (But let me know if you would like it anyway and I'll add it to the question.) – Steven W. Klassen Aug 12 '20 at 20:18
  • So the menu item clearly doesn't have an associated value. Is the menu item in a cell or some other type of parent? I check values of cells with the following: `application.tables.cells.containing(.staticText, identifier: "Mobile QA").element.isSelected` You'd of course need to modify this for your identifier and parent type. – Mike Collins Aug 12 '20 at 23:15
  • The items direct parent is the Menu item itself, whose parent is the MenuBarItem (title 'View' which is the menu it is in), then the MenuBar, then the application. I don't see anything in any of those that would tell me what I would like. In fact the MenuItem itself is the only thing I see in the tree that could possibly contain the info. It just looks like the state isn't included. – Steven W. Klassen Aug 13 '20 at 15:27
  • Are you in touch with your developers? Perhaps they could set an accessibility value when the state changes? – Mike Collins Aug 14 '20 at 14:56
  • That would be an option, but then the test really wouldn’t be testing the UI, it would be testing the extra scaffolding used to allow a test. If apple currently does not include access to the menu item state in the testing infrastructure, I will just have to leave it out. – Steven W. Klassen Aug 14 '20 at 15:42
  • A lot of UI testing is predicated on accessibility elements. If you've not yet, you _will_ run into having to rely on them. A unit test should be able to cover the reliability of the "scaffolding" so that you can trust it. – Mike Collins Aug 17 '20 at 17:26
  • True enough, and I am using an accessibility item in order to identify the menu item (the `identifier`), however what you are suggesting is (I think) something different. It would lead to the possibility of having the tests passing (because the “scaffolding” item is set) but the reality is failing (because the actual change is not being made). Unlikely, granted, but certainly possible. In any event in my case there is no authored “code” that is turning the menu item on/off, instead there is a binding to a value in the app delegate object. – Steven W. Klassen Aug 17 '20 at 21:06
  • I think I’m going to leave it out unless someone finds a way to actually read the value of a menu item toggle in the test code. – Steven W. Klassen Aug 17 '20 at 21:08
  • I suppose one possibility along the lines of your suggestion would be if there is a way I could automatically tie the bound value to an accessibility item. In that case the test would be more valid as it would not be dependent on developers remembering to set it. I’ll take a closer look at that. – Steven W. Klassen Aug 17 '20 at 21:09
  • Yeah, I’ve not done this, but I’m sure someone out there has. Sorry I could only get the gears turning. – Mike Collins Aug 18 '20 at 15:43
  • No worries. I think this is an area where Apple has just not yet filled in all the blanks. It is easy to get the toggle value from a toggle button, but not from a menu button. In any event, I'm going to drop this pursuit as not being important enough to justify the time I've spent on it. But I'll keep my eyes open and post an answer if and when one becomes clear to me. – Steven W. Klassen Aug 18 '20 at 17:08
  • Looking for the same thing but with no luck so far. – Gabriel Porumb Mar 04 '22 at 17:32

0 Answers0