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

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

环境: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 条回复 时间 点赞
wenliang 回复

木有。。。

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

wenliang 回复

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

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

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

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

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

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

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

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

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

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

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

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

踩坑王!

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