EarlGrey - 如何检查屏幕上是否显示多个对象

EarlGrey - How do I check if multiple objects are being shown on the screen

EarlGrey 文档 says

You must narrow down the selection until it can uniquely identify a single UI element

我的 UI 上有三个 UI 视图,我需要检查使用 grey_sufficientlyVisible() 断言的可见性。但是,除非我真的使用它们各自的可访问性标签来挑选每一个,否则我无法匹配所有这些。有没有办法匹配一组超视图,或者我应该为每个视图创建单独的测试条件?

通过说匹配器必须能够唯一地标识一个元素,EarlGrey 让做错事变得更难。想象一下,当多个元素匹配时无意中选择了错误的元素并断言它是否可见,后来发现检查了错误的元素的可见性......哎呀!

无论如何,您可以通过多种方式完成您想要完成的任务:

1) 如果所有这些视图共享一个共同的父视图,那么您可以编写一个匹配父视图的自定义匹配器,并编写一个迭代子视图的自定义断言,存储具有所需可访问性标签的视图,然后通过可见性匹配器运行每个单独的视图。类似于:

for (UIView *view in matchedViews) {
  GREYAssertTrue([grey_sufficientlyVisible() matches:view],
                 @"View %@ is not visible", view);
}

2) 或者,如果您不介意创建一个更复杂的匹配多个视图的技术,您可以从中创建一个可重用的函数,您可以做一些类似于我为检查过的测试所做的事情如果 table 视图有五行带有辅助功能标签 "Row 1":

- (void)testThereAreThreeViewsWithRow1AsAccessibilityLabel {
  NSMutableArray *evaluatedElements = [[NSMutableArray alloc] init];
  __block bool considerForEvaluation = NO;
  MatchesBlock matchesBlock = ^BOOL(UIView *view) {
    if (considerForEvaluation) {
      if (![evaluatedElements containsObject:view]) {
        [evaluatedElements addObject:view];
        considerForEvaluation = NO;
        return YES;
      }
    }
    return NO;
  };
  DescribeToBlock describeToBlock = ^void(id<GREYDescription> description) {
    [description appendText:@"not in matched list"];
  };
  id<GREYMatcher> notAlreadyEvaluatedListMatcher =
      [GREYElementMatcherBlock matcherWithMatchesBlock:matchesBlock
                                      descriptionBlock:describeToBlock];
  id<GREYMatcher> viewMatcher =
      grey_allOf(grey_accessibilityLabel(@"Row 1"), notAlreadyEvaluatedListMatcher, nil);
  for (int i = 0; i < 5; i++) {
    considerForEvaluation = YES;
    [[EarlGrey selectElementWithMatcher:viewMatcher] assertWithMatcher:grey_sufficientlyVisible()];
  }
}

如@khandpur 所述,让匹配器唯一标识元素确实有意义。但我认为,如果您真的不在乎找到了多少元素,那么有一种 hacky 方法可以做到这一点。

id<GREYMatcher> matcher = grey_allOf(grey_accessibilityID(your_identifier), // or to match certain class
                                     grey_sufficientlyVisible(),
                                     nil);
NSError *error;
[[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_isNil(!visible) error:&error];
if (!error) {

  // Only one element exists
} else if ([error.domain isEqual:kGREYInteractionErrorDomain] &&
    error.code == kGREYInteractionElementNotFoundErrorCode) {

  // Element doesn’t exist
} else if ([error.domain isEqual:kGREYInteractionErrorDomain] &&
           error.code == kGREYInteractionMultipleElementsMatchedErrorCode) {

  // Multiple elements exist
  // your logic ...
}