|
| 1 | +--- |
| 2 | +title: Appium自动化测试介绍和使用说明 |
| 3 | +date: 2018-09-09 20:58:43 |
| 4 | +tags: Appium, Python |
| 5 | +category: iOS |
| 6 | +--- |
| 7 | + |
| 8 | +### 前言 |
| 9 | +最初因为公司业务需要,公司缺少测试,所以要求开发人员自行进行测试,甚至是自动化测试,各人负责自己的产品和功能。所以需要寻找一种比较合适的自动化测试框架来实现。 |
| 10 | + |
| 11 | +#### 框架选择 |
| 12 | +基于这几项标准: |
| 13 | + |
| 14 | +* 同时支持iOS、Android、H5,且尽量能保持接口统一,减少开发维护成本; |
| 15 | +* 编程语言支持Python/Ruby; |
| 16 | +* 用户量大,文档丰富。 |
| 17 | + |
| 18 | +最后确定的是**Appium** |
| 19 | + |
| 20 | +#### Appium简介 |
| 21 | +Appium的具体介绍,参考[Appium](http://appium.io/)。 |
| 22 | +这里是几点比较好的理念。 |
| 23 | + |
| 24 | +* 采用Appium时,无需对被测应用做任何修改,也无需嵌入任何东西; |
| 25 | +* Appium对iOS和Android的原生自动化测试框架进行了封装,并提供了统一的API,减少了自动化测试代码的维护工作量; |
| 26 | +* Appium采用Client-Server的架构设计,并采用标准的HTTP通信协议;Server端负责与iOS/Android原生测试框架交互,无需测试人员关注细节实现;Client端基本上可以采用任意主流编程语言编写测试用例,减少了学习成本。 |
| 27 | + |
| 28 | +### 环境准备(iOS) |
| 29 | +#### 安装Appium依赖 |
| 30 | + |
| 31 | +验证:`$ appium-doctor --ios` |
| 32 | +安装:`$ npm install appium-doctor -g` |
| 33 | +再次验证:`$ appium-doctor --ios` 成功即可 |
| 34 | + |
| 35 | + |
| 36 | + |
| 37 | +#### 安装Appium的server部分 |
| 38 | + |
| 39 | +有多种方式安装: |
| 40 | + |
| 41 | +* 源代码编译安装; |
| 42 | +* Terminal中通过npm命令安装; |
| 43 | +* 直接下载[appium.dmg](https://bitbucket.org/appium/appium.app/downloads/)安装 |
| 44 | + |
| 45 | +这里比较推荐第三个(我安装的是v1.7.1),直接安装应用程序,虽然看起来没有那么高大上,但是比较方便,除了GUI界面操作更直观以外,更重要的原因是,相比于命令行运行方式,Appium app多了一个Inspector模块,可以调用模拟器运行被测应用程序,并且可以更方便地在预览页面中查看UI元素的层级结构和详细控件属性,极大地提高了编写测试脚本的效率。为了操作更加方便,同时我也使用npm进行了安装。 |
| 46 | + |
| 47 | +提供相关命令: |
| 48 | + |
| 49 | +``` |
| 50 | +>brew install node //get node.js |
| 51 | +>npm install -g appium //get appium |
| 52 | +>npm install wd |
| 53 | +``` |
| 54 | + |
| 55 | +#### 安装Appium的client部分 |
| 56 | +client部分实际就是安装脚本的编译环境。Appium最主流是使用ruby脚本或python脚本。刚开始我选择的是ruby脚本,在配置环境的过程中遇到了各种问题,耗时比较久,因为对ruby不够熟悉,最后还是选择了python来实现。(ruby的配置方法暂时不进行介绍) |
| 57 | + |
| 58 | +配置python环境很简单:`$ pip install Appium-Python-Client` |
| 59 | + |
| 60 | +### Appium-desktop使用 |
| 61 | +先记住这个: |
| 62 | +{ |
| 63 | + "platformName": "iOS", |
| 64 | + "platformVersion": "11.0", |
| 65 | + "deviceName": "iPhone 7", |
| 66 | + **"automationName": "XCUITest",** |
| 67 | + "app": "/path/to/my.app" |
| 68 | +} |
| 69 | +很重要!很重要!很重要! |
| 70 | + |
| 71 | +1. 启动Appium |
| 72 | +2. start之后,点击放大镜图标进行配置,配置内容为上述的这个部分。 |
| 73 | +3. 点击“Start Session” |
| 74 | +4. 等待片刻即开始运行。可以进行tap gesture sendKey 以及可以录制脚本(录制的脚本大多数情况下不能直接使用,会有一些方法的调整)。 |
| 75 | + |
| 76 | +### 开始python自动化测试 |
| 77 | +#### 编写python脚本 |
| 78 | +基于appium-desktop录制的脚本进行修改,得到如下脚本(login_test.py): |
| 79 | + |
| 80 | +``` |
| 81 | +import unittest |
| 82 | +import os |
| 83 | +from appium import webdriver |
| 84 | +from time import sleep |
| 85 | +from appium.webdriver.common.touch_action import TouchAction |
| 86 | +from selenium.common.exceptions import NoSuchElementException |
| 87 | +
|
| 88 | +
|
| 89 | +class loginTest (unittest.TestCase): |
| 90 | +
|
| 91 | + def setUp(self): |
| 92 | + app = os.path.abspath('/Users/Jeffrey/Desktop/CareVoice.app') |
| 93 | +
|
| 94 | + self.driver = webdriver.Remote( |
| 95 | + command_executor = 'http://127.0.0.1:4723/wd/hub', |
| 96 | + desired_capabilities = { |
| 97 | + 'app':app, |
| 98 | + 'platformName': 'iOS', |
| 99 | + 'platformVersion': '11.2', |
| 100 | + 'deviceName': 'iPad Air', |
| 101 | + 'bundleId': 'co.kangyu.Kangyu', |
| 102 | + 'automationName':'XCUITest', |
| 103 | + "noReset": 'true' |
| 104 | + # 'udid': '45751dc8cd8d737bbcea48a0307d50419161afb8' |
| 105 | + } |
| 106 | + ) |
| 107 | + def test_login(self): |
| 108 | + print ("启动login测试") |
| 109 | + sleep(1) |
| 110 | + print ("开始测试") |
| 111 | + driver = self.driver |
| 112 | +
|
| 113 | + el1 = driver.find_element_by_accessibility_id("Profile") |
| 114 | + el1.click() |
| 115 | + print ('点击profile') |
| 116 | +
|
| 117 | + el2 = driver.find_element_by_accessibility_id("Sign In") |
| 118 | + el2.click() |
| 119 | +
|
| 120 | + try: |
| 121 | + el3 = driver.find_element_by_xpath("//XCUIElementTypeApplication[@name=\"The CareVoice\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther[1]/XCUIElementTypeScrollView") |
| 122 | + except NoSuchElementException: |
| 123 | + print ('已经登录了') |
| 124 | + return; |
| 125 | + # 执行退出登录 |
| 126 | + TouchAction(driver).press(x=358, y=779).move_to(x=3, y=-303).release().perform() |
| 127 | + |
| 128 | + TouchAction(driver).press(x=339, y=787).move_to(x=22, y=-272).release().perform() |
| 129 | + |
| 130 | + TouchAction(driver).press(x=347, y=818).move_to(x=3, y=-444).release().perform() |
| 131 | + |
| 132 | + ell1 = driver.find_element_by_accessibility_id("Settings") |
| 133 | + ell1.click() |
| 134 | + print ('点击设置') |
| 135 | + ell2 = driver.find_element_by_accessibility_id("Sign Out") |
| 136 | + ell2.click() |
| 137 | + print ('点击退出登录') |
| 138 | +
|
| 139 | + el3 = driver.find_element_by_xpath("//XCUIElementTypeApplication[@name=\"The CareVoice\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther[1]/XCUIElementTypeScrollView") |
| 140 | + el3.click() |
| 141 | + else: |
| 142 | + print ('还没有登录,所以可以找到') |
| 143 | + el3.click() |
| 144 | +
|
| 145 | + print ('点击密码登录') |
| 146 | + el4 = driver.find_element_by_accessibility_id("phone") |
| 147 | + print ('点击用户名') |
| 148 | + el4.send_keys("13262851829") |
| 149 | + print ('输入用户名') |
| 150 | +
|
| 151 | + el5 = driver.find_element_by_xpath("//XCUIElementTypeApplication[@name=\"The CareVoice\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView") |
| 152 | + el5.click() |
| 153 | + print ('收起键盘') |
| 154 | +
|
| 155 | + el6 = driver.find_element_by_xpath("//XCUIElementTypeApplication[@name=\"The CareVoice\"]/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeScrollView/XCUIElementTypeOther[3]/XCUIElementTypeOther[1]/XCUIElementTypeSecureTextField") |
| 156 | + el6.click() |
| 157 | +
|
| 158 | + print ('点击密码') |
| 159 | + el6.send_keys("111111") |
| 160 | + print ('输入密码') |
| 161 | +
|
| 162 | + # el5.click() |
| 163 | + # el7 = driver.find_element_by_accessibility_id("Sign In") |
| 164 | + # el7.click() |
| 165 | + # print ('点击登录') |
| 166 | +
|
| 167 | + el8 = driver.find_element_by_accessibility_id("Return") |
| 168 | + el8.click() |
| 169 | + print ('点击登录') |
| 170 | +
|
| 171 | + sleep(1) |
| 172 | +
|
| 173 | + TouchAction(driver).press(x=394, y=303).move_to(x=-25, y=479).release().perform() |
| 174 | +
|
| 175 | + el8 = driver.find_element_by_accessibility_id("Home") |
| 176 | + print ('点击Home') |
| 177 | + el8.click() |
| 178 | +
|
| 179 | + def tearDown(self): |
| 180 | + sleep(5) |
| 181 | + print ('退出程序') |
| 182 | + self.driver.quit() |
| 183 | +
|
| 184 | +if __name__ == '__main__': |
| 185 | + suite = unittest.TestLoader().loadTestsFromTestCase(loginTest) |
| 186 | + unittest.TextTestRunner(verbosity=2).run(suite) |
| 187 | +
|
| 188 | +``` |
| 189 | + |
| 190 | +#### 开启Appium服务 |
| 191 | +`>appium & //start appium` |
| 192 | + |
| 193 | +如果服务开启成功,则会出现这样: |
| 194 | + |
| 195 | +#### 运行客户端脚本 |
| 196 | +`$ python3 login_test.py` |
| 197 | + |
| 198 | +运行成功即会打开模拟器运行程序,可以添加一些输出语句,观察实际的操作过程。 |
| 199 | + |
| 200 | +### 补充 |
| 201 | +建议参考Appium的官方文档,有很大的参考价值。 |
| 202 | +这是Appium的[示例代码](https://github.com/appium/sample-code)。 |
| 203 | +python[示例](https://github.com/appium/python-client/tree/master/test/functional/ios) |
| 204 | + |
| 205 | + |
| 206 | + |
0 commit comments