简体   繁体   中英

How can my XCode UI test detect that the screen has changed?

I'm trying to create a tree walker using XCode 7's XCTest UI testing functionality that systematically explores a deterministic tree of table views to a specified depth. It almost works, except that I cannot reliably detect whether or not the tap on any given element has actually triggered a transition to a new screen. I have a hacky method that works most of the time, which is to detect that either the nav bar label has changed OR that the number of menu elements has changed.

The first test has false negatives, because successive screens can have identical nav bar labels (the codebase I'm walking is not mine). The second test has false positives, because sometimes clicking on a table element does not transition to another table/screen but instead adds extra elements to the current screen.

After doing some reading, it seemed that using accessibility labels might be the way to go. So I set a UID for the nav bar's accessibility label in the application code (in viewDidAppear) and then test for it in the UI test code. It feels like this ought to work, but I only ever get back a value of nil in the test code.

I will freely confess that I am a noob when it comes to UI testing and am mainly cutting/pasting/adapting other people's code without having a clear understanding of what I'm doing. So I'm probably making some kind of naive blunder, in the accessibility label code itself and possibly at the conceptual level for detecting that the screen has changed; maybe there's something much simpler/more idiomatic I could be doing.

In the application:

- (void)viewDidAppear: (BOOL)animated {

    [super viewDidAppear: animated];

    //...

    UINavigationBar* navBar = self.navigationController.navigationBar;
    if( navBar )
    {
        static NSInteger s_UID = 0;
        navBar.topItem.accessibilityLabel = [NSString stringWithFormat:@"UID-%ld", s_UID++];
    }
}

In the XCTest UI test:

- (NSString*) navBarAccessibilityLabel: (XCUIApplication*) app
{
    NSString* result = NULL;

    XCUIElementQuery *navBars = app.navigationBars;
    XCUIElement* firstElem = [navBars.staticTexts elementBoundByIndex:0];
    if( firstElem )
    {
        result = (NSString*)firstElem.accessibilityLabel; // This is always nil
    }

    return result;
}

Note that firstElem IS found, and that I am able to extract eg firstElem.label from it very happily.

Any help appreciated.

You can test if elements are accessible:

Left click inside a UI test and start recording, the simulator will start and you can click on the element inside the simulator, if the element is accessible Xcode will write test code for you inside the testExample method.

在此输入图像描述

Or run your app in the Simulator and open the Accessibility Inspector, and hover over the element as details will appear in the Inspector.

在此输入图像描述

Apart from that, I think in your case you could verify this by adding a navigation item title for each screen ie self.navigationItem.title = @"myScreen";

And then verify the screen with an assertion ie

// let app = XCUIApplication() // Swift

UIApplication *app = [UIApplication alloc] init]; // Objective-C

XCTAssertEqual(app.navigationBars.element.identifier, "myScreen") // Don't forget to import class XCTest

Assuming you have given your view controllers proper identifiers (so you can distinguish among them), you can add this to the view controllers involved:

#ifdef UITESTING
- (void) viewDidAppear: animated
{
  [super viewDidAppear: animated];
  // do your checking here
}
#endif

In your project's Test target, under the build settings there is a section Proprocessor. There you can set Preprocessor macros. Just add 'UITESTING=1' to the Debug and/or Release setting. The effect is that in your test build UITESTING will be defined, so all code under #ifdef UITESTING will be included by the preprocessor.

I would use snapshot testing using Facebook's Snapshot test library .

View-based testing means verifying that what the user sees is what you want the user to see. Doing this means being able to ensure that different versions of your views, or different states of your views, continue to look the same. View-based testing can be used to provide a high-level test covering a lot of use cases surrounding an object.

You can find a great article with more detail here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM