环境:iOS 9.3(真机),Mac OS X 10.11,KIF 3.4.2

前言

KIF 3.4.2 本身自带了出错自动截图功能,关键代码如下:

- (void)failWithException:(NSException *)exception stopTest:(BOOL)stop
{
    self.continueAfterFailure = YES;

    [self recordFailureWithDescription:exception.description inFile:exception.userInfo[@"FilenameKey"] atLine:[exception.userInfo[@"LineNumberKey"] unsignedIntegerValue] expected:NO];

    if (stop) {
        [self writeScreenshotForException:exception];
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Swizzle([XCTestCase class], @selector(_recordUnexpectedFailureWithDescription:exception:), @selector(KIF_recordUnexpectedFailureWithDescription:exception:));
        });
        [exception raise];
    }
}

最终是调用了 UIApplication-KIFAdditions.m 里面的 - (BOOL)writeScreenshotForLine:(NSUInteger)lineNumber inFile:(NSString *)filename description:(NSString *)description error:(NSError **)error 方法进行截图和存储。

按照官方的说明,只需要配置一个环境变量 KIF_SCREENSHOTS 就能设定截图保存地址了进行出错自动截图了。然而真实情况没那么简单。

坑 1:环境变量

首先,这个环境变量不是 Mac 的环境变量,而是 Scheme 里面的环境变量。如下图:

KIF 中获取环境变量的关键代码:

NSString *outputPath = [[[NSProcessInfo processInfo] environment] objectForKey:@"KIF_SCREENSHOTS"];

原因嘛,很简单,KIF 是作为应用的一部分在手机上运行的,所以获取不到 mac 上的环境变量。

坑 2:截图存储目录

我想把截图存到项目代码文件夹里面,那么我打算把这个值放到 KIF_SCREENSHOTS 这个环境变量里:$(SRCROOT)/kif_screenshots

然后,就没有然后了。。。用例出错后,还是只有 log ,没有截图。。。

为啥呢???

和前面第一个坑差不多,因为运行位置是你的手机,所以能存储的目录其实就只有 sandbox 里面的目录,即 Documents 或者 Library 。

那么,得怎么改?难道要修改 KIF 的源码!?

改源码也不行,因为 sandbox 目录每次安装都不一样。。。

最后通过 Google 找到了变通方法:用 ~~ 经过 outputPath = [outputPath stringByExpandingTildeInPath]; 处理后会自动变成应用在真机上的 sandbox 目录,如 ~/Documents/kif_screenshots 会转换成
/var/mobile/Containers/Data/Application/EBE399B9-5E75-41EC-BCD2-E7F722364DBF/Documents/kif_screenshots

坑 3:保存截图到 Mac 上

填完第二个坑后,终于有截图了。等等,截图放在真机上,我加入不了报告里啊!!!

同样通过 Google ,找到了解决方法:ios-deploy它能在非越狱机器上获取指定 app 的所有可读写目录内容。用法如下:

// Download the Documents directory of the app *only*
ios-deploy --download=/Documents --bundle_id my.app.id --to ./my_download_location

但有个不好的地方,每次都是传回来都是带目录结构的。转换也很简单,写了个简单的 shell 脚本:

# Set in app scheme's environment variable. It's folder on ios device
KIF_SCREENSHOTS=/Documents/KIF_SCREENSHOTS

# Path on Mac
OUTPUT_FOLDER=kif_screenshots

# bundle_id
BUNDLE_ID=com.xxx.photo

mkdir tmpKifScreenshot
ios-deploy --bundle_id $BUNDLE_ID --download=$KIF_SCREENSHOTS --to "tmpKifScreenshot"
cp tmpKifScreenshot$KIF_SCREENSHOTS/*.png $OUTPUT_FOLDER
rm -rf tmpKifScreenshot

最大的缺点就是获取不到 scheme 里面的 KIF_SCREENSHOTS 的值,所以变成 hard code 了。大家如果知道什么好方法欢迎分享出来~

ok,坑填完,截图到手了。接下来怎么用是后续的事情了~

参考资料

How to take screenshots when any step fails in KIF?


↙↙↙阅读原文可查看相关链接,并与作者交流