前言
参考这篇博客,我搭建了iOS的自动化测试环境,基于Appium。以下就是在搭建的过程中遇到的若干问题。
框架选择
基于这几项标准:
- 同时支持iOS、Android、H5,且尽量能保持接口统一,减少开发维护成本;
- 编程语言支持Python/Ruby;
- 用户量大,文档丰富。
最后确定的是Appium
Appium简介
Appium的具体介绍,参考Appium。
这里是几点比较好的理念。
- 采用Appium时,无需对被测应用做任何修改,也无需嵌入任何东西;
- Appium对iOS和Android的原生自动化测试框架进行了封装,并提供了统一的API,减少了自动化测试代码的维护工作量;
- Appium采用Client-Server的架构设计,并采用标准的HTTP通信协议;Server端负责与iOS/Android原生测试框架交互,无需测试人员关注细节实现;Client端基本上可以采用任意主流编程语言编写测试用例,减少了学习成本。
环境准备(iOS)
这个部分是根据博客的流程来的,也是此篇的重点,介绍中间集成中遇到的各种问题,以及解决方式。
在Appium中测试iOS时,依赖于Apple开发环境,比如Xcode(大于4.6.3)、Apple Developer Tools,当然,这对于我而言肯定是已经具备好的。
在安装Appium之前,为了确保Appium的相关依赖已经准备就绪,可以使用Appium-doctor来进行验证。
-
$ appium-doctor --ios
如果是全绿色表示都是成功的,如果没有安装或者缺少组件,那肯定看不到这种状态。
安装
$ npm install appium-doctor -g
如果顺利安装,则会出现如下:
这是部分截图,如果出现了红色error信息的话,那就是安装失败了。比如:ERR! { Error: EACCES: permission denied, access '/usr/local/lib/node_modules' 这样的提示,那就是没有权限。需要再刚刚的命令行中添加sudo,或直接切换到root模式下。我选择添加sudo
即 $ sudo npm install appium-doctor -g
appium-doctor 验证失败
目前我这里只出现了一种验证失败的情况,后续发现更多的话会及时补充。
我遇到的问题是:AppiumDoctor ✖ Carthage was NOT found!
提示我没有Carthage,直接安装一个即可。
$ brew install carthage
( #carthage:类似cocoapods管理第三方代码,自动将工程编译为动态库 )我采用 homebrew 来安装。安装成功了,但是提示我brew有点老旧,需要升级(brew update),这算是题外话
$ appium-doctor --ios 再次验证,发现已经全部验证成功。好了,到下一步。
经过以上两步已经安装好了Appium的相关依赖。
安装Appium
有多种方式安装。Appium采用Client-Server的架构方式,我们这里指的安装是Server部分。
- 源代码编译安装;
- Terminal中通过npm命令安装;
- 直接下载appium.dmg安装
这里比较推荐第三个,直接安装应用程序,虽然看起来没有那么高大上,但是比较方便,除了GUI界面操作更直观以外,更重要的原因是,相比于命令行运行方式,Appium app多了一个Inspector模块,可以调用模拟器运行被测应用程序,并且可以更方便地在预览页面中查看UI元素的层级结构和详细控件属性,极大地提高了编写测试脚本的效率。
Client部分是编写脚本。其实我们原本可以不安装任何东西,只需要选择任意一门开发语言,然后直接基于WebDriver的C/S协议即可编写自动化测试代码。
我们现在安装,主要就是安装Library。
比如选择ruby,那么需要安装的Library就是appium_lib,安装方式如下:
- $ gem install appium_lib
我同样遇到了权限的问题,需要sudo权限。 -
$ sudo gem install appium_lib 然后报错了
报错,我的ruby版本过低了,那当然是升级ruby啊。在网上找的方案中,是通过rubygems-update来升级ruby,我试了一下,发现并不方便。所以我选择安装rvm,使用rvm来升级ruby。
升级ruby的方式有多种,这里简单介绍一下。
-
gem install rubygems-update
update_rubygems
这是通过rubygems来升级。我完成了第一步之后,遇到了另外一个问题,AML safe loading is not available. Please upgrade psych to a version that supports safe loading (>= 2.0).有点连锁反应啊,遂换成了其他的方案升级。当然,这个方案也是有效的,我遇到的这些问题兴许你们不会遇到的。
通过rvm安装
$ curl -L get.rvm.io | bash -s stable
brew upgrade bash
再执行安装命令,还是报同样的错误。
发现问题其实是在于libreadline.6.dylib不能成功loaded,试着根据目录找到这个库,发现没找到。
ln -s /usr/local/opt/readline/lib/libreadline.7.dylib /usr/local/opt/readline/lib/libreadline.6.dylib
再次执行安装命令,出现了成功的画面。BingGo!rvm安装好了。接下来看下一步。
-
$ ruby -v 查询当前版本,发现我的版本不高
-
$ rvm list known
-
$ rvm install 2.4
这就是安装好了。再次检查,$ ruby -v
嗯?可能你会出现版本还是旧的情况,当然如果没有出现,就继续执行接下来的。 安装好了,但是检查的版本依旧是旧的,十有八九ruby的环境变量路径错了。两个办法。第一个办法:添加ruby至环境变量。
vim .profile
vim .bashrc
vim .bash_profile
然后重启source
source .profile
source .bash_profile
第二个办法,如果是iterm2的话,选择菜单栏--profiles--选择login shell,打开新的窗口。执行 $ rvm use 2.4.1
(我的是2.4.1的版本),然后执行ruby -v
就可以发现是最新的了。
真是一步一个脚印啊!
3.通过homebrew安装
$ brew install ruby
安装后检查ruby版本,如果出现了上述一样的情况,那么也可以采用那两种方案。
至此,ruby的Library就搭建好了。
接下来看python。python比较简单。
`$ pip install Appium-Python-Client` 搞定
Appium使用
先记住这个:
{
"platformName": "iOS",
"platformVersion": "11.0",
"deviceName": "iPhone 7",
"automationName": "XCUITest",
"app": "/path/to/my.app"
}
很重要!很重要!很重要!
Appium开始
前面介绍的只是desktop的使用而已。接下来介绍重点的服务端和客户端的配合使用。以python为例。
服务端
brew install node //get node.js
npm install -g appium //get appium
npm install wd //get appium client
appium & //start appium
这几步每一步都可能出问题。我在第一步和第二步均出现了问题。我安装了node,但是link错了。
此乃解决之道(源自Stack Overflow):
sudo brew uninstall node
brew update
brew upgrade
brew cleanup
brew install node
sudo chown -R $(whoami) /usr/local
brew link --overwrite node
brew postinstall node
后面几步算是比较顺利的。
直到我启动之后执行脚本。因为我使用的是python,所以命令是:
python appiumSimpleDemo.py
然并卵,失败了。原因是我安装了好几个python版本,在不同的路径之下,解决的办法是:修改路径;或者直接使用python3启动即可。不更换路径了。
python3 appiumSimpleDemo.py
客户端
任重而道远。
其实上文已经介绍过了。
附脚本文件:
import unittest
import os
from appium import webdriver
from time import sleep
from appium.webdriver.common.touch_action import TouchAction
class appiumSimpleTezt (unittest.TestCase):
def setUp(self):
app = os.path.abspath('/Users/Jeffrey/Desktop/CareVoice.app')
self.driver = webdriver.Remote(
command_executor = 'http://127.0.0.1:4723/wd/hub',
desired_capabilities = {
'app':app,
'platformName': 'iOS',
'platformVersion': '11.2',
'deviceName': 'iPhone 8',
'bundleId': 'co.kangyu.Kangyu',
'automationName':'XCUITest',
"noReset": 'true'
# 'udid': '45751dc8cd8d737bbcea48a0307d50419161afb8'
}
)
def test_ui_computation(self):
print ("Hello world")
sleep(2)
print ("nihaoa")
driver = self.driver
el1 = driver.find_element_by_accessibility_id("Profile")
el1.click()
print ('点击profile')
el2 = driver.find_element_by_accessibility_id("Sign In")
el2.click()
print ('点击signIn')
el3 = driver.find_element_by_xpath("//XCUIElementTypeApplication[@name=\"The CareVoice\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther[1]/XCUIElementTypeScrollView")
el3.click()
print ('点击密码登录')
el4 = driver.find_element_by_accessibility_id("phone")
print ('点击用户名')
el4.send_keys("12345678902")
print ('输入用户名')
el5 = driver.find_element_by_xpath("//XCUIElementTypeApplication[@name=\"The CareVoice\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther[3]/XCUIElementTypeOther[1]/XCUIElementTypeSecureTextField")
print ('点击密码')
el5.send_keys("111111")
print ('输入密码')
el5.click()
el6 = driver.find_element_by_accessibility_id("Sign In")
el6.click()
print ('点击登录')
def tearDown(self):
sleep(20)
print ('退出程序')
self.driver.quit()
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(appiumSimpleTezt)
unittest.TextTestRunner(verbosity=2).run(suite)
其中使用了录制的功能,简化书写脚本的过程。
关于取控件的部分(基本算是python测试案例的事情了),需要根据Appium-desktop来获取。以及录制脚本的相关操作。会在下一篇补充了。