iOS UI 自动化:监控信号日志

Posted

技术标签:

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

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

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

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

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

【问题讨论】:

【参考方案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: 方法,当它准备好让脚本捕获屏幕时,它会留给应用程序本身发出信号。效果很好,没有人为的延迟!

【讨论】:

以上是关于iOS UI 自动化:监控信号日志的主要内容,如果未能解决你的问题,请参考以下文章

在 ios 设备上运行 UI 自动化时出现时间标志错误

IDEA+java通过SSH来进行分析日志,实现UI自动化动态验证码登录

Qt5 UI信号槽自动连接的控件重名

Qt5 UI信号槽自动连接的控件重名大坑(UI生成的槽函数存在一个隐患,即控件重名。对很复杂的控件,不要在 designer 里做提升,而是等到程序启动后,再动态创建,可以避免很多问题)

Xcode 自动化 UI 测试日志内存使用情况

运行 Instrument 的 UI 自动化时捕获 iPhone 控制台日志