简体   繁体   English

我的XCode UI测试如何检测屏幕是否已更改?

[英]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. 我正在尝试使用XCode 7的XCTest UI测试功能创建一个树木漫步者,该功能系统地探索表视图的确定性树到指定的深度。 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. 我有一个hacky方法,大部分时间都可以工作,即检测导航栏标签已更改或菜单元素的数量已更改。

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. 因此,我在应用程序代码(在viewDidAppear中)为导航栏的可访问性标签设置了一个UID,然后在UI测试代码中对其进行测试。 It feels like this ought to work, but I only ever get back a value of nil in the test code. 感觉这应该工作,但我只在测试代码中获得nil值。

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. 我会自由地承认,在UI测试方面我是一个菜鸟,主要是切割/粘贴/调整其他人的代码,而不清楚我正在做什么。 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: 在XCTest UI测试中:

- (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. 请注意,firstElem IS被发现,并且我能够非常愉快地从中提取例如firstElem.label

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. 在UI测试中左键单击并开始录制,模拟器将启动,您可以单击模拟器内的元素,如果元素可访问,Xcode将在testExample方法中为您编写测试代码。

在此输入图像描述

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"; 除此之外,我认为在您的情况下,您可以通过为每个屏幕添加导航项标题来验证这一点,即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. 在项目的测试目标中,在构建设置下有一个部分Proprocessor。 There you can set Preprocessor macros. 在那里,您可以设置预处理器宏。 Just add 'UITESTING=1' to the Debug and/or Release setting. 只需在调试和/或发布设置中添加'UITESTING = 1'即可。 The effect is that in your test build UITESTING will be defined, so all code under #ifdef UITESTING will be included by the preprocessor. 结果是在测试构建中将定义UITESTING,因此预处理器将包含#ifdef UITESTING下的所有代码。

I would use snapshot testing using Facebook's Snapshot test library . 我会使用Facebook的Snapshot测试库进行快照测试

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. 你可以在这里找到一篇更详细的文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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