移动端自动化测试Appium 从入门到项目实战Python版
最近某讯课堂查看了一个直播课程也有录播,讲的还不错,讲的自动化测试的从这里学到了这些有些感悟记录下,可以点击去看看
环境搭建
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,但是实践过程中发现以下几个问题:
- 大多数新装的app都会出现几页的欢迎页,那么问题来了:
- 欢迎页的上下左右滑动
- 如果不是新装的app,那么就应该是直接登录就可以了,就不用滑动欢迎页了
- 用户登录状态
- 如果用户未登录,那么才能输入用户名密码进行登录
- 如果用户已登录,直接返回用户已登录的信息,进行其他的操作就可以了
接下来就开始解决这些问题啦~
- 滑动页面元素,可以使用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)
- 当打开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()