一.背景

由于自动化测试脚本中需要获取应用打印的网络请求结果日志来作为用例执行的结果的判断依据,刚开始都是通过 appium server 再 webhook 去获取日志,后面就觉得要在工程中转输出一个日志文件,团队合作还经常合并代码冲突,后来一想,为什么我们不自己直接去获取,多出中转输出这一步呢,于是就去研究 appium 是怎么获取日志并输出的,发现模拟器可以直接通过 tail 捕捉本地模拟器日志 system.log 文件即可,了解到真机需要通过 libimobiledevice 来获取,于是就去了解 libimobiledevice,到官网了解到最新的已经支持到 iOS10 系统,还好支持到 iOS10 了,因为所有用例都是基于 iOS10 后的 XCUITest 编写的,不然就 gg 了

二. tail 获取 iOS 模拟器日志

这个比较简单,只需要执行一个简单 tail 命令读取日志文件即可

1. 终端直接执行

tail -f <filename> //从文件尾部开始实时输出

日志文件的路径:/Users/$UserName/Library/Logs/CoreSimulator/$simulator_hash/system.log

UserName: 即你电脑用户名,simulator_hash:模拟器的 identifier

2. python 脚本 Popen 标准输出

由于是要在项目中抓取日志输出,所以就用到 python 的子进程 Subprocess 执行 tail 命令,并获得输出,再正则匹配需要的内容后再 kill 子进程


# conf配置文件读取(团队开发,所以这个路径是配置的)
user = config_manager.get('appInfo_%s' % coder, 'user')
simulator_hash = config_manager.get('appInfo_%s' % coder, 'simulator_hash')
filename = '/Users/%s/Library/Logs/CoreSimulator/%s/system.log' % (user, simulator_hash)
# 1. tail 文件尾持续读取方式
LogUitls.log_process = Popen(['tail', '-f', '-50', filename], stdout=PIPE, stderr=PIPE)
...
拿到输出匹配自己要的内容就可以了

三.libimobiledevice idevicesyslog 获取真机日志

真机获取日志就相对复杂些了,但是现在开源环境给了我们红利,之前提到过的 libimobiledevice 这个工具,这是一个 C 语言写的工具 ,具体的就没去研究了,用了几个命令之后,就猜测现在那些 iOS 的手机助手很有可能全是基于这个工具来写的

libimobiledevice简介

A cross-platform software protocol library and tools to communicate with iOS® devices natively.
也就是说 libimobiledevice 是一个跨平台的可与 iOS 设备通信的工具,也看过一些资料说是一些爱好者就破解了 iTunes 的通信协议,然后在 Linux 上实现了该协议

安装libimobiledevice

通过 github 上面可以看到安装需要安装很多依赖来支持,Mac 上安装应该是可以 homebrew 执行以下命令就可以简单的安装了,为什么说应该是因为自己这么安装遇到问题了

sudo brew install libimobiledevice

安装好之后连上自己 iOS10.2 系统果机,飞速敲入idevicesyslog -u <设备identifier>Could not start service com.apple.syslog_relay. 。。。只好去测试那边搜索一番找来一台 iOS10 的果 7,结果还是同样错误。。。再找一台 iOS8.x 系统,却是可以的,所以猜想可能是之前通过brew install libimobiledevice --HEAD安装的版本并不是最新的,于是有了下面的尝试,结果又碰一鼻子灰,当时也是把遇到的问题在 Note 中记录下来了,所以干脆一起贴出来吧

安装成功后,不仅 iOS10 可以支持,最新的 iOS10.3 也是可以的

git clone https://github.com/libimobiledevice/libimobiledevice.git
./autogen.sh
make
sudo make install

安装过程并不顺利,遇到了以下问题:

1. 'openssl/ssl.h' file not found

➜ libimobiledevice git:(master) make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all-recursive
Making all in common
CC socket.lo
CC thread.lo
CC debug.lo
In file included from debug.c:36:
../src/idevice.h:30:10: fatal error: 'openssl/ssl.h' file not found
#include <openssl/ssl.h>

在.bash_profile 或.zshrc 中添加以下环境变量设置
export LD_LIBRARY_PATH=$(brew --prefix openssl)/lib
export CPATH=$(brew --prefix openssl)/include
export PKG_CONFIG_PATH=$(brew --prefix openssl)/lib/pkgconfig

2. linker command failed with exit code 1 (use -v to see invocation)

Undefined symbols for architecture x86_64:
"_ERR_remove_thread_state", referenced from:
_internal_idevice_deinit in idevice.o
_idevice_connection_enable_ssl in idevice.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [libimobiledevice.la] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

看到有人说通过修改 openssl 的 linker 可以,但是对我不起作用,/usr/bin/openssl根本就不能移除,MacOS 使用
rm /usr/bin/openssl
ln –s /usr/local/Cellar/openssl/1.0.2h_1/bin/openssl /usr/local/bin

最后我是通过 github 上有认提供的安装脚本libimobile-installer重新安装的,脚本上的apt-get相关命令是 Linux 上的命令,Mac 上安装的话,可以注释掉,或者不用管也可以,报找不到命令的错误也没关系

libimobiledevice 使用

更多命令,可以输入 idevice 连按两个 tab 查看,我就不一一列举了

脚本中获取日志参考上面模拟器的方法即可。

真机日志 NSLog 输出还存在日志太长不全的问题

后面真机跑用例时发现,app 中打印的网络请求返回结果不全而导致获取不到结果而断言失败,google 一下发现有人同样遇到这种情况:
http://stackoverflow.com/questions/39584707/nslog-on-devices-in-ios-10-xcode-8-seems-to-truncate-why


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