文章目录
appium
第一节课 appium原理与环境搭建+元素定位简介
1.安装代码工具包
appium python client
2.安装appium server desktop(建议1.13版本)
从云盘目录下载(最快)
或者从官网下载:https://github.com/appium/appium-desktop/releases?after=v1.17.1-1
3.安装JDK 1.8版本
注意:安装路径不要有中文和空格
将JDK所在目录添加到系统环境变量
变量名JAVA_HOME 变量值:jdk所在的根目录
然后添加%JAVA_HOME%\bin 到环境变量PATH
环境变量设置后,重新启动相关工具才会生效
4.下载安卓SDK
下载云盘上的SDK压缩包(选择对应操作系统版本),解压到本地硬盘
进入到对应的SDK目录,并将该目录添加到系统环境变量 ANDROID_HOME
pip install appium-python-client
5.手机端配置
确保电脑的USB端口能够识别手机,(电脑可以安装对应手机的USB驱动) win10自动可以识别
确保电脑上面不要装带有adb工具的应用(XX管家,X大师,手机助手之类等 ,同样国产杀毒软件也不
建议安装)
USB最好是原装
开启USB调试功能
Ø用usb线连接到电脑,一头连手机,一头连电脑
Ø进入手机设置->关于手机
Ø不断点击版本号,直到激活开发者模式
Ø退出到上级菜单,在开发者模式中,启动usb调试
Ø手机端设置USB连接为MTP媒体传输模式或文件传送模式(不要使用仅充电)
Ø确认授权电脑端调试
appium工作原理深入
弄清这一行代码发生了什么?
webdriver.Remote(‘http://localhost:4723/wd/hub’,desired_caps)
1.客户端代码与appiumserver建立连接-session,并传递caps配置信息
2.Appiumserver检查配置信息是否符合要求
3.利用adb工具检查当前连接的移动设备
4.安装appium-settings与uiautomator2到被测手机(首次运行脚本发生)
5.手机启动appium-settings作为监听服务,用于和appium-server进行通信
6.uiautomator2启动被测app (代码指定了底层驱动为UI2)
配置项信息官方:
http://appium.io/docs/en/writing-running-appium/caps/#uiautomator2-only
adb无线连接
1. USB连接手机 确保adb可以正常连接
C:\Users\Shone>adb devices
List of devices attached
882QAEU99J9HU device
2. 激活adb服务
# adb tcpip 端口号(建议默认用5555)
C:\Users\Shone>adb tcpip 5555
restarting in TCP mode port: 5555
提示端口号后可以拔线了
3. 通过手机局域网IP连接手机
# adb connect devicesip:port(如果port是5555可以省略)
C:\Users\Shone>adb connect 192.168.0.103
already connected to 192.168.0.103:5555
4. 检查是否连接上
C:\Users\Shone>adb devices -l
List of devices attached
192.168.0.103:5555 device product:meizu_16th_CN model:16th device:16th transport_id:3
注意:某些手机()拔线之后会断开adb无线服务,因此不能实现真正的无线连接
第二节课 appium元素定位+设备信息
自动化配置信息
UiAutomator1(案例拉勾网)
#导包
from appium import webdriver
#准备自动化配置信息
desired_caps={
#移动设备平台
'platformName':'Android',
#平台OS版本号
'plathformVersion':'8',
#设备的名称--值可以随便写
'deviceName':'test0106',
#提供被测app的信息-包名,入口信息
'appPackage':'com.alpha.lagouapk',
'appActivity':'.HelloActivity',
#确保自动化之后不重置app
'noReset':True,
#设置session的超时时间,单位秒
'newCommandTimeout':6000,
#更换底层驱动
'automationName':'UiAutomator1',
'unicodeKeyboard':True,#修改手机的输入法,UI2不需要设置
'resetKeyboard':True#自动化结束之后将输入法还原-概率性
}
#初始化driver对象-用于控制手机
driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)
driver.implicitly_wait(10)#稳定元素
#点击输入框
driver.find_element_by_id('com.alpha.lagouapk:id/search_tab_txt').click()
#操作输入框-输入职位信息
driver.find_element_by_id('com.alpha.lagouapk:id/result_Search').send_keys('软件测试')
#点击第一个搜索结果
res=driver.find_elements_by_id('com.alpha.lagouapk:id/tv_suggest_key')
res[0].click()
# 查看结果
jobs=driver.find_elements_by_id('com.alpha.lagouapk:id/position_card_content_layout')
for job in jobs:
job_name= job.find_element_by_id('com.alpha.lagouapk:id/position_name').text
job_salary = job.find_element_by_id('com.alpha.lagouapk:id/position_card_salary').text
job_company = job.find_element_by_id('com.alpha.lagouapk:id/position_card_company_name').text
print(f'{job_name}|{job_salary}|{job_company}')
# input('......')
driver.quit()
UiAutomator2(案例boss直聘)
#导包
import time
from appium import webdriver
#准备自动化配置信息
desired_caps={
#移动设备平台
'platformName':'Android',
#平台OS版本号,写整数位即可
'plathformVersion':'8',
#设备的名称--值可以随便写
'deviceName':'test0106',
#提供被测app的信息-包名,入口信息:
#1.打开被测app,2.命令行输入以下信息
#adb shell dumpsys activity recents | findstr intent={
'appPackage':'com.hpbr.bosszhipin',
'appActivity':'.module.launcher.WelcomeActivity',
#确保自动化之后不重置app
'noReset':True,
#设置session的超时时间,单位秒,默认60s
'newCommandTimeout':6000,
#设置底层测试驱动-1.15默认使用的底层驱动就是UiAutomator2
'automationName':'UiAutomator2',#或者UiAutomator1
#'skipServerInstallation':True#跳过UI2的安装,如果第一次运行程序,不要添加该配置
} #加入这个命令的前提是,你的手机已经安装过UI2,因为第一次安装完毕后,反复执行驱动会重复进行安装,加入这个命令的意义就是避免重复安装
#初始化driver对象-用于控制手机-启动被测应用
#IP-appium-server所在机器的网络ip,port-监听的端口号,path固定/wd/hub
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
driver.implicitly_wait(10)#稳定元素
#点击放大镜
eles=driver.find_elements_by_id('com.hpbr.bosszhipin:id/img_icon')#先取所有符合条件的元素
#找到第二个元素--放大镜
btn=eles[1]
btn.click()
#搜索框输入职位信息
search_input=driver.find_element_by_id('com.hpbr.bosszhipin:id/et_search')
search_input.send_keys('软件测试')#输入参数
time.sleep(2)#等待关键字输入完毕
#模拟直接输入enter
driver.keyevent(66)
#选择符合条件的第一个搜索结果
# driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_filtered_name').click()
#获取当前页面所有职位信息元素
job_msg=driver.find_elements_by_id('com.hpbr.bosszhipin:id/view_job_card')
for job in job_msg:
#输出岗位名称
name=job.find_element_by_id('com.hpbr.bosszhipin:id/tv_position_name')
# print(name.text)
#输出薪资
salray=job.find_element_by_id('com.hpbr.bosszhipin:id/tv_salary_statue')
# print(salray.text)
#输出公司名称
company=job.find_element_by_id('com.hpbr.bosszhipin:id/tv_company_name')
print('%s|%s|%s'%(name.text,salray.text,company.text))
# input('......')
driver.quit()
封装配置信息+结合xpath定位元素
配置信息
'''
@author: haiwen
@date: 2020/11/11
@file: conf.py
'''
#准备自动化配置信息
desired_caps={
#移动设备平台
'platformName':'Android',
#平台OS版本号,写整数位即可
'plathformVersion':'8',
#设备的名称--值可以随便写
'deviceName':'test0106',
#提供被测app的信息-包名,入口信息:
#1.打开被测app,2.命令行输入以下信息
#adb shell dumpsys activity recents | findstr intent={
'appPackage':'com.hpbr.bosszhipin',
'appActivity':'.module.launcher.WelcomeActivity',
#确保自动化之后不重置app
'noReset':True,
#设置session的超时时间,单位秒,默认60s
'newCommandTimeout':6000,
#设置底层测试驱动-1.15默认使用的底层驱动就是UiAutomator2
'automationName':'UiAutomator2',#或者UiAutomator1
#'skipServerInstallation':True#跳过UI2的安装,如果第一次运行程序,不要添加该配置
}
案例boss直聘,结合xpath和id进行元素定位
'''
@author: haiwen
@date: 2020/11/11
@file: auto_boss1111.py
'''
#注意包名,项目名不要有同名--appium
from appium import webdriver
from conf import desired_caps
#启动session打开被测app
driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
driver.implicitly_wait(15) #防止代码速度超过界面响应速度导致的找不到元素
#1.点击放大镜
# eles=driver.find_elements_by_id('com.hpbr.bosszhipin:id/img_icon')
#第二个元素是放大镜
# eles[1].click()
#1.1通过xpath一次性定位到放大镜
driver.find_element_by_xpath('//*[@resource-id="com.hpbr.bosszhipin:id/ly_menu"]/*[2]').click()
#同样可以把下表2改成last()表示最后一个元素增加表达式的容错性
# 最后一个元素可以使用[last()]来表示
#2.输入职位信息
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_search').send_keys('自动化测试')
#.\n字符通常在PC系统中可以转化为回车或换行,但是在移动手机系统中通常不可以
#3.选择第一个候选信息
driver.find_element_by_id('com.hpbr.bosszhipin:id/rl_words').click()
#4.输出岗位信息:
job_cards=driver.find_elements_by_id('com.hpbr.bosszhipin:id/boss_job_card_view')
for job in job_cards:
postion=job.find_element_by_id('com.hpbr.bosszhipin:id/tv_position_name').text
salary=job.find_element_by_id('com.hpbr.bosszhipin:id/tv_salary_statue').text
company=job.find_element_by_id('com.hpbr.bosszhipin:id/tv_company_name').text
#可以自定义获取其他信息
print(f'薪资{salary}:岗位:{postion}:公司:{company}')
#选择第一个搜索结果,点击进入详情,
driver.find_element_by_id('com.hpbr.bosszhipin:id/view_job_card').click()
#获取职位名称下面的信息:地区、工作年限、学历
location=driver.find_element_by_xpath('//*[@resource-id="com.hpbr.bosszhipin:id/tv_required_location"]').text
degree=driver.find_element_by_xpath('//*[@resource-id="com.hpbr.bosszhipin:id/tv_required_degree"]').text
experence=driver.find_element_by_xpath('//*[@resource-id="com.hpbr.bosszhipin:id/tv_required_work_exp"]').text
print(f'工作地区:{location},年限{experence},学历:{degree}')
#退出
driver.quit()
app中的xpath定位注意点
在Appium中,我们没法使用css,因为css是 web 专用的
与web不同,底层测试驱动并不识别XPATH
Appium负责解析xpath给底层测试驱动来识别
每个节点名对应元素的class属性
对于一些比较复杂的元素的定位,我们可以用它定位
driver.find_element_by_xpath('//ele1/ele2[@attr="a1"]')
在app中,用class属性来代替元素标签名
如:
//android.view.ViewGroup
第三节课 手机界面操作+结合pytest实现代码封装与优化
界面操作
点击–对元素的操作
滑动
输入
双击
长按
截屏
放大
拖动
分解后的动作有:
点击(坐标点击)
场景:无法定位到目标元素,采取的一种候补方法
缺点:不是针对元素的操作,必须等目标界面出现才能有对应的交互效果(相当于瞎子点屏幕),不同
分辨率的屏幕会导致误差。
可以通过屏幕尺寸比例减小不同屏幕之间的误差(具体看代码)
driver.tap([(pos_x,pos_y)])
#导包
import time
from appium import webdriver
#准备自动化配置信息
desired_caps={
#移动设备平台
'platformName':'Android',
#平台OS版本号
'plathformVersion':'8',
#设备的名称--值可以随便写
'deviceName':'test0106',
#提供被测app的信息-包名,入口信息
'appPackage':'com.renaissance.bingzhe',
'appActivity':'.UnityPlayerActivity',
#确保自动化之后不重置app
'noReset':True,
#设置session的超时时间,单位秒
'newCommandTimeout':6000,
#指定自动化驱动
'automationName':'UiAutomator2',
}
#初始化driver对象-用于控制手机
driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)
driver.implicitly_wait(10)
time.sleep(20)
#通过坐标模拟点击某个控件
# driver.tap([(872,64)])
#写死的坐标做成屏幕的相对位置--解决不同的屏幕误差的问题
win_size=driver.get_window_size()#屏幕的尺寸
width=win_size['width']
height=win_size['height']
pos_y=height/32
pos_x=width/7*5.5
print(pos_x,pos_y)
driver.tap([(pos_x,pos_y)])
input('输入任意键退出代码')
driver.quit()
长按
场景:很多,如长按桌面壁纸可以调出设置屏幕功能
driver.tap([(500,800)],3000)
import time
from appium import webdriver
from config import desktop_caps
driver=webdriver.Remote('http://localhost:4723/wd/hub',desktop_caps)
#等待5秒种
time.sleep(5)
#使用屏幕操作,长按屏幕3秒(比如手机主界面,长按后可以拖动图标)
#500,800为坐标
driver.tap([(500,800)],3000)
input('输入任意字符结束')
driver.quit()
滑动
场景:边滑动边查找信息
driver.swipe(start_x,start_y,end_x,end_y,500)
import time
from config import boos_caps
from appium import webdriver
#初始化driver对象-用于控制手机
driver=webdriver.Remote('http://localhost:4723/wd/hub',boos_caps)
driver.implicitly_wait(10)#稳定元素
#边滑动边获取信息--向上滑动
width=driver.get_window_size()['width']
height=driver.get_window_size()['height']
start_x=width/2
start_y=height/2
end_x=start_x #向上滑动 x不变
end_y=start_y-500
#注意滑动坐标不要超出屏幕
time.sleep(5)
#寻找工作岗位--后台开发
def search_job(job_name):
while True:
#先找目标元素:
name=driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_position_name').text
#判断是否为目标元素--判断岗位信息是否正确
if job_name in name:
print('找到了目标岗位')
salary=driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_salary_statue').text
print(f'薪资是:{salary}')
break
# 滑动
driver.swipe(start_x,start_y,end_x,end_y,500)
截屏
#截屏
driver.save_screenshot('boss.png')
打开通知
#打开通知栏
#方式1:driver.swipe() ,起点坐标设置为屏幕的上边缘
#方式2:直接调用方法
driver.open_notifications()
time.sleep(3)
#关闭通知栏
#方式1:driver.swipe() 模拟向上滑动
#方式2:调用返回键--模拟键盘信号
模拟键盘信号
driver.keyevent(4)
#driver.press_keycode() 同上
对应的键盘信号可以通过百度 Android keycode
滑动,截图,打开通知,模拟键盘信号代码结合
'''
@author: haiwen
@date: 2020/9/16
@file: swipe.py
'''
import time
from config import boos_caps
from appium import webdriver
#初始化driver对象-用于控制手机
driver=webdriver.Remote('http://localhost:4723/wd/hub',boos_caps)
driver.implicitly_wait(10)#稳定元素
#边滑动边获取信息--向上滑动
width=driver.get_window_size()['width']
height=driver.get_window_size()['height']
start_x=width/2
start_y=height/2
end_x=start_x #向上滑动 x不变
end_y=start_y-500
#注意滑动坐标不要超出屏幕
time.sleep(5)
#寻找工作岗位--后台开发
def search_job(job_name):
while True:
#先找目标元素:
name=driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_position_name').text
#判断是否为目标元素--判断岗位信息是否正确
if job_name in name:
print('找到了目标岗位')
salary=driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_salary_statue').text
print(f'薪资是:{salary}')
break
driver.swipe(start_x,start_y,end_x,end_y,500)
# search_job('Python开发')
#截屏
driver.save_screenshot('boss.png')
#打开通知栏
#方式1:driver.swipe() ,起点坐标设置为屏幕的上边缘
#方式2:直接调用方法
driver.open_notifications()
time.sleep(3)
#关闭通知栏
#方式1:driver.swipe() 模拟向上滑动
#方式2:调用返回键--模拟键盘信号
driver.keyevent(4)
#driver.press_keycode() 同上
time.sleep(5)
driver.quit()
代码部分
boss直聘修改密码代码优化
import time
from config import boos_caps
from appium import webdriver
#启动被测app
def start_app():
global driver
driver=webdriver.Remote('http://localhost:4723/wd/hub',boos_caps)
driver.implicitly_wait(10)#稳定元素
#修改密码
def change_psw(old_psw,new_psw):
# 1.进入我的标签
driver.find_element_by_id('com.hpbr.bosszhipin:id/cl_tab_4').click()
# 2.点击右上角设置图标
driver.find_element_by_id('com.hpbr.bosszhipin:id/iv_general_settings').click()
# 3.进入账号与绑定
driver.find_element_by_id('com.hpbr.bosszhipin:id/cl_item').click()
# 4.进入设置密码
driver.find_element_by_xpath('//*[@text="修改密码"]').click()
time.sleep(2)
# print(driver.page_source)#当元素定位工具无法查看元素时候,可以通过该方法查看xml信息-根据元素特征进行定位-对大家要求比较高-会看xml信息
# 5.完成密码设置
#5.1输入旧密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_old').send_keys(old_psw)
#5.2输入新密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_new').send_keys(new_psw)
#5.4输入确认密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_new_confirm').send_keys(new_psw)
#5.5点击确定
driver.find_element_by_id('com.hpbr.bosszhipin:id/btn_save').click()
def end_app():
#结束session
driver.quit()
测试框架–pytest
#安装:pip install pytest
#使用:pytest 测试用例文件 -s
#案例:
#等同于setup的功能,不同的是比setup功能更强,可以为用例定制初始化和清除步骤
@pytest.fixture()
def before_test():
print('执行初始化动作')
start_app()
yield #后面跟的是清除动作,暂时理解为关键字 #后面可以跟常量或者变量,如果没有跟任何的值,可以作为 return
after_test()
#清除动作
def after_test():
print('执行清除动作')
end_app()
#测试用例--fixtrue需要显示引用
def test_modify_psw(before_test):
change_psw('boss666','boss123')
if __name__ == '__main__':
# 生成测试报告
pytest.main(['test_boss.py','-s','--alluredir=tmp/report'])
# 使用服务打开测试报告
os.system('allure serve tmp/report')
测试报告–allure
#安装allure命令行工具
#1.下载 https://github.com/allure-framework/allure2/releases
#2.解压缩文件,并添加环境变量
#安装pytest-allure插件
pip install allure-pytest
测试报告生成-allure
#生成报告缓存文件
pytest --alluredir=tmp/my_allure_results
#打开测试报告
allure serve tmp/my_allure_results
第四节课 案例分析(yaml)+多设备
yaml案例:
每次执行新密码替换旧密码,就不需要频繁变更密码,前提是app没有做历史密码的限制
1、yaml文件 — psw.yml
new: boss666
old: boss123
2、读取yaml,写入yaml — yml.conf.py
import yaml
#读yaml
def read_conf(path='psw.yml'):
with open(path,encoding='utf-8') as f:
content=f.read()
#转化成python能识别的格式
data=yaml.safe_load(content)
return data
#写yaml
def write_conf(data,path='psw.yml'):
with open(path,'w',encoding='utf-8',) as f:
#将python格式转化成yml格式
content=yaml.safe_dump(data)
f.write(content)
if __name__ == '__main__':
print(read_conf())
write_conf({'old': 'boss666', 'new': 'boss123'})
print(read_conf())
3、配置文件 — app.conf.py
#准备自动化配置信息
boss_caps={
#移动设备平台
'platformName':'Android',
#平台OS版本号,写整数位即可
'plathformVersion':'8',
#设备的名称--值可以随便写
'deviceName':'test0106',
#提供被测app的信息-包名,入口信息:
#1.打开被测app,2.命令行输入以下信息
#adb shell dumpsys activity recents | findstr intent={
'appPackage':'com.hpbr.bosszhipin',
'appActivity':'.module.launcher.WelcomeActivity',
#确保自动化之后不重置app
'noReset':True,
#设置session的超时时间,单位秒,默认60s
'newCommandTimeout':6000,
#设置底层测试驱动-1.15默认使用的底层驱动就是UiAutomator2
'automationName':'UiAutomator2',#或者UiAutomator1
#'skipServerInstallation':True#跳过UI2的安装,如果第一次运行程序,不要添加该配置
}
4、页面操作代码 — auto_boss1115.py
'''
@author: haiwen
@date: 2020/11/15
@file: auto_boss1115.py
'''
import time
from appium import webdriver
from yml_conf import read_conf,write_conf
from app_conf import boss_caps
def start_app():
global driver
driver=webdriver.Remote('http://localhost:4723/wd/hub',boss_caps)
driver.implicitly_wait(10)#稳定元素
def end_app():
#结束session
driver.quit()
#修改密码
def change_psw(old_psw,new_psw):
# 1.进入我的标签
driver.find_element_by_id('com.hpbr.bosszhipin:id/cl_tab_4').click()
# 2.点击右上角设置图标
driver.find_element_by_id('com.hpbr.bosszhipin:id/iv_general_settings').click()
# 3.进入账号与绑定
driver.find_element_by_id('com.hpbr.bosszhipin:id/cl_item').click()
# 4.进入设置密码
driver.find_element_by_xpath('//*[@text="修改密码"]').click()
time.sleep(2)
# print(driver.page_source) #当元素定位工具无法查看元素时候,可以通过该方法查看xml信息-根据元素特征进行定位-对大家要求比较高-会看xml信息
# 5.完成密码设置
#5.1输入旧密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_old').send_keys(old_psw)
#5.2输入新密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_new').send_keys(new_psw)
#5.4输入确认密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_new_confirm').send_keys(new_psw)
#5.5点击确定
driver.find_element_by_id('com.hpbr.bosszhipin:id/btn_save').click()
#如果修改成功就调换密码
logo=driver.find_elements_by_xpath('//*[@text="手机号登录/注册"]')
#如果找到了,调换密码
if logo:
data={'new': old_psw, 'old': new_psw}
#调换密码后写进配置文件
write_conf(data)
def login(psw):
#点击账号密码登录
driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_password_login').click()
#输入密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_password').send_keys(psw)
#登录
driver.find_element_by_id('com.hpbr.bosszhipin:id/btn_login').click()
#等待手动完成验证码
time.sleep(10)
5、test — test_boss.py
'''
@author: haiwen
@date: 2020/11/15
@file: test_boss.py
'''
import pytest
from auto_boss1115 import *
@pytest.fixture(scope='module') #scope默认为function,表示每条测试用例都会执行一次,module表示所有测试用例,只会执行一次,级别比function级别要高
def before_modify_psw():
print('执行初始化动作')
start_app()
yield
end_app()
def test_modify_psw(before_modify_psw):
#从配置文件获取密码
psw=read_conf()
old_psw=psw['old']
new_psw=psw['new']
#登录应该用old
login(old_psw)
change_psw(old_psw,new_psw)
if __name__ == '__main__':
pytest.main(['test_boss.py','-s','--alluredir=tmp/report'])
多设备:
1、yaml文件 — psw.yml
new: boss666
old: boss123
2、读取yaml,写入yaml — yml.conf.py
'''
@author: haiwen
@date: 2020/11/15
@file: yml_conf.py
'''
import yaml
#读yaml
def read_conf(path='psw.yml'):
with open(path,encoding='utf-8') as f:
content=f.read()
#转化成python能识别的格式
data=yaml.safe_load(content)
return data
#写yaml
def write_conf(data,path='psw.yml'):
with open(path,'w',encoding='utf-8',) as f:
#将python格式转化成yml格式
content=yaml.safe_dump(data)
f.write(content)
if __name__ == '__main__':
print(read_conf())
write_conf({'old': 'boss666', 'new': 'boss123'})
print(read_conf())
3、配置文件 — app.conf.py
'''
@author: haiwen
@date: 2020/11/15
@file: app_conf.py
'''
boss_caps={
#平台
"platformName": "Android",
"platformVersion": "8",
"deviceName": "test",
#被测app的信息
'appActivity':'.module.launcher.WelcomeActivity',
'appPackage':'com.hpbr.bosszhipin',
#设置命令超时时间
'newCommandTimeout':6000,
#确保自动化之后不重置app
'noReset':True,
#底层驱动
'automationName':'UiAutomator2',
#如果不想每次都安装UI2驱动,可以这么设置
#'skipServerInstallation':True,
}
#拷贝两份配置项
xiaomi_caps=boss_caps.copy()
meizu_caps=boss_caps.copy()
xiaomi_caps['platformVersion']= '9'
xiaomi_caps['devicesName']='192.168.0.100:5555'
#UI2需要和本机进行通信,默认的端口号是8200,如果不指定同时运行多台设备会造成1台运行失败
#自定义端口范围8245-8299
xiaomi_caps['systemPort']='8255'
meizu_caps['devicesName']='192.168.0.103:5555'
meizu_caps['systemPort']='8260'
4、页面操作代码 — auto_boss1115_multi.py
'''
@author: haiwen
@date: 2020/11/15
@file: auto_boss1115.py
'''
import time
from appium import webdriver
from yml_conf import read_conf,write_conf
from app_conf import boss_caps
def start_app(caps,port): #caps配置项,port端口
global driver
driver=webdriver.Remote(f'http://localhost:{port}/wd/hub',caps)
driver.implicitly_wait(10)#稳定元素
def end_app():
#结束session
driver.quit()
#修改密码
def change_psw(old_psw,new_psw):
# 1.进入我的标签
driver.find_element_by_id('com.hpbr.bosszhipin:id/cl_tab_4').click()
# 2.点击右上角设置图标
driver.find_element_by_id('com.hpbr.bosszhipin:id/iv_general_settings').click()
# 3.进入账号与绑定
driver.find_element_by_id('com.hpbr.bosszhipin:id/cl_item').click()
# 4.进入设置密码
driver.find_element_by_xpath('//*[@text="修改密码"]').click()
time.sleep(2)
# print(driver.page_source)#当元素定位工具无法查看元素时候,可以通过该方法查看xml信息-根据元素特征进行定位-对大家要求比较高-会看xml信息
# 5.完成密码设置
#5.1输入旧密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_old').send_keys(old_psw)
#5.2输入新密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_new').send_keys(new_psw)
#5.4输入确认密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_new_confirm').send_keys(new_psw)
#5.5点击确定
driver.find_element_by_id('com.hpbr.bosszhipin:id/btn_save').click()
#如果修改成功就调换密码
logo=driver.find_elements_by_xpath('//*[@text="手机号登录/注册"]')
#如果找到了,调换密码
if logo:
data={'new': old_psw, 'old': new_psw}
#调换密码后写进配置文件
write_conf(data)
def login(psw):
#点击账号密码登录
driver.find_element_by_id('com.hpbr.bosszhipin:id/tv_password_login').click()
#输入密码
driver.find_element_by_id('com.hpbr.bosszhipin:id/et_password').send_keys(psw)
#登录
driver.find_element_by_id('com.hpbr.bosszhipin:id/btn_login').click()
#等待手动完成验证码
time.sleep(10)
5、test — test_boss_multi.py
'''
@author: haiwen
@date: 2020/11/15
@file: test_boss.py
'''
import pytest
from auto_boss1115_multi import *
from app_conf import xiaomi_caps ,meizu_caps
from multi_process_demo import *
@pytest.fixture(scope='module',params=[(xiaomi_caps,4723),(meizu_caps,4727)])
def before_modify_psw(request): #request是pytest的内置变量,获取fixture的参数
caps = request.param[0] #配置项 # 获取fixture参数
port = request.param[1] #端口号
#启动appium服务
start_appium(port) # 启动appium服务
print('执行初始化动作')
# 启动被测APP
start_app(caps,port)
yield
# 关闭被测APP
end_app()
#关闭appium服务
close_appium(port)
def test_modify_psw(before_modify_psw):
#从配置文件获取密码
psw=read_conf()
old_psw=psw['old']
new_psw=psw['new']
#登录应该用old
login(old_psw)
change_psw(old_psw,new_psw)
if __name__ == '__main__':
pytest.main(['test_boss_multi.py','--alluredir=tmp/report','-n 2','-s'])
6、自动化appium server — multi_process_demo.py
'''
@author: haiwen
@date: 2020/9/18
@file: multi_process_demo.py
'''
import os
import subprocess
import time
from multiprocessing import Process
#启动appium服务
def start_appium(*port):
for p in port:
cmd = 'appium -p ' + str(p)
print(cmd)
subprocess.Popen(cmd, shell=True)
#关闭appium服务
#根据关闭进程来关闭服务
def close_appium(port):
p=subprocess.Popen(f'netstat -ano |findstr {port}', shell=True, stdout=subprocess.PIPE)
#获取命令行的输出
#decode('gbk')是因为Windows是gbk的格式,支持中文
res1=p.stdout.read().decode('gbk')
#如果监测到了监听
if res1:
pid=res1.split()[-1]
os.system(f'taskkill /f /pid {pid}')
#同时启动多个appium服务
def sync_appium_server(*portlist):
process_list=[]
for port in portlist:
#多进程方式打开appium-server,这里不能用多线程(服务只能用多进程,不能用多线程)
p=Process(target=start_appium,args=(port,))
p.start() #启动多进程
process_list.append(p) #将多进程放进进程列表
return process_list
#关掉进程列表种所有进程(服务)
def terminal_sync_server(process_list):
for p in process_list:
p.terminate() #终止进程--等同直接干掉服务
def test_app():
print('app testing.....')
time.sleep(5)
if __name__ == '__main__':
portlist=['4723','4727']
# processlist=sync_appium_server(*portlist)
# time.sleep(5)
# terminal_sync_server(processlist)
for port in portlist:
close_appium(port)
#第一种:
portlist=['4723','4727']
sync_appium_server(*portlist)
time.sleep(5)
for port in portlist:
close_appium(port)
#第二种:
portlist=['4723','4727']
processlist=sync_appium_server(*portlist)
#因为返回的时多进程,多服务,所以用processlist来接收,并用terminal_sync_server内的循环去杀掉进程
terminal_sync_server(processlist)
第五节课 手机web页面自动化,混合app的自动化
1、appium可以测试的对象
原生 :所有控件都是一种开发技术,如android都是java代码组成的控件,ios都是object-c构成的,如
日历程序,计算机都是这种原生app
混合 :原生app无法满足内容快速变更的需要,因此需要结合能快速展现内容的web技术,两种技术结
合在了一起所以称之为混合。如淘宝,美团,展示商品内容的部分都是web页面,该页面嵌套在原生应
用中,可以通过元素定位工具看到这部分内容是包含在webview元素下面的。
而混合app中的网页内容是通过手机系统中webview渲染的,和手机浏览器没有关系,其本质是谷歌浏
览器内核,可以看成同版本的谷歌浏览器。
web应用:手机网页
2、自动化混合APP的条件
#1.确保混合app开启webview debug模式
#2.确定对应设备的webview版本,选择匹配其版本的chromedriver
#3.代码自动化webview种的内容需要切到webview对应的context种
3、总结
1.在电脑上自动化手机页面不需要Appium
2.用手机浏览器自动化需要匹配手机浏览器版本的驱动
3.只有开启debug模式的app才能被自动化webview的内容
4.自动化webview界面内容需要匹配webview版本的驱动
4、查看webview版本
方式1: 设置搜索webview
方式2: 输入以下命令后通过手机浏览器查看
adb shell am start -a android.intent.action.VIEW -d
https://liulanmi.com/labs/core.html
方式3: 通过chrome远程调试功能
1.浏览器地址输入: chrome://inspect
2.手机端打开混合app(开启了webview)
3.查看显示的webview版本
5、APP面试点
1.appium基本原理,手机生态
2.元素定位方法-xpath语法
3.代码功底,封装层级
4.常用测试框架掌握-pytest
5.实际项目经验
6、代码部分
1.PC端自动化手机模式网页
'''
@author: haiwen
@date: 2020/11/16
@file: web1_pc.py
'''
#PC端自动化手机模式网页
from selenium import webdriver
#将自动打开的浏览器调成手机模式访问页面
#1.定义一个谷歌浏览器配置项
chrome_options=webdriver.ChromeOptions()
#2.添加配置--设置成手机浏览器模式
chrome_options.add_experimental_option("mobileEmulation",{"deviceName":"iPhone X"})
driver=webdriver.Chrome(chrome_options=chrome_options) #默认UA是PC请求头
driver.get('http://baidu.com')
driver.set_window_size(400,800)
#百度搜索松勤
driver.find_element_by_id('index-kw').send_keys('松勤\n')
res=driver.find_element_by_css_selector('.c-gap-bottom-small').text#查看第一个搜索结果
#断言,结果种包含松勤软件测试
assert '松勤软件测试' in res
driver.quit()
2.自动化手机浏览器(手机安装chrome浏览器)
'''
@author: haiwen
@date: 2020/11/16
@file: web2_moblie.py
'''
from appium import webdriver
#自动化手机浏览器
browser_caps={
#平台
"platformName": "Android",
"platformVersion": "9",
"deviceName": "test",
#被测app的信息
# 'appActivity':'.module.launcher.WelcomeActivity',
# 'appPackage':'com.hpbr.bosszhipin',
#如果测试谷歌浏览器,直接设置browserName即可
'browserName': 'Chrome',
#设置命令超时时间
'newCommandTimeout':6000,
#确保自动化之后不重置app
'noReset':True,
#底层驱动
'automationName':'UiAutomator2',
#如果不想每次都安装UI2驱动,可以这么设置
#'skipServerInstallation':True,
'systemPort':'8255',
#使用指定版本的浏览器驱动---对应手机谷歌浏览器
'chromedriverExecutableDir': r'C:\Tools\webdriver\chromedriver_win32_v81'
}
driver=webdriver.Remote('http://localhost:4723/wd/hub',browser_caps)
driver.implicitly_wait(10)
#自动化手机浏览器:
driver.get('http://baidu.com')
#driver.set_window_size(400,800)
#百度搜索松勤
driver.find_element_by_id('index-kw').send_keys('松勤\n')
res=driver.find_element_by_css_selector('.c-gap-bottom-small').text#查看第一个搜索结果
#断言,结果种包含松勤软件测试
assert '松勤软件测试' in res
driver.quit()
3.自动化混合app — web3_hybird.py
'''
@author: haiwen
@date: 2020/11/16
@file: web3_hybird.py
'''
#自动化混合app
from appium import webdriver
hybird_caps={
# 平台-设备
"platformName": "Android",
"platformVersion": "9",
"deviceName": "test",
# 被测app的信息
'appActivity':'.MainActivity',
'appPackage':'com.example.haiwen.myhybirdapp',
# 设置命令超时时间
'newCommandTimeout': 6000,
# 确保自动化之后不重置app
'noReset': True,
# 底层驱动
'automationName': 'UiAutomator2',
# 如果不想每次都安装UI2驱动,可以这么设置
# 'skipServerInstallation':True,
'systemPort': '8255',
# 使用指定版本的浏览器驱动---对应当前手机操作系统的webview版本
'chromedriverExecutableDir': r'C:\Tools\webdriver\chromedriver_win32_v80'
}
driver=webdriver.Remote('http://localhost:4723/wd/hub',hybird_caps)
#输入豆瓣移动端网址
driver.find_element_by_id('com.example.haiwen.myhybirdapp:id/editText').send_keys('https://m.douban.com/home_guide')
#回车访问页面
driver.find_element_by_id('com.example.haiwen.myhybirdapp:id/button').click()
#查看当前app所有的context(操作这个步骤的同时,要后台杀掉其他的混合app进程,否则会有冲突)
print(driver.contexts)
#查看当前的context,为原生的context,也就是NATIVE_APP
print(driver.current_context)
#操作webview部分的内容需要切到webview对应的context,格式为WEBVIEW_加包名
driver.switch_to.context('WEBVIEW_com.example.haiwen.myhybirdapp')
#查看当前context,现在是切换到了对应的webview的context,格式为WEBVIEW_com.example.haiwen.myhybirdapp
print(driver.current_context)
#接下就是操作网页
driver.find_element_by_css_selector('.search-input').send_keys('肖申克的救赎\n') #搜索电影
#电影评分
rate=driver.find_element_by_css_selector('li.search-module:nth-child(1) .search_results_subjects li:nth-child(1) .rating>span:nth-child(2)').text
print('电影评分是%s'%rate)
#切换回原生应用,再次输入访问其他浏览器,或者操作原生应用的元素
driver.switch_to.context('NATIVE_APP')
driver.quit()
#1.确保混合app开启webview debug模式
#2.确定对应设备的webview版本,选择匹配其版本的chromedriver
#3.代码自动化webview种的内容需要切到webview对应的context种