Тестирование пользовательского интерфейса Xcode позволяет получать серию системных предупреждений

У меня проблема, если я попытаюсь разрешить серийное системное оповещение, сработает только один раз, а следующее оповещение не «разрешит», я погуглю больше времени и узнаю об этом сообщении: (Тестирование пользовательского интерфейса Xcode 7: как отклонить серию системных предупреждений в коде) Ничего.. не работает. Вот мой текущий код, первое предупреждение успешно «разрешено», следующее предупреждение не обнаружено.

XCUIApplication *app = [[XCUIApplication alloc] init];
app.launchEnvironment = @{
        @"isUITest" : @YES,
        @"withFakeData" : fakeData
};
[app launch];


for (int i = 1; i <= self.possibleSystemAlerts; i++) {
    NSLog(@"%d", i);
    XCTestExpectation *expectation = [self expectationWithDescription:@"High Expectations"];
    id monitor = [self addUIInterruptionMonitorWithDescription:@"Push notifications" handler:^BOOL(XCUIElement *_Nonnull interruptingElement) {
        XCUIElement *element = interruptingElement;
        XCUIElement *allow = element.buttons[@"Allow"];
        XCUIElement *ok = element.buttons[@"OK"];

        if ([ok exists]) {
            [ok tap];
            [expectation fulfill];
            return YES;
        }

        if ([allow exists]) {
            [allow forceTap];
            [expectation fulfill];
            return YES;
        }
        return NO;
    }];
    [app tap];
    [self waitForExpectationsWithTimeout:6.0 handler:^(NSError *error) {
        if (error) {
            NSLog(@"Timeout Error: %@", error);
        }
    }];
    [self removeUIInterruptionMonitor:monitor];
}

С уважением, Иван.

УПД:

Хорошо, я нашел решение, как после первого оповещения попробовать закрыть второе (спасибо за этот сайт: http://www.it1me.com/it-answers?id=32148965&s=Template:Viper&ttl=Xcode+7).+UI+Тестирование%3A+как+закрыть+серию+системных+предупреждений+в+коде) Просто всегда нужно возвращать НЕТ.

Но другая проблема...

    t =    10.18s                     Find: Descendants matching type Alert
    t =    10.18s                     Find: Identity Binding
    t =    11.19s                     Find the "Allow “MyApp” to access your location while you use the app?" Alert (retry 1)
    t =    11.19s                         Snapshot accessibility hierarchy for com.apple.springboard
    t =    11.26s                         Find: Descendants matching type Alert
    t =    11.26s                         Find: Identity Binding
    t =    12.27s                     Find the "Allow “MyApp” to access your location while you use the app?" Alert (retry 2)
    t =    12.27s                         Snapshot accessibility hierarchy for com.apple.springboard
    t =    12.33s                         Find: Descendants matching type Alert
    t =    12.34s                         Find: Identity Binding
    t =    12.42s                     Assertion Failure: UI Testing Failure - No matches found for "Allow “MyApp” to access your location while you use the app?" Alert
Query input was {(
    Alert 0x7febe8731630: traits: 72057602627862528, {{25.0, 193.0}, {270.0, 182.0}}, label: '“MyApp” Would Like to Send You Notifications'
)}

Он попытался закрыть третье уведомление, а не второе, конечно, он не нашел это системное предупреждение...


person MeGaPk    schedule 20.04.2016    source источник
comment
Разве сайт, на который вы ссылаетесь в обновлении, не является просто отрывком из того же вопроса и ответа, на который вы ссылались в исходном сообщении?   -  person Joe Masilotti    schedule 21.04.2016


Ответы (2)


Создавайте обработчики предупреждений один за другим перед запуском приложения. Кроме того, не забудьте tap() в любом месте приложения, прежде чем взаимодействовать с предупреждением. Это известная ошибка в Xcode.

addUIInterruptionMonitor(withDescription:"First Dialog") { (alert) -> Bool in
    alert.buttons["Allow"].tap()
    return true
}

addUIInterruptionMonitor(withDescription:"Second Dialog") { (alert) -> Bool in
    alert.buttons["Allow"].tap()
    return true
}

addUIInterruptionMonitor(withDescription:"Third Dialog") { (alert) -> Bool in
    alert.buttons["Allow"].tap()
    return true
}

let app = XCUIApplication()
app.launch()

app.tap()
app.tap()
app.tap()

Эти три касания последовательно запускают каждый обработчик предупреждений, фактически не вызывая никаких событий в вашем приложении. Также обратите внимание, что каждый обработчик прерывания не указывает ничего о предупреждении, а только кнопку подтверждения.

person Joe Masilotti    schedule 21.04.2016
comment
вопрос был помечен как цель c. это решение на Swift - person Sazzad Hissain Khan; 02.03.2017
comment
Это не работает для нас, пытающихся отклонить предупреждение SFAuthenticationSession в Xcode 9/iOS 11. - person Robert Atkins; 15.11.2017
comment
Но это решение работает для нас: stackoverflow.com/a/46951214/17294 - person Robert Atkins; 15.11.2017
comment
... некоторое время. - person Robert Atkins; 15.11.2017
comment
что я должен указать в качестве описания для addUIInterruptionMonitor ?? описание, которое я установил в info.plist? - person Maryam Fekri; 16.02.2018
comment
В моем случае addUIInterruptionMonitor хорошо работает для iOS 11, для iOS 10 работает решение, рекомендованное @RobertAtkins. Большое спасибо. - person Rostyslav Druzhchenko; 28.02.2018
comment
Благодарю вас! Решил мою проблему! - person Pedro Paulo Amorim; 31.07.2018

Использование цикла For, перебирающего количество возможных системных предупреждений, кажется наиболее вероятным случаем сбоя в вашем коде. Превращение его в цикл while, который оценивает наличие системного предупреждения как условное, было бы намного чище визуально, включало бы меньше общей логики и не имело бы условия сбоя, когда self.possibleSystemAlerts не является правильным значением.

Вся логика вашего монитора также может быть вырвана. Тест будет ждать, пока приложение не будет простаивать, и к этому времени вы получите предупреждение или не получите предупреждение. Оцените его наличие или отсутствие, взаимодействуйте с ним или завершите цикл.

person Aaron Sofaer    schedule 20.04.2016
comment
Перед началом нового теста я удаляю приложение из своего симулятора. И я использую waitForExpectationsWithTimeout, чтобы не запускать основные тесты. - person MeGaPk; 21.04.2016
comment
Обновленный вопрос, пожалуйста, проверьте. - person MeGaPk; 21.04.2016