APP UI自动化测试方法很多,本文主要讲述基于Appium+Python+Unittest的APP UI自动化测试环境搭建以及脚本写作指导,参考和总结了APP UI自动化测试学习过程中的相关知识,仅供大家参考。
1.1 JDK 安装
Java 环境分 JDK 和 JRE ,JDK 就是 Java Development Kit。简单的说 JDK 是面向开发人员使用的 SDK,它提供了 Java 的开发环境和运行环境。JRE 是 Java Runtime Enviroment 是指 Java 的运行环境,是面向 Java 程序的使用者。
1.1.1下载
1) 访问JDK官网:
2) 选择对应系统版本安装包下载
备注:下载需要登录Oracle账户
1.1.2 安装 双击安装包,点击next一步步安装,安装路径选择默认(最好安装在C盘),安装完成后在对应安装路径下可看到如下文件:
1.1.3 配置环境变量
1)新建JAVA_HOME系统变量
我的电脑->更多->属性->高级系统设置->环境变量:
在系统变量中点击新建,新建一个JAVA_HOME变量:
变量名:JAVA_HOME
变量值:JDK安装路径,如C:\Program Files\Java\jdk1.8.0_112
2)设置系统变量Path
选中系统变量Path,点击编辑,增加两个值:
%JAVA_HOME%\bin;
%JAVA_HOME%\jre\bin;
3) 测试安装是否成功
在cmd命令窗口中输入java -version,回显如下图所示说明JDK已经安装配置成功:
1.2 Android SDK安装
Android SDK(Software Development Kit,软件开发工具包)提供了 Android API 库和开发工具构建,测试和调试应用程序。简单来讲,Android SDK 可以看作用于开发和运行 Android 应用的一个软件。
1.2.1 通过Android Studio安装
1.2.1.1下载
1)访问Android SDK官网
developer.android.com/studio?hl=z…
2)下载Android Studio
1.2.1.2 安装
1)双击下载的exe文件,一路点击next
2)如果需要安装自带的模拟器,就把这一项勾选上,然后 Next(若是需要使用模拟器运行,建议勾选第二项)
3)选择安装目录:由于需要磁盘空间较大,建议安装目录选择非C盘
4)选择 SDK 的页面注意一下选择 Custom,这样可以只安装自己喜欢的部分,接下来选择主题,当然这个以后可以在 Android Studio 里边改。
1.2.1.3 配置环境变量
1)新增ANDROID_HOME变量
我的电脑->更多->属性->高级系统设置->环境变量:
在系统变量中点击新建,新建一个ANDROID_HOME变量
变量名:ANDROID_HOME
变量值:Android SDK安装路径
2)设置系统变量Path
选中系统变量Path,点击编辑,增加如下值:
%ANDROID_HOME%\platform-tools;
%ANDROID_HOME%\tools;
%ANDROID_HOME%\build-tools\29.0.3;
3)验证安装是否成功
在cmd命令窗口中输入adb –version,出现如下回显信息说明Android SDK安装成功:
在cmd命令窗口中输入aapt命令出现如下回显说明Android SDK安装成功:
1.2.2通过Android SDK安装包安装
下载Android SDK Tools:下载基本的Android命令行工具,可以使用包含的SDKManager下载其他的SDK软件包。
1.2.2.1下载
下载Android SDK Tools,翻过墙的朋友可以去Google Android的官网上下载developer.android.com/sdk/index.h… 不愿意翻墙的朋友,可以去这个网站下载www.androiddevtools.cn/
下面介绍一下在这个网站上下载的情况,首先打开www.androiddevtools.cn/ ,我们可以看到这里面有Android开发所需的各种工具,首先找到SDK Tools:
有exe和zip两种安装包,选择其中一种下载即可(建议下载zip安装包)。
1.2.2.2安装
下载好解压到某一个目录下(需要的磁盘空间达到几十G),进入SDK的解压目录下,双击“SDK Manager.exe”打开SDK管理器,就会出现下面android sdk manager窗口,Tools勾选Android SDK Platform-tools和Android SDK Build-tools对应版本(一般是最新版本)下载,API可以选择对应版本下载,Extras中Android Support Repository、Android SupportLibrary和Google USB Driver也可选择最新版本下载,如果时间和网速允许也可以全部下载。
l Tools目录下:
1)Android SDK Tools(必须,只需下载一个版本,一般选择最新版本):基础工具包
2)Android SDK Platform-tools(必须,只需下载一个版本,一般选择最新版本):从android2.3开始划出此目录,存放公用开发工具,比如adb、sqlite3等,被划分到了这里。
3)Android SDK Build-tools(必须,可以安装多个版本):Android项目构建工具
l Android xxx(API xx) 目录(可选的各平台开发工具):
SDK Platform(必须):对应平台的开发工具,需要在哪个版本的平台下开发就下载哪个。一般我们下载最新的,最新的兼容容以前的。
l Extras(可选的扩展)
1.2.2.3环境变量配置 环境变量配置参考1.2.1.3 环境变量配置
1.3 Python安装
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。在开发过程中没有了编译这个环节。Python 编辑器很多,推荐:PyCharm、Atom、Sublime text3 等。
1.3.1 下载
- Python官网下载地址:
- 选择最新版本下载:
1.3.2 安装 下载成功后双击安装包,启动安装,安装界面上选择Add to Path,即可自动添加到系统变量中,无需再手工添加。
1.3.3 配置环境变量 安装完成后,python安装路径的环境变量已经自动配置到系统变量Path中,如果没有,则需要手动添加到Path中。
打开cmd命令窗口,输入python,如果回显如下图所示,说明python安装配置成功。
1.4 Pycharm安装 PyCharm 是一种 Python IDE,其带有一整套可以帮助用户在使用 Python 语言开发时提高其效率的工具,比如, 调试、语法高亮、Project 管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外,该 IDE 提供了一些高级功能,以用于支持 Django 框架下的专业 Web 开发。
1.4.1下载 1) 官网下载地址
www.jetbrains.com/pycharm/dow…
2) 选择Community版本点击Download进行下载
1.4.2安装 双击安装包,点击【next】一步步安装即可。
1.5 Node.js安装
Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台,Node.js 是一个非阻塞、事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。
事件驱动:服务器只在用户那边有事件发生的时候才响应
非阻塞:Node.js 的应用是通过 javascript 开发的,然后直接在 Google 的变态 V8 引擎上跑。用了 Node.js,你就不用担心用户端的请求会在服务器里跑了一段能够造成阻塞的代码了。非阻塞的服务器想象成一个 loop 循环,这个 loop 会一直跑下去。一个新请求来了,这个 loop 就接了这个请求,把这个请求传给其他的进程(比如传给一个搞数据库查询的进程),然后响应一个回调(callback)。完事了这 loop 就接着跑,接其他的请求。这样下来。服务器就不会像之前那样傻等着数据库返回结果了。
1.5.1下载
1)官网下载地址:
2)下载本机对应的node.js版本
1.5.2 安装
下载完成后,双击.msi 文件,进行安装,一直点击【Next】即可(注意安装到非系统盘):
注意以下内容:
npm package manager 表示npm包管理器
online documentation shortcuts 在线文档快捷方式
Add to PATH 添加node安装路径到环境变量
1.5.3 配置环境变量
安装完成后,.msi格式的安装包已经将node.exe添加到系统环境变量path中,若没有,则需要自己手动添加(在系统变量—>path变量名—>“编辑”添加node的路径)。
在cmd命令窗口中输入node -v,回显如下即表示node.js安装成功:
1.5.4 npm
npm是node.js 的包管理工具,能解决 Node 代码部署上的很多问题;允许用户从npm服务器下载别人编写的第三方包到本地使用;允许用户从npm服务器下载并安装别人编写的命令行程序到本地使用;允许用户将自己编写的包或命令行程序上传到npm服务器供别人使用。
在cmd命令窗口中输入npm -v,回显如下即表示npm可正常使用:
1.6 Appium安装
appium参考手册:appium.io/docs/cn/abo…
Appium 是一个用 Node.js 写的、暴露 REST API 的 WEB 服务器。它接受来自客户端的连接,监听命令并在移动设备上执行,答复 HTTP 响应来描述执行结果。
Appium 是一个开源、跨平台(测试程序跨平台、支持多平台上的 app 测试)、多语言支持的(开发语言)移动应用自动化工具。
Appium可以安装桌面版本或服务版本。
桌面版本在APP UI自动测试过程中每次测试前用户需要预先手工启动Appium,再执行python脚本测试用例,测试完成再手动关闭Appium,但是桌面版本提供了Inspector方法用于获取APP界面的UI定位元素;服务版本可以通过appium命令启动,可以将启动和停止脚本内置在python中,自动化启动和停止Appium,但是服务版本无法通过界面的Inspector来获取UI元素定位信息。
1.6.1桌面版安装
1)Appium官网
2)下载最新版本安装包
3)双击下载的exe程序,一路【Next】安装即可
1.6.2服务版安装
1) 打开cmd窗口,执行npm install -g Appium
2) 安装appium doctor:cnpm install appium-doctor -g
3) 安装完成后,在cmd窗口执行appium,出现如下截图说明安装成功
4) 查看appium安装路径:
在cmd命令窗口输入:where appium
5) 查看appium版本号
在cmd命令窗口输入:appium -v
1.6.3安装Appium-Python-Client
通过cmd命令:pip install Appium-Python-Client安装。
安装后可以通过如下命令来检测是否安装成功:输入命令“python”—>“from appium import webdriver” 回车,如果控制台没有报错,则说明安装成功:
1.7 基于unittest框架开发测试用例
因为之前做接口自动化测试的时候用了unittest框架,所以APP UI自动化测试也延用了这个框架,这样测试报告、日志记录等功能可以直接复用,无需再重新开发。大家如果有自己使用的较为熟悉的测试框架,也可以不基于unittest框架进行用例测试,例如使用pytest测试框架等等。
1.7.1 工程目录 测试工程目录规划如下:
1.7.2 Appium界面元素定位方法
1) driver.find_element_by_id() #id定位
2) driver.find_element_by_name() #name定位(已经凉了,不支持)
3)driver.find_element_by_xpath() #xpath定位
3) find_element_by_class_name #class_name定位
4) driver.find_element_by_css_selector() #css定位
5) driver.find_element_by_link_text() #link定位
6) driver.find_element_by_tag_name() #tag定位
7) driver.find_element_by_partial_link_text() #partial定位
8) driver.find_element_by_accessibility_id() #accessibility_id定位
9) driver.find_element_by_android_uiautomator() #原生定位
常用的方法是id定位、name定位、xpath定位、classname定位以及accessibility_id定位、原生定位。
1.7.3 元素id等信息获取方法
获取元素的id、name、xpath等信息主要有两种方法:
1.7.3.1 Android SDK的tools中自带的UIAutomator
1.7.3.2 Appium自带的Insecptor方法
1) 点击Start Server启动桌面版Appium(界面信息按默认设置即可)
2) 点击Start Inspector Session
3) 按如下配置Desired Capabilities(请保证手机已通过USB连接到PC,通过adb devices可以查询到对应手机)
l platformName:手机的操作系统,ios或者Android
l platforVersion:Android系统版本,可以通过adb shell getprop ro.build.version.release查看
l deviceName:设备名称,可以通过adb devices -l中model查看
appPackage: 待测试APP包名称,可以通过如下方法获取
appActivity: apk的launcherActivity,通过命令adb shell dumpsys activity | findstr “mResume”查看(需先打开手机应用)
注意:Android 8.1之前应使用adb shell dumpsys activity | findstr “mFocus”
4) 点击Start Session:
5) 点击APP页面,在右侧Selected Element下可以看到该按键对应的元素信息
6) 点击Start Recording后,操作APP页面(选中某一按键,Tap代表点击,Send keys代表输入文本【适用于搜索等需要输入文本场景】,clear清空输入的文本),可以录制python脚本:
7) 录制的Python脚本
1.7.4 控件操作API 序号
API
方法描述
1
text(self)
获取控件显示的文本信息,常用于断言
2
tag_name(self)
获取控件的tag名称,需要在网页测试中使用
3
click(self)
点击控件
4
clear(self)
清空文本控件框的文本
5
is_enabled(self)
判断控件是否可用,可用的话,返回True
6
is_selected(self)
判断控件是否被选中,如果选中了,返回True
7
is_displayed(self)
判断控件是否显示,如果显示了,返回True
8
get_attribute(self,name)
获取控件的某个属性值,如:
e1.get_attribute(‘text’),获取控件的text信息
9
parent(self)
返回控件的父控件
10
send_keys(self,*keys)
在文本输入框中输入信息
11
screen_shot(self,filename)
截图
1.7.4 Unittest测试框架
1.7.4.1 简介
unittest框架最核心的四个概念:
1)test case:就是我们的测试用例,unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的实例就是一个测试用例;unittest中测试用例方法都是以test开头的,且执行顺序会按照方法名的ASCII值排序。
2)test fixure:测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建(SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。
3)test suite:测试套件,用来把需要一起执行的测试用例集中放到一块执行,相当于一个篮子。我们可以使用TestLoader来加载测试用例到测试套件中。
4)test runner:用来执行测试用例的,并返回测试用例的执行结果。它还可以用图形或者文本接口,把返回的测试结果更形象的展现出来,如:HTMLTestRunner。
1.7.4.2 断言
Unittest提供了自带的断言方式,主要有以下几种:
方法
检查
assertEqual(a, b,msg=None)
a==b
assertNotEqual(a, b)
a !=b
assertTrue(x)
bool(x) is True
assertFalse(x)
bool(x) is False
assertIs(a, b)
a is b
assertIsNot(a, b)
a is not b
assertIsNotNone(x)
x is not None
assertIn(a, b)
a in b
assertNotIn(a, b)
a not in b
assertIsInstance(a, b)
isinstance(a,b)
assertNotIsInstance(a, b)
not isinstance(a,b)
如果断言失败即不通过就会抛出一个AssertionError断言错误,成功则标识为通过,以上几种方式都有一个共同点,就是都有一个msg参数(表中只列了一个,其实都有),默认是None,即msg = None,如果指定msg参数的值,则将该信息作为失败的错误信息返回。
1.7.5 Python+Appium+Unittest脚本
- 自动启动/停止Appium
1)自动启动
l bat脚本:
@echo off
title startAppiumServer
cmd /c "appium -a 127.0.0.1 -p 4723"
l python调用bat脚本(bat脚本和python脚本文件放置在同一文件夹下)
try:
# 启动appium
os.system('start startAppiumServer.bat')
except Exception as msg:
print (msg)
raise
# 等待appium服务启动完毕
time.sleep(8)
2)自动停止
l bat脚本:
@echo off
title stopAppiumServer
tasklist /V|find "startAppiumServer">nul
if %errorlevel%==0 (
::关闭appium服务
taskkill /F /IM node.exe
taskkill /F /FI "WINDOWTITLE eq startAppiumServer"
)
taskkill /F /FI "WINDOWTITLE eq stopAppiumServer"
l python调用bat脚本(bat脚本和python脚本文件放置在同一文件夹下)
finally:
# 执行完毕测试用例关闭appium服务
os.system('start stopAppiumServer.bat')
- 启动待测APP
from appium import webdriver
class driver(object):
def __init__(self):
self.desired_caps = {}
self.desired_caps["platformName"] = "Android"
self.desired_caps["platformVersion"] = "10.0.0"
self.desired_caps["deviceName"] = "SPN_AL00"
self.desired_caps["appPackage"] = "cn.honor.qinxuan"
self.desired_caps["appActivity"] = ".MainActivity"
self.desired_caps["unicodeKeyboard"] = True
self.desired_caps["resetKeyboard"] = True
self.host = '127.0.0.1'
self.port = 4723
def getDriver(self):
url = 'http://%s:%s/wd/hub' % (self.host, str(self.port))
try:
# 启动APP
driver = webdriver.Remote('http://localhost:4723/wd/hub', self.desired_caps)
return driver
except Exception as msg:
print (msg)
raise
- Unittest测试用例
import unittest
import logging
import sys
sys.path.append(r"D:\ME\AutoTest\UITest\Common")
import driver
import method
import time
class TestALLPage(unittest.TestCase):
"""遍历点击测试用例"""
@classmethod
def setUpClass(cls):
# 所有用例执行前执行
print('所有用例执行开始前执行')
# 获取Driver
global dr
test = driver.driver()
dr = test.getDriver()
# 保证测试开始前APP位于首页
apphomepage = method.method(dr)
apphomepage.initialPage()
def setUp(self):
# 每条用例执行之前都会执行
print("用例{}开始执行--".format(self))
def tearDown(self):
# 每条用例执行之后都会执行
print("用例{}执行结束--".format(self))
@classmethod
def tearDownClass(cls):
print('所有用例执行后执行')
# 退出APP
dr.quit()
def test_alltest_001(self):
"""遍历点击"""
# 点击首页
e3 = dr.find_element_by_id('cn.honor.qinxuan:id/rb_home')
e3.click()
time.sleep(1)
# 点击首页广告图,进入广告图商详
e4 = dr.find_element_by_id('cn.honor.qinxuan:id/imageView')
e4.click()
time.sleep(1)
# 点击返回首页
e5 = dr.find_element_by_id('cn.honor.qinxuan:id/iv_qx_normal_back')
e5.click()
time.sleep(1)
# 点击全部商品
e6 = dr.find_element_by_id('cn.honor.qinxuan:id/rb_qinxuan')
e6.click()
time.sleep(1)
# 点击全部商品综合页签
e7 = dr.find_element_by_id('cn.honor.qinxuan:id/tv_sort_default')
e7.click()
time.sleep(1)
# 点击全部商品新品页签
e8 = dr.find_element_by_id('cn.honor.qinxuan:id/tv_sort_new')
e8.click()
time.sleep(1)
# 点击全部商品评价页签
e9 = dr.find_element_by_id('cn.honor.qinxuan:id/tv_sort_remark')
e9.click()
time.sleep(1)
# 点击全部商品价格页签
e10 = dr.find_element_by_id('cn.honor.qinxuan:id/tv_sort_price')
e10.click()
time.sleep(1)
# 点击全部商品价格排序
e11 = dr.find_element_by_id('cn.honor.qinxuan:id/iv_sort_price')
e11.click()
time.sleep(1)
- 执行用例,结果保存在报告中
import unittest
# 中文 Chinese
from HwTestReport import HTMLTestReport
# 英文 English
from HwTestReport import HTMLTestReportEN
import datetime
import time
import os
import logging
now_path = os.path.dirname(os.path.realpath(__file__)) # 获取当前路径
log_path = os.path.join(now_path, "../Logs") # LOG日志存储路径
class runTest(object):
def __init__(self):
pass
def run(self):
try:
# 启动appium
os.system('start startAppiumServer.bat')
except Exception as msg:
print(msg)
raise
# 等待appium服务启动完毕
time.sleep(8)
try:
# 指定测试用例路径
case_path = "../TestSet/TestCase"
# 创建测试套件(此时是个空的)
suite = unittest.TestSuite()
'''
用discover方法找出目录下要执行的测试用例脚本
.discover方法里面有3个参数:
case_dir:测试用例所在目录
pattern:匹配脚本名称的规则,例如test*.py是匹配所有以test开头的脚本
top_level_dir:顶级目录名称,一般默认为None
'''
discover = unittest.defaultTestLoader.discover(case_path, pattern='test_ALL.py', top_level_dir=None)
# 将discover筛出来的用例循环添加到测试套件中
for casefile in discover:
for case in casefile:
suite.addTest(case)
# 测试报告
nowtime = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
dir = '../report/' + 'HtmlTestReport' + '_' + str(nowtime) + '.html'
report = open(dir, 'wb+')
runner = HTMLTestReport(stream=report,
verbosity=2,
title='荣耀亲选appUI自动化测试报告',
description='荣耀亲选APP UI自动化测试测试报告',
tester='Zhan Cuiping')
# LOG日志记录
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename=log_path + '/' + nowtime + r"result.log",
filemode='w')
logger = logging.getLogger()
logger.info(suite)
# 开始执行测试集
runner.run(suite)
report.close()
# 邮件发送测试报告
time.sleep(2)
except Exception as msg:
print(msg)
raise
finally:
# 执行完毕测试用例关闭appium服务
os.system('start stopAppiumServer.bat')
if __name__ == '__main__':
try:
runuitest = runTest()
runuitest.run()
except:
print("运行失败")
raise
1.8 FAQ
- 通过python的os.system执行bat脚本提示appium不是内部或外部命令 Python执行os.system('start startAppiumServer.bat')提示appium不是内部/外部命令(直接双击.bat脚本执行没有该提示)
将appium安装路径的
C:\Users\XXX\AppData\Roaming\npm\node_modules\appium\node_modules.bin加入系统变量Path中,通过python执行仍然提示appium不是内部或外部命令
重启电脑后解决
- 误删除Path系统变量恢复方法 l 电脑未重启
->win+R,在弹出窗口中输入regedit命令并回车
->在打开的注册表中,进入
\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager\Environment
备注:执行npm命令如果提示npm不是有效的命令,则需要安装Node.js(安装参考:www.runoob.com/nodejs/node…
->双击Path,复制其数值数据
->我的电脑->属性->高级系统设置->环境变量->系统变量,点击新建,变量名命名为Path,变量值粘贴之前复制的数值数据,保存即可。
l 电脑已重启:
复制别人的Path值或原来备份的Path,原来安装程序时手动添加的Path值也需要自行添加回来
Path值备份:
C:\ProgramData\Oracle\Java\javapath;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0;%SYSTEMROOT%\System32\OpenSSH;C:\Program Files\TortoiseSVN\bin;%android%;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;%ANDROID_HOME%\build-tools\29.0.3;%GRADLE_HOME%\bin;C:\Program Files\Git\cmd;C:\Program Files\nodejs;C:\Users\XXX\AppData\Roaming\npm\node_modules\appium\node_modules.bin;
- 安装Appium,cnpm命令执行提示cnpm不是有效的内部或外部命令 安装 appium,执行:cnpm install -g appium,命令后出现:cnpm 不是内部或外部命令,也不是可运行的程序,见下图:
解决:
没有 cnpm 包,需要先安装 cnpm:命令行输入:npm install -g cnpm,出现下图为安装成功
Could not find a connected Android device 测试过程中启动Appium提示Could not find a connected Android device:
可能原因:
1) 手机未连接 —— 连接手机,打开USB调试模式
2) 手机已连接,USB调试模式未打开 —— 在开发者模式中打开USB调试模式,在cmd命令窗口中执行adb devices,如果回显中有终端设备,说明连接无问题
3) 也可能是adb进程被占用了,在任务管理器中将结束adb进程后再执行程序
stackoverflow.com/questions/6…
I had the same problem. Try the following:
- Go to Appium Server GUI -> Advanced
Server address: localhost
Port: 4723
Allow CORP: yes - Go to Appium Inspector
Remote host: localhost
Port: 4723
Path: /wd/hub - Allow Unauthorized Certificates
- Select your capabilities
- Start server