第二章 基于
Python
语言的
Appium
使用
一、
Appium
环境搭建
1
基础环境
与
Java
版一致。
2 Python+Appium
环境
在基础环境上继续安装。
安装
python
用于编写脚本
安装
Appium Python Client
Appium Client
是对
webdriver
原生
api
的一些扩展和封装。它可以帮助我们更容
易的写出用例,写出更好懂的用例。
Appium Client
是配合原生的
webdriver
来使
用的,因此二者必须配合使用缺一不可。
pip install Appium-Python-Client
二、 编写自动化测试脚本
1
导入包
from appium import webdriver
2
设置
desired_capabilities
2.1
创建字典
device={}
名称并非关键字,自行命名
2.2
指定设备信息
device['deviceName']='192.168.120.102:5555'
指定移动设备或模拟器的种类,如
iPhone Simulator
,
iPad Simulator
,
iPhone
Retina 4-inch
,
Android Emulator
,
Galaxy S4
等
device['platformName']='Android'
指定移动操作系统平台,如
iOS
,
Android
或
FirefoxOS
device['platformVersion']='9'
指定移动操作系统版本
device['appPackage']='com.android.calculator2'
指定
app
程序包名
device['appActivity']=' com.android.calculator2.Calculator'
指定启动页的名字。
2.3
启动
app
driver=webdriver.Remote("http://localhost:4723/wd/hub",device)
#
启动
app
2.6
关闭
App
driver.quit()
3
编写测试脚本
Appium
保存能力
{
"platformName": "Android",
"deviceName": "192.168.120.102:5555",
"platformVersion": "9",
"appPackage": "com.android.calculator2",
#com.android.quicksearchbox
"appActivity": ".Calculator"
#com.android.quicksearchbox.SearchActivity
}
点击元素
driver.find_element_by_id("com.android.calculator2:id/digit_9").click()
driver.find_element_by_id("com.android.calculator2:id/op_add").click()
driver.find_element_by_id("com.android.calculator2:id/digit_1").click()
driver.find_element_by_id("com.android.calculator2:id/eq").click()
回车
driver.press_keycode(66)
指定每次运行测试前不重新安装
App
device['noReset']=True
键盘输入数据
driver.find_element_by_id("android.widget.EditText").send_keys("
数据
")
指定
App
中可以输入中文
device['unicodeKeyboard']= True
device['resetKeyboard']=True
driver.find_element_by_id("android.widget.EditText").send_keys(u"
中文
")
4
断言
res=driver.find_element_by_class_name("android.widget.EditText").text
if res==str(7):
print("
测试通过
")
else:
print("
测试失败
")
5
参数化
使用列表
data=[
['123','+','45','168'],
['23','-','6','17'],
['6','*','8','48']
]
将运算符修改为可识别字符串
for i in range(len(data)):
if data[i][1]=='+':
data[i][1]='add'
elif data[i][1]=='-':
data[i][1]='sub'
elif data[i][1]=='*':
data[i][1]='mul'
else:
data[i][1]='div'
for
循环分离每个数据后参数替换
for i in data:
for j in range(0,len(i)-1):
x=i[j]
if j!=1:
for a in x:
driver.find_element_by_id("com.android.calculator2:id/digit_"+a).click()
else:
driver.find_element_by_id("com.android.calculator2:id/op_"+i[1]).click()
driver.find_element_by_id("com.android.calculator2:id/eq").click()
jg=driver.find_element_by_id("com.android.calculator2:id/result").text
sleep(3)
if jg==i[3]:
print("
测试通过
")
else:
print("
测试失败
")
读
txt
文件
file=open(
文件名,
'r')
返回文件对象,文本默认编码方式是
UTF-8
。
'r'
表示只是读,默认项。
遍历文件
for
变量
in file
按行读出,处理后可存入列表。
关闭文件
file.close( )
释放文件占用的系统资源。
读
excel
文件
安装
pandas
pip install --no-index --find-links=
包位置
-r requirements.txt
requirements.txt
中记录着所有需要的依赖包和版本号
验证是否成功
python
→
import pandas
pip list
导入包
import pandas
获得数据
data=pandas.read_excel("xls
文 件 名
",sheet_name=sheet
表 编 号 或 名
称
,names=[
新列名列表
],dtype={"
新列名
":
类型
},skiprows=
跳过数据行的行
数
,header=None
表示没有列名
)
默认认为包含列名
表编号从
0
开始
新列名列表中的列名要加引号
获得全部数据,结果为
DataFrame
(字典,列名为关键字)
datalist=data.values.tolist()
返回列表
三、
unittest
测试框架
1
导入包
from appium import webdriver
from time import sleep
import unittest
2
创建全局变量
driver=None
放在类之外
3
创建类
3.1
创建测试类
class
类名
(unittest.TestCase):
括号内表示继承,不能省略
3.2
创建初始化和还原环境的函数
这些函数需要放在类中。
@classmethod
def setUpClass(cls):
cls
不能省略
所有测试函数运行前运行一次
driver
需要声明为全局变量
device={}
device['deviceName']='192.168.120.102:5555'
device['platformName']='Android'
device['platformVersion']='9'
device['noReset']=True
device['appPackage']='com.android.quicksearchbox'
device['appActivity']='com.android.quicksearchbox.SearchActivity'
device['unicodeKeyboard']= True
device['resetKeyboard']=True
global driver
driver=webdriver.Remote("http://localhost:4723/wd/hub",device)
@classmethod
def tearDownClass(cls):
cls
不能省略
所有测试函数运行完后运行一次
3.3
测试函数
def
函数名
(self):
u'''
测试描述
'''
global driver
其他测试代码
函数名必须以
test
开头
self
不能省略
u"""
测试描述
"""
可以省略,省略时显示函数名
多个测试函数按照函数名的
ASCII
顺序执行
3.4
运行测试
if __name__ == "__main__":
unittest.main(verbosity=2)
上述代码放在模块内,类之外
表示当单独运行模块时才会被执行,
import
到其他脚本中是不会被执行
verbosity=2
表示显示每个用例的详细信息,可以省略,但测试结果不详细
测试结果
.
:代表测试通过。
F
:代表测试失败,
F
代表
failure
。
E
:代表测试出错,
E
代表
error
。
s
:代表跳过该测试,
s
代表
skip
。
4
断言
4.1 assert
断言
assert str1 in str2
,断言失败时的消息文本
assert
表达式
1==
表达式
2
self.assertIn(str1,str2)
断言
str1
是否在
str2
中
self.assertEqual(
实际,预期
)
4.2 WebApp
中的断言
获得网页返回结果
/
所有页面元素
driver.page_source
5
参数化
5.1
安装
nose_parameterized
pip install …
5.2
导入包
parameterized
包名不是
nose_parameterized
import parameterized
5.3
定义参数数据
data=[
[
数据
11
,数据
12 ] ,
[
数据
21
,数据
22 ]
]
参数放在列表中
5.4
引用参数
@parameterized.parameterized.expand(data)
def test…(self ,
参数
1,
参数
2, …):
self
不能省略
参数的个数应与列表中的个数一致
可以实现局部迭代
6
测试报告
最好创建运行测试套件的单独的模块
导入包
import HTMLTestRunner
可以自行修改此文件
创建测试套件
suite=unittest.TestSuite()
tests=unittest.defaultTestLoader.discover("
测 试 模 块 所 在 目 录
",
pattern='test_*.py')
suite.addTests(tests)
运行测试,保存报告
now = time.strftime("%Y%m%d %H%M%S",time.localtime())
获取当前时间并设置时间格式
reportFile="./"+now+"_result.html"
测试报告的存放路径及文件名,文件名中加了当前时间以便每次生成不同
的测试报告
fp=open(reportFile,'wb')
runner=HTMLTestRunner.HTMLTestRunner(stream=fp, title=u'
报告标题功能测
试报告
', description=u'
报告的说明与描述
', tester=u'
测试员姓名
')
runner.run(suite)
fp.close()
关闭文件流,不关的话生成的报告是空的
放在最后,在
run
之后
四、 安装
apk
并测试
1
安装
Genymotion-ARM-Translation
Genymotion
是一款基于
x86
架构的
Android
模拟器,而大部分应用是
arm
架构,所以
两者不兼容。
对于
x86
的真机,
X86
处理器已经能够基本兼容
ARM
了指令。
对于
Genymotion
模拟器,则通过安装
Genymotion-ARM-Translation
来进行兼容。
genymotion
使用
Genymotion-ARM-Translation.zip
文件是不通用的,每个
Android
版本
对应
ARM
指令集的版本也是不一样。
将文件复制到模拟器
adb push Genymotion_ARM_Translation.zip /sdcard/Download
将
Genymotion-ARM-Translation.zip
继续拖动到模拟器中
重启模拟器
adb reboot
如果拖动没安装成功,可以使用下面的命令安装
adb shell
cd /sdcard/Download/
sh /system/bin/flash-archive.sh /sdcard/Download/Genymotion_ARM_Translatio
n.zip
2
安装
apk
命令
adb install .apk
文件
鼠标拖动
3
切换
Activity
driver.wait_activity("activity
名称
",
超时时间
)
4
操作弹窗
toast=('xpath','//*[contains(@text,"ALLOW")]')
查找
xpath
路径,标记任意,
text
属性中包括
ALLOW
id
有时候会发生变化
t=WebDriverWait(driver,10,0.1).until(expected_conditions.presence_of_element_located(toa
st))
寻找指定的
toast
元素
最大超时时间
10s
,默认
30s
,间隔查询时间
0.1s
,默认
0.5s
查询一次
需要导入包、
from selenium.webdriver.support.ui import WebDriverWait
等待模块
from selenium.webdriver.support import expected_conditions
判断模块
t.click()
单击找到的元素
5
滑屏
获得屏幕大小
/
屏幕分辨率
width=driver.get_window_size()['width']
height=driver.get_window_size()['height']
向上划屏
for i in range(1,7):
driver.swipe(width/2,height*3/4,width/2,height/4,1000)
向上滑,每次间隔
1000ms
6
判断是否出现指定窗口
if driver.current_activity()=='activity
名称
'
driver.current_activity()
获得当前
activity
名称
适当提前延时
if driver.wait_activity("activity
名称
",
超时时间
)
返回值
窗口存在是返回
True
7
补充问题
device['autoLaunch'] = False
有时不想让
appium
每次都启动
app
,而是想自己打开
activity
或者在原来
activity
基础上继续操作,可以使用此项
但
device['appPackage']='com.tencent.mm'
和
device['appActivity']='com. tencent.mm.ui.
LauncherUI'
仍然不能省略
启动
App
driver.launch_app()
关闭
App
driver.close_app()
重置
App
driver.reset()
清除设置以后启动或重启
App
自己启动
activity
driver.start_activity('com.tencent.mm','com.tencent.mm.ui.LauncherUI')
在原有
activity
上继续操作
一般不需要切换窗口
查看所有的
App
类型
/
上下文
driver.contexts
查看当前的
App
类型
/
上下文
driver.context
driver.current_context
切换
App
类型
/
上下文
driver.switch_to.context("WEBVIEW_com
…
")