iOS UI Automation: мониторинг журнала для сигналов
Я работаю над настройкой проекта автоматизации пользовательского интерфейса XCode/Instruments с целью автоматической съемки снимков экрана моего приложения в различных состояниях.
Одна из главных проблем с этим подходом - выбор времени. Поскольку приложение связывается с сервером, время, которое требуется для того, чтобы произошли определенные события, варьируется (иногда довольно много) от запуска к запуску. Использование задержек далеко от идеала, так как оно увеличивает время выполнения захвата скриншота (и мы должны выполнить это около 280 раз, чтобы оно сложилось) и все еще не гарантирует, что приложение находится в правильном состоянии (для Например, мы не можем гарантировать, что сервер вернется через 5 секунд, но в большинстве случаев это должно быть < 1 сек).
Таким образом, я думаю, что идеальным решением было бы вставить в журнал собственно приложение доброкачественных операторов, которые могли бы отслеживаться сценарием автоматизации пользовательского интерфейса. Например, в любое время сценарий обнаруживает "!!SCREENSHOT!!" в журнале это может сделать еще один снимок экрана. Таким образом, мы можем использовать программные конструкции, чтобы убедиться, что приложение находится в правильном состоянии для скриншота, и сократить общее время выполнения скрипта, избегая задержек.
Мой вопрос в первую очередь это возможно? И если да, то как? Если нет, то есть ли другие идеи, которые придут для решения этой проблемы?
1 ответ
Ну, я не мог найти ничего о мониторинге журнала из сценария автоматизации, поэтому я решил это другим способом, который до сих пор, кажется, работает довольно хорошо.
Основная идея заключалась в том, чтобы вместо использования журнала в качестве сигнала использовать вместо этого элемент пользовательского интерфейса. Я создал простой метод в своем делегате приложения, который создает пустую метку за пределами экрана и назначает ей известный accessibilityIdentifier
(dispatch_after
не является строго необходимым, но я хотел убедиться, что управление вернулось в основной цикл событий перед записью).
- (void)signalScreenshot:(int)number {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ( ![[[NSProcessInfo processInfo] arguments] containsObject:@"automatedexecution"] ) {
NSLog(@"Screenshot signaled, but ignoring because we are not in automated execution.");
return;
}
UILabel* elem = [[UILabel alloc] initWithFrame:CGRectMake(-100, -100, 50, 50)];
elem.accessibilityIdentifier = [NSString stringWithFormat:@"screenshotSignal_%d", number];
NSLog(@"Signaling for screenshot %d...", number);
[self.window insertSubview:elem atIndex:0];
});
}
Существование этого невидимого элемента в иерархии представлений служит сигналом для сценария автоматизации для создания снимка экрана. Внутри скрипта автоматизации я написал captureScreen
функция, которая использует счетчик с самостоятельным приращением для определения номера экрана. Для каждого добавочного номера экрана существует уникальный элемент сигнала.
var screenshotCounter = 0;
function captureScreen() {
screenshotCounter++;
var screenshotSignal = target.frontMostApp().mainWindow().elements().firstWithName("screenshotSignal_" + screenshotCounter);
screenshotSignal.withValueForKey(1, "isVisible");
if ( screenshotSignal.isValid() ) {
UIALogger.logDebug( "Screenshot " + screenshotCounter + " signaled." );
target.captureScreenWithName( "" + screenshotCounter );
return true;
} else {
target.logElementTree();
throw "Did not detect screenshot signal " + screenshotCounter;
}
}
Теперь внутри моего скрипта я могу автоматизировать приложение, чтобы оно оказалось в нужном месте и вызвать captureScreen()
, Затем это приложение оставляется на усмотрение самого приложения, чтобы сообщить о готовности сценария захватить экран, вызвав signalScreenshot:
метод выше. Прекрасно работает, и никаких искусственных задержек!