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

无人久伴 提交于 2020-02-03 10:42:47

问题


The EarlGrey documentation says that

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

I have three UIViews on my UI that I need to check the visibility of using the grey_sufficientlyVisible() assertion. However, unless if I literally pick each one up using their individual accessibility labels or so, I cannot match all of them. Is there a way to match a super-set of views or should I create individual test conditions for each of the views?


回答1:


By saying that matchers must be able to uniquely identify an element, EarlGrey is making it harder to do the wrong thing. Imagine unintentionally selecting the wrong element when multiple elements are matched and asserting if it's visible and later finding out the wrong element was checked for visibility...yikes!

Anyhow, what you're trying to accomplish can be done in a couple of ways:

1) If all of these views share a common parent then you could write a custom matcher that matches on the parent and write a custom assertion that iterates over the subviews, storing the view that have the desired accessibility labels and then runs each of those individual views through visibility matcher. Something like:

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

2) Or if you don't mind creating a little more sophisticated technique of matching multiple views that you can probably create a reusable function out of, you can do something similar to what I had done for a test which checked if a table view has five rows with accessibility label "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()];
  }
}



回答2:


It does make sense to have the matcher identifying an element uniquely, as @khandpur mentioned. But I think there's a kind of hacky way to do this if you really don't care how many elements were found.

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 ...
}


来源:https://stackoverflow.com/questions/35448041/earlgrey-how-do-i-check-if-multiple-objects-are-being-shown-on-the-screen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!