Appium Android 自动化实践:Appium+Python 入门

于归 · September 09, 2017 · Last by 百事可乐 replied at November 08, 2018 · 9442 hits

写在开头

在社区潜水一年多,潜水期间社区里的内容解决了我在工作中大大小小的各种问题,正好这段时间开始又重新开始研究了移动端自动化测试,就准备把自己瞎琢磨的一些东西分享给有需要的朋友吧~ 😂

环境搭建

appium的环境搭建社区里已经有hin多hin详细的帖子了,可以参照这篇帖子:Appium macOS 下的 Appium 安装与配置
,这里就不多加介绍了,还没有搭建环境的或者搭建过程中碰到一些问题的,可以尝试看看这篇帖子,说不定有你想要的答案哦~😄

正文内容

Android元素定位

下面开始介绍目前所了解到的两种元素定位的工具吧~

uiautomatorviewer

uiautomatorviewer是Android SDK自带的工具,mac是在../../Library/Android/sdk/tools/bin
路径下,在目录下执行命令./uiautomatorviewer就可以愉快的用它进行元素定位了~相信大家用的都比较多的啦~😇
下面使用的是我厂的产品(不打广告),如下:

😂 想知道哪里点哪里,真的是so easy~
不过用的时候碰到这个问题:

😂 我把模拟器重启了一下就好了,尴尬~

Appium Desktop

Appium Desktop是在appium官方网站下载的,刚用的时候还有点懵逼,这特么是个什么鬼~
😂 后来通过查找各种资料,终于会用了,可以出来显摆一下了~
入口如下图,开启appium服务之后,点击上面的「Start New Session」按钮,就进入到图右边的界面啦~

然后像右图一样配置好测试设备的信息,点击开始就可以进入到获取元素定位的界面,如下图:

😀 这块功能挺好玩的,中间部分有个小眼睛的按钮,点击可以进行录制,还能把操作转成你想要的测试代码,右边还有三个操作「Tap」、「send keys」和「clear」

测试脚本编写

导入相关的库

import unittest # 单元测试框架
from appium import webdriver # appium

用unittest编写测试脚本框架

class AppTest(unittest.TestCase):

def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = '/Users/yugui/Desktop/idxyer-v7.3.3.apk'
desired_caps['noReset'] = False
desired_caps["unicodeKeyboard"] = "True"
desired_caps["resetKeyboard"] = "True"

self.wd = webdriver.Remote('http://127.0.0.1:4725/wd/hub', desired_caps)
self.wd.implicitly_wait(60)

def test_login(self):
pass

def tearDown(self):
self.wd.quit()

if __name__ == '__main__':
unittest.main()

编写测试用例

还是以我厂的app为例,想写一个登录的小demo,但是实践过程中发现以下几个问题:

  1. 大多数新装的app都会出现几页的欢迎页,那么问题来了:
    1. 欢迎页的上下左右滑动
    2. 如果不是新装的app,那么就应该是直接登录就可以了,就不用滑动欢迎页了
  2. 用户登录状态
    1. 如果用户未登录,那么才能输入用户名密码进行登录
    2. 如果用户已登录,直接返回用户已登录的信息,进行其他的操作就可以了

接下来就开始解决这些问题啦~👏

  1. 滑动页面元素,可以使用swipe来进行操作,我在这里封装了一个方法,以方便使用,下面贴代码:
def SwipeLeft(self, duration):
# 获取手机分辨率的宽度
x = self.wd.get_window_size()['width']
# 获取手机分辨率的高度
y = self.wd.get_window_size()['height']
self.wd.swipe(x * 9/10, y/2, x/10, y/2, duration)
  1. 当打开app时,没有欢迎页,那么就不需要进行滑动页面了,所以我们应该在这里判断元素是否存在,如果存在则滑动页面,不存在则输出相应信息并进行下一步操作 在这里我也是封装了一个函数,因为感觉有好些地方都要用到呢~ 下面贴代码:
def findElement(self, element):
try:
WebDriverWait(self.wd, 10).until(expected_conditions.presence_of_element_located((By.ID, element)))
return True
except selenium.common.exceptions.TimeoutException:
return False
except selenium.common.exceptions.NoSuchElementException:
return False

🙃 因为元素找不到有多重原因,有可能是超时也有可能是没有这个元素,所以这里做了两个异常处理。

下面是正经的测试代码,

def test_login(self):
if self.findElement('cn.dxy.idxyer:id/start_up_welcome_image_iv'):
for i in range(3):
self.SwipeLeft(1000)
self.wd.find_element_by_id('cn.dxy.idxyer:id/start_up_welcome_enter_tv').click()
else:
print('欢迎页不存在的')
self.wd.implicitly_wait(60)
self.wd.find_element_by_id('cn.dxy.idxyer:id/main_mine_rb').click()
if self.findElement('cn.dxy.idxyer:id/tab_account'):
self.wd.find_element_by_id('cn.dxy.idxyer:id/sso_username').set_value('111111111')
self.wd.find_element_by_id('cn.dxy.idxyer:id/sso_password').set_value('111111111')
self.wd.find_element_by_id('cn.dxy.idxyer:id/sso_login').click()
else:
print('用户已登录')

👊 到这里也差不多收工了,最后贴上完整的.py文件:

import unittest
import selenium.common.exceptions
from appium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By


class AppTest(unittest.TestCase):

def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = '/Users/yugui/Desktop/idxyer-v7.3.3.apk'
desired_caps['noReset'] = False
desired_caps["unicodeKeyboard"] = "True"
desired_caps["resetKeyboard"] = "True"

self.wd = webdriver.Remote('http://127.0.0.1:4725/wd/hub', desired_caps)
self.wd.implicitly_wait(60)

# 向左滑动的函数
def SwipeLeft(self, duration):
x = self.wd.get_window_size()['width']
y = self.wd.get_window_size()['height']
self.wd.swipe(x * 9/10, y/2, x/10, y/2, duration)

# 当元素找不到时
def findElement(self, element):
try:
WebDriverWait(self.wd, 10).until(expected_conditions.presence_of_element_located((By.ID, element)))
return True
except selenium.common.exceptions.TimeoutException:
return False
except selenium.common.exceptions.NoSuchElementException:
return False

def test_login(self):
if self.findElement('cn.dxy.idxyer:id/start_up_welcome_image_iv'):
for i in range(3):
self.SwipeLeft(1000)
self.wd.find_element_by_id('cn.dxy.idxyer:id/start_up_welcome_enter_tv').click()
else:
print('欢迎页不存在的')
self.wd.implicitly_wait(60)
self.wd.find_element_by_id('cn.dxy.idxyer:id/main_mine_rb').click()
if self.findElement('cn.dxy.idxyer:id/tab_account'):
self.wd.find_element_by_id('cn.dxy.idxyer:id/sso_username').set_value('1111111')
self.wd.find_element_by_id('cn.dxy.idxyer:id/sso_password').set_value('1111111')
self.wd.find_element_by_id('cn.dxy.idxyer:id/sso_login').click()
else:
print('用户已登录')

def tearDown(self):
self.wd.quit()

if __name__ == '__main__':
unittest.main()

最后

😳 第一次写分享,感觉篇幅有那么一丢丢长,能看到这里的应该都是真爱了,如果有不足的地方希望大家可以给出改进意见哪~

共收到 11 条回复 时间 点赞

赞一个!

正经的代码😂, 加油

kookooji 回复

😂 谢谢你的消灭零回复,哈哈

Scofell 回复

🙃 很正经的哦

案例很详细,入门必备

大神厉害了 支持😜 😜 😜

猜测是妹子,很萌

期待后续

羡慕 楼主框架用的这么熟练

我怎么不能执行第一个if语句呢,直接打印了

可以了,可能一开始改的东西,加多了

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 13 Dec 20:49
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up