【问题标题】:iOS UI Automation: Monitor log for signalsiOS UI 自动化:监控信号日志
【发布时间】:2015-10-29 17:07:55
【问题描述】:

我正在设置一个 Xcode/Instruments UI 自动化项目,目的是自动捕获我的应用在各种状态下的屏幕截图。

这种方法的主要问题之一是时机。由于应用程序与服务器通信,因此某些事件发生所需的时间会因运行而异(有时会很大)。使用延迟远非理想,因为它会延长执行屏幕截图捕获的时间(我们必须运行大约 280 次,所以它会加起来)并且仍然不能保证应用程序处于正确的状态(对于例如,我们不能保证服务器会在 5 秒内返回,但大多数时候应该是

所以我的想法是,一个理想的解决方案是将良性日志语句插入到实际应用程序本身中,可以由 UI 自动化脚本监控。例如,只要脚本检测到“!!SCREENSHOT!!”在日志中,它可以捕捉另一个屏幕截图。通过这种方式,我们可以使用编程构造来确保应用程序处于正确的屏幕截图状态,并通过避免延迟来缩短脚本的整体执行时间。

我的问题首先是这可能吗?如果是这样,怎么办?如果没有,是否有其他人提出其他想法来解决这个问题?

【问题讨论】:

    标签: ios xcode7 ios-ui-automation xcode-instruments


    【解决方案1】:

    嗯,我找不到任何关于从自动化脚本监控日志的信息,所以我用另一种方式解决了这个问题,目前看来效果很好。

    基本思想是使用 UI 元素代替使用日志作为信号。我在我的应用程序委托中创建了一个简单的方法,它在屏幕外创建一个空标签并为其分配一个已知的accessibilityIdentifierdispatch_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: 方法,当它准备好让脚本捕获屏幕时,它会留给应用程序本身发出信号。效果很好,没有人为的延迟!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多