iOS 测试 KIF 在真机上进行截图踩坑小记

陈恒捷 · 2016年05月03日 · 最后由 陈恒捷 回复于 2017年04月27日 · 3052 次阅读

环境: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?

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 17 条回复 时间 点赞

踩坑王!

项目路径下的*.xcscheme文件里可以找到 Environment Variables
勾选了 shared 的话在 <.xcodeproj or .xcworkspace>/xcshareddata/xcschemes/
没勾的话在<.xcodeproj or .xcworkspace>/xcuserdata/$USER.xcuserdatad/xcschemes/

你好,iOS 新人问一个可能有些愚蠢的问题,KIF 可以用于真机测试么?

#6 楼 @chenhengjie123 我想在真机上调用 KIF 里面的 UIAutomationHelper 这个类 ,然后调用他的 acknowledgeSystemAlert 这个方法, 来处理系统的弹窗, 但是只要一执行这个方法 ,控制台 就无线打印 UIAutomation is not enabled on this device. UIAutomation must be enabled in Settings. 这个提示, 请问这个问题有解不?

#7 楼 @AllocAndInit 你试下在开发者选项里面打开 UIAutomation ?我没用过这个类,但从名字上看调用的是 UIAutomation 。iOS 8 以上 UIAutomation 默认是关闭的,需要手动到开发者选项打开。

#8 楼 @chenhengjie123 在真机上,这个 Enable UI Automation 我确定打开了, 然后再 控制台还是不停的打印 UIAutomation is not enabled on this device. UIAutomation must be enabled in Settings ,有点搞不明白,请问还有其他的什么方法不?

#8 楼 @chenhengjie123 把 demo 跑在模拟器上的话, 不会有这样的问题,一跑到真机上就出现了上面的问题

#10 楼 @AllocAndInit 那就不大清楚了。没用过这个类。

#11 楼 @chenhengjie123 如果在 iOS 自动化测试过程中需要处理系统的弹窗,有什么好的方法没有了?多谢

#12 楼 @AllocAndInit 我这边是通过直接修改源码,让它不申请通知权限解决的。我们也就只有这个属于系统弹窗,其它都是应用内弹窗。

如果系统弹窗多的话,UIAutomation 或者 XCUITest 可能是比较好的解决方法。你可以在 KIF 的 isssue 里问下官方这个 UIAutomationHelper 具体要怎么使用。

KIF 真机测试需要怎么配置?

wenliang 回复

不需要什么额外配置,和你做普通真机调试差不多。

楼主,KIF 测试的时候,有没有遇到过 SVProgressHUB 提示显示不出来的情况?

wenliang 回复

木有。。。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册