背景

  1. Appium 目前最新的版本是 1.6.3 ,appium 客户端 (appium server 的 GUI 图形化操作界面) 最新版本是 1.5.3, 但是 appium GUI 目前还只支持到iOS10以下基于UIAutomation框架的测试,而iOS10以后苹果已经更改为XCUITest

  2. 我们项目中想要做到对开发代码无侵染的方式来达到自动化测试的目的(这就需要通过 xpath 的方式去查找页面元素)

  3. 项目是使用 React Native 跨平台开发的应用

综合这三个背景,并且 iOS + React Native 结合的相关资料又比较少,就注定我要在自动化测试的道路上踩坑,写这篇这个也是想给后面玩的同学们一个肯定回答:appium + iOS10.2 + Xcode8.2.1 + React Native即使不在代码加 accessibilityLabel 或 TestID,就用 xpath 照样玩得转

开发环境

前期准备

需要安装的辅助工具

环境搭建

经过一个星期的折腾,最终搭建满足 UIAutomation 和 XCUITest 的测试环境:

1. 使用 npm 或 cnpm 安装 appium,appium-doctor

$ npm install -g appium
$ npm install -g appium-doctor

2. 下载 appium GUI

appium 和 appium GUI 只要安装其中一项就可以启动服务,但是如果要用到其中的 inspector 去检查元素的 xpath,所以还是安装了

下载地址. appium-desktop

安装最新的版本 1.5.3 就行,但是即使最新的,也只能支持 iOS10 以下系统的元素检查。

3. 使用 appium-doctor 检查 appium 环境

$ appium-doctor //appium-doctor --ios 只检测iOS环境
info AppiumDoctor Appium Doctor v.1.4.1
info AppiumDoctor ### Diagnostic starting ###
info AppiumDoctor ✔ The Node.js binary was found at: /usr/local/bin/node
info AppiumDoctor ✔ Node version is 6.3.1
info AppiumDoctor ✔ Xcode is installed at: /Applications/Xcode_7.3.1.app/Contents/Developer
info AppiumDoctor ✔ Xcode Command Line Tools are installed.
info AppiumDoctor ✔ DevToolsSecurity is enabled.
info AppiumDoctor ✔ The Authorization DB is set up properly.
info AppiumDoctor ✔ Carthage was found at: /usr/local/bin/carthage
info AppiumDoctor ✔ HOME is set to: /Users/iSteven
info AppiumDoctor ✔ ANDROID_HOME is set to: /Users/iSteven/Library/Android/sdk
info AppiumDoctor ✔ JAVA_HOME is set to: /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home
info AppiumDoctor ✔ adb exists at: /Users/iSteven/Library/Android/sdk/platform-tools/adb
info AppiumDoctor ✔ android exists at: /Users/iSteven/Library/Android/sdk/tools/android
info AppiumDoctor ✔ emulator exists at: /Users/iSteven/Library/Android/sdk/tools/emulator
info AppiumDoctor ✔ Bin directory of $JAVA_HOME is set
info AppiumDoctor ### Diagnostic completed, no fix needed. ###
info AppiumDoctor
info AppiumDoctor Everything looks good, bye!
info AppiumDoctor

环境常见问题解决:

4. 安装 appium client 端

appium client 有 ruby,python,java 三个版本,可自行选择自己喜欢的安装即可

python 版

pip install Appium-Python-Client
如果安装过程出现 could not create ‘/Library/Python/2.7/site-packages/appium’: Permission denied 错误,

使用 pip install Appium-Python-Client –user 命令可以安装成功

tar -xvf Appium-Python-Client-X.X.tar.gz
cd Appium-Python-Client-X.X
python setup.py install

git clone git@github.com:appium/python-client.git
cd python-client
python setup.py install

ruby 版(一定要在线安装)

ruby 的 appium client 叫做 appium lib,为什么是这样就不解释了,总之是历史原因。

首先 update rubygem 和 bundler(说老实话,真的不需要,但官方文档上这么写)

gem update --system
gem update bundler

然后使用 gem 安装

gem uninstall -aIx appium_lib \\(这个也不是必须的)
gem install --no-rdoc --no-ri appium_lib

java 版(在线安装)

java 的话用 maven 安装就可以了

<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>1.3.0</version>
</dependency>

也可以自己下载 jar 包,请自行选择最新版本。

5. 其他相关安装

brew install libimobiledevice --HEAD
brew install ideviceinstaller
npm install -g ios-deploy
sudo gem install xcpretty

6. 安装 app-inspector

npm install app-inspector -g

到这里所有相关的环境就已经安装好了,下面就可以开始撸起袖子干了,也是大家的踩坑时间了

如果以上安装还有问题,可以参考:

在 MAC 上搭建 appium1.6.3 过程
appium1-macOS10.12 下如何丝滑的使用 appium?

运行 Demo

  1. 下载 demo
  2. 启动 appium 服务

    appium

  3. cd 到sample-code-master/sample-code/examples/python目录下,运行下面命令就可以成功运行示例了

    python ios_simple.py

    成功运行截图:

    Server 端成功运行:

    Client 端成功运行:

    要成功运行,得满足以下条件:

* 有安装 python
* 保证/apps/TestApp/build/release-iphonesimulator/TestApp.app 路径下存在 TestApp.app 这个文件
* 保证 ios_simple.py 示例中的 platVersion 填的是你 Xcode 版本有的 iOS 系统版本

遇到错误:

[XCUITest] Error: simctl error running 'install': An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=2):
Failed to install the requested application
An application bundle was not found at the provided path.
Provide a valid path to the desired application bundle.

执行跑 demo 的时候,app 安装不上, 将 app 文件直接移到同脚本同级目录,修改app = os.path.abspath('../../apps/TestApp/build/release-iphonesimulator/TestApp-iphonesimulator.app')
app = os.path.abspath('TestApp-iphonesimulator.app')即可。

到这里不出问题的话,恭喜你已经可以成功使用 Appium 自动化测试框架了

遇到的问题

这个过程中磕磕绊绊碰到了不少问题,现在只能列出稍微还记得的一些问题吧。

1. 通过 appium inspector Xpath 获取到的 React Native 页面封装的 TextInput 不能使用 sendkeys 或 set_Value 输入。

下图便是 appium inspector+Xcode7.3.1+iOS9.3 上 react native 页面元素,后面和 android 端同事比对下 xpath 路径,发现 iOS 这边路径明显比安卓短很多,后面通过 app-inspector 获取到也是要长很多 (获取到的是基于 XCUITest 的,元素都是以 XCUIElementType 标识),也就是说只有 appium 基于 UIAutomation 的版本 RN 的 ‘textfield’ 不支持直接使用 send_keys 或 set_value 来输入,应该 appium 1.5.3 中 inspector 对 rn 的适配还没那么好导致的。

解决方法:app-inspector 检查元素得到 xpath 即可正常输入。(尝试过 WebDriveAgent 获取 xpath,rn 页面整个是个 label 文字显示;也尝试过查找键盘上对应键再 click,速度太慢不能接受)

app-inspector 使用方法:

app-inspector -u <设备/模拟器UDID> //加 --verbose可查看详情

2. app-inspector 模拟器运行报错

server.js:16:12 [master] pid:32216 server start with config:
{ port: 5678,
verbose: true,
udid: 'DC8E88DF-EDA7-487A-9D34-77AA58B3ADB5',
ip: '10.180.185.87',
host: 'iStevendeMacBook-Pro.local',
loaded_time: '2017-02-27 16:42:19' }
app-inspector.js:42:10 [master] pid:32216 server start at: http://10.180.185.87:5678
xctest-client.js:56:14 [master] pid:32216 project path: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/xctest-client/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
xctest-client start with port: 8900
xctest-client.js:233:14 [master] pid:32216 xcode version: 7.3.1
WebDriverAgent version: 1.0.41
xctest-client.js:99:16 [master] pid:32216 tail: /Users/iSteven/Library/Logs/CoreSimulator/DC8E88DF-EDA7-487A-9D34-77AA58B3ADB5/system.log: No such file or directory
xctest-client.js:107:16 [master] pid:32216 simulator log process exit with code: 1, signal: null
xctest-client.js:255:14 [master] pid:32216 Fail to start xctest: undefined
xctest-client.js:267:14 [master] pid:32216 killing deviceLogProc pid: 32220
xctest-client.js:272:14 [master] pid:32216 killing runnerProc pid: 32221
app-inspector:66:44 [master] pid:32216 undefined
xctest-client.js:181:14 [master] pid:32216 xctest client exit with code: null, signal: SIGKILL

这个问题还去提了 issue,但是后面自己卸载再重装就好了,也不知道是什么东西没装好还是咋的,希望有清楚的可以回答下

遇到这样问题可按这里配置下环境试试macaca 环境配置

成功运行之后就是可以看到下图,并且会自动打开浏览器,load 模拟器或者真机。

3. app-inspector 真机运行报错

>> xctest-client.js:171:14 [master] pid:11850 please check project: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:170:14 [master] pid:11850 2017-03-03 16:09:44.301 xcodebuild[11856:248062] Error Domain=com.apple.dtdevicekit Code=-402652994 "App installation failed" UserInfo={NSLocalizedFailureReason=This application's application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed., com.apple.dtdevicekit.stacktrace=(
0 DTDeviceKitBase 0x000000011145537b DTDKCreateNSError + 113
1 DTDeviceKitBase 0x0000000111455ab9 DTDK_AMDErrorToNSError + 791
2 DTDeviceKitBase 0x00000001114959df __90-[DTDKRemoteDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:]_block_invoke + 158
3 DVTFoundation 0x0000000108686989 DVTInvokeWithStrongOwnership + 75
4 DTDeviceKitBase 0x0000000111495725 -[DTDKRemoteDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:] + 1181
5 IDEiOSSupportCore 0x000000011138be1f __118-[DVTiOSDevice(DVTiPhoneApplicationInstallation) processAppInstallSet:appUninstallSet:installOptions:completionBlock:]_block_invoke.336 + 4597
6 DVTFoundation 0x00000001087aacb7 __DVTDispatchAsync_block_invoke + 827
7 libdispatch.dylib 0x00007fffacd96ef7 _dispatch_call_block_and_release + 12
8 libdispatch.dylib 0x00007fffacd8e0b8 _dispatch_client_callout + 8
9 libdispatch.dylib 0x00007fffacda4ae5 _dispatch_queue_serial_drain + 896
10 libdispatch.dylib 0x00007fffacd96cd9 _dispatch_queue_invoke + 1046
11 libdispatch.dylib 0x00007fffacd8fe70 _dispatch_root_queue_drain + 476
12 libdispatch.dylib 0x00007fffacd8fc47 _dispatch_worker_thread3 + 99
13 libsystem_pthread.dylib 0x00007fffacfdb712 _pthread_wqthread + 1299
14 libsystem_pthread.dylib 0x00007fffacfdb1ed start_wqthread + 13
), NSLocalizedRecoverySuggestion=This application's application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed., NSLocalizedDescription=App installation failed}
>> xctest-client.js:171:14 [master] pid:11850 please check project: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:170:14 [master] pid:11850 2017-03-03 16:09:44.301 xcodebuild[11856:248062] Error Domain=IDETestOperationsObserverErrorDomain Code=5 "Early unexpected exit, operation never finished bootstrapping - no restart will be attempted" UserInfo={NSLocalizedDescription=Early unexpected exit, operation never finished bootstrapping - no restart will be attempted}
>> xctest-client.js:171:14 [master] pid:11850 please check project: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:170:14 [master] pid:11850
Testing failed:
Test target WebDriverAgentRunner encountered an error (Early unexpected exit, operation never finished bootstrapping - no restart will be attempted)
>> xctest-client.js:171:14 [master] pid:11850 please check project: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:170:14 [master] pid:11850 ** TEST FAILED **
>> xctest-client.js:171:14 [master] pid:11850 please check project: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:267:14 [master] pid:11850 killing deviceLogProc pid: 11853
>> xctest-client.js:272:14 [master] pid:11850 killing runnerProc pid: 11856
>> xctest-client.js:278:14 [master] pid:11850 killing iproxyProc pid: 11855
>> xctest-client.js:181:14 [master] pid:11850 xctest client exit with code: 65, signal: null
>> xctest-client.js:209:14 [master] pid:11850 iproxy exit with code: null, signal: SIGKILL
>> xctest-client.js:145:16 [master] pid:11850 deviceconsole exit with code: null, signal: SIGKILL
>> xctest-client.js:255:14 [master] pid:11850 Fail to start xctest: undefined
>> app-inspector:66:44 [master] pid:11850 undefined

捕捉关键信息

>> xctest-client.js:171:14 [master] pid:11850 please check project: /Users/iSteven/.nvm/versions/node/v6.3.1/lib/node_modules/app-inspector/node_modules/webdriveragent/WebDriverAgent/WebDriverAgent.xcodeproj
>> xctest-client.js:170:14 [master] pid:11850
2017-03-03 16:09:44.301 xcodebuild[11856:248062] Error Domain=com.apple.dtdevicekit Code=-402652994 "App installation failed" UserInfo={NSLocalizedFailureReason=This application's application-identifier entitlement does not match that of the installed application. These values must match for an upgrade to be allowed.,

从上面看就是 bundle-id 错误,进到 WebDriverAgent 工程目录下修改工程 bundle-id 重新运行即可

4. 团队里有人因为先安装 Appium 后再安装 Xcode 获取不到 Xcode 版本问题,具体错误信息如下:

WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Could not determine Xcode version: Could not get Xcode version. /Library/Developer/Info.plist does not exist on disk.

解决办法: 卸载 Appium,重新安装

5. WebDriverAgent 相关依赖安装出错

[Xcode] 2017-04-05 16:09:12.331 xcodebuild[91135:3418654] Error Domain=IDEFoundationErrorDomain Code=1 "Cannot launch simulated executable: no file found at /Users/Chetwyn/Library/Developer/Xcode/DerivedData/WebDriverAgent-cvqckynzuuktkogfpkkkgyompmoj/Build/Products/Debug-iphonesimulator/WebDriverAgentRunner-Runner.app" UserInfo={NSLocalizedDescription=Cannot launch simulated executable: no file found at /Users/Chetwyn/Library/Developer/Xcode/DerivedData/WebDriverAgent-cvqckynzuuktkogfpkkkgyompmoj/Build/Products/Debug-iphonesimulator/WebDriverAgentRunner-Runner.app}
[Xcode] 
[Xcode] 2017-04-05 16:09:12.331 xcodebuild[91135:3418654] Error Domain=IDETestOperationsObserverErrorDomain Code=6 "Early unexpected exit, operation never finished bootstrapping - no restart will be attempted" UserInfo={NSLocalizedDescription=Early unexpected exit, operation never finished bootstrapping - no restart will be attempted}

解决办法: 卸载 appium-xcuitest-driver,重新安装,再执行./Scripts/bootstrap.sh -d

npm uninstall appium-xcuitest-driver
nom install appium-xcuitest-driver
./Scripts/bootstrap.sh -d

6. 最近 Xcode 升级到 8.3, WebDriverAgent 工程跑不起来,报错误:"XCUISiriService is partial: introduced in iOS 10.3 XCUIDevice.h"

解决办法: 找到 WebDriverAgent/Configurations/ProjectSettings.xcconfig 文件,在原来
WARNING_CFLAGS = $(inherited) -Weverything -Wno-objc-missing-property-synthesis -Wno-unused-macros -Wno-disabled-macro-expansion -Wno-gnu-statement-expression -Wno-language-extension-token -Wno-overriding-method-mismatch -Wno-missing-variable-declarations -Rno-module-build -Wno-auto-import -Wno-objc-interface-ivars -Wno-documentation-unknown-command -Wno-reserved-id-macro -Wno-unused-parameter -Wno-gnu-conditional-omitted-operand -Wno-explicit-ownership-type -Wno-date-time -Wno-cast-align -Wno-cstring-format-directive -Wno-double-promotion -Wno-partial-availability

后面加上-Wno-partial-availability即可

WebdirverAgent 上相关 issue: Silence unguarded availability warning from Xcode 8.3 #525

最后找到其解决的commit

参考资料


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