appium
文章目录
appium
1、appium可以测试的对象
2、自动化混合APP的条件
3、总结
4、查看webview版本
5、APP面试点
6、代码部分
方式1: 设置搜索webview
方式2: 输入以下命令后通过手机浏览器查看
方式3: 通过chrome远程调试功能
1.PC端自动化手机模式网页
2.自动化手机浏览器(手机安装chrome浏览器)
3.自动化混合app --- web3_hybird.py
yaml案例:
多设备:
1、yaml文件 --- psw.yml
2、读取yaml,写入yaml --- yml.conf.py
3、配置文件 --- app.conf.py
4、页面操作代码 --- auto_boss1115.py
5、test --- test_boss.py
1、yaml文件 --- psw.yml
2、读取yaml,写入yaml --- yml.conf.py
3、配置文件 --- app.conf.py
4、页面操作代码 --- auto_boss1115_multi.py
5、test --- test_boss_multi.py
6、自动化appium server --- multi_process_demo.py
界面操作
代码部分
点击(坐标点击)
长按
滑动
截屏
打开通知
模拟键盘信号
滑动,截图,打开通知,模拟键盘信号代码结合
driver.tap([(pos_x,pos_y)])
driver.tap([(500,800)],3000)
driver.swipe(start_x,start_y,end_x,end_y,500)
分解后的动作有:
boss直聘修改密码代码优化
测试框架--pytest
测试报告--allure
自动化配置信息
封装配置信息 结合xpath定位元素
UiAutomator1(案例拉勾网)
UiAutomator2(案例boss直聘)
配置信息
案例boss直聘,结合xpath和id进行元素定位
app中的xpath定位注意点
1.安装代码工具包
2.安装appium server desktop(建议1.13版本)
3.安装JDK 1.8版本
4.下载安卓SDK
5.手机端配置
appium工作原理深入
adb无线连接
开启USB调试功能
配置项信息官方:
1. USB连接手机 确保adb可以正常连接
2. 激活adb服务
3. 通过手机局域网IP连接手机
4. 检查是否连接上
第一节课 appium原理与环境搭建 元素定位简介
第二节课 appium元素定位 设备信息
第三节课 手机界面操作 结合pytest实现代码封装与优化
第四节课 案例分析(yaml) 多设备
第五节课 手机web页面自动化,混合app的自动化
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 timefrom 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/hubdriver=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)#等待关键字输入完毕#模拟直接输入enterdriver.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'''#注意包名,项目名不要有同名--appiumfrom appium import webdriverfrom conf import desired_caps#启动session打开被测appdriver=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"]').textdegree=driver.find_element_by_xpath('//*[@resource-id="com.hpbr.bosszhipin:id/tv_required_degree"]').textexperence=driver.find_element_by_xpath('//*[@resource-id="com.hpbr.bosszhipin:id/tv_required_work_exp"]').textprint(f'工作地区:{location},年限{experence},学历:{degree}')#退出driver.quit()
app中的xpath定位注意点
在Appium中,我们没法使用css,因为css是 web 专用的与web不同,底层测试驱动并不识别XPATHAppium负责解析xpath给底层测试驱动来识别每个节点名对应元素的class属性对于一些比较复杂的元素的定位,我们可以用它定位driver.find_element_by_xpath('//ele1/ele2[@attr="a1"]')在app中,用class属性来代替元素标签名如://android.view.ViewGroup
第三节课 手机界面操作 结合pytest实现代码封装与优化
界面操作
点击–对元素的操作
滑动
输入
双击
长按
截屏
放大
拖动
分解后的动作有:
点击(坐标点击)
场景:无法定位到目标元素,采取的一种候补方法
缺点:不是针对元素的操作,必须等目标界面出现才能有对应的交互效果(相当于瞎子点屏幕),不同
分辨率的屏幕会导致误差。
可以通过屏幕尺寸比例减小不同屏幕之间的误差(具体看代码)
driver.tap([(pos_x,pos_y)])
#导包import timefrom 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/32pos_x=width/7*5.5print(pos_x,pos_y)driver.tap([(pos_x,pos_y)])input('输入任意键退出代码')driver.quit()
长按
场景:很多,如长按桌面壁纸可以调出设置屏幕功能
driver.tap([(500,800)],3000)
import timefrom appium import webdriverfrom config import desktop_capsdriver=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 timefrom config import boos_capsfrom 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/2start_y=height/2end_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 timefrom config import boos_capsfrom 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/2start_y=height/2end_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 timefrom config import boos_capsfrom appium import webdriver#启动被测appdef 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 #后面跟的是清除动作,暂时理解为关键字 #后面可以跟常量或者变量,如果没有跟任何的值,可以作为returnafter_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: boss666old: boss123
2、读取yaml,写入yaml — yml.conf.py
import yaml#读yamldef read_conf(path='psw.yml'): with open(path,encoding='utf-8') as f: content=f.read() #转化成python能识别的格式 data=yaml.safe_load(content) return data#写yamldef 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 timefrom appium import webdriverfrom yml_conf import read_conf,write_conffrom app_conf import boss_capsdef 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 pytestfrom 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: boss666old: boss123
2、读取yaml,写入yaml — yml.conf.py
'''@author: haiwen@date: 2020/11/15@file: yml_conf.py'''import yaml#读yamldef read_conf(path='psw.yml'): with open(path,encoding='utf-8') as f: content=f.read() #转化成python能识别的格式 data=yaml.safe_load(content) return data#写yamldef 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-8299xiaomi_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 timefrom appium import webdriverfrom yml_conf import read_conf,write_conffrom app_conf import boss_capsdef 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 pytestfrom auto_boss1115_multi import *from app_conf import xiaomi_caps ,meizu_capsfrom 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 osimport subprocessimport timefrom 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.在电脑上自动化手机页面不需要Appium2.用手机浏览器自动化需要匹配手机浏览器版本的驱动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.常用测试框架掌握-pytest5.实际项目经验
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 resdriver.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 resdriver.quit()
3.自动化混合app — web3_hybird.py
'''@author: haiwen@date: 2020/11/16@file: web3_hybird.py'''#自动化混合appfrom appium import webdriverhybird_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_APPprint(driver.current_context)#操作webview部分的内容需要切到webview对应的context,格式为WEBVIEW_加包名driver.switch_to.context('WEBVIEW_com.example.haiwen.myhybirdapp')#查看当前context,现在是切换到了对应的webview的context,格式为WEBVIEW_com.example.haiwen.myhybirdappprint(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)').textprint('电影评分是%s'%rate)#切换回原生应用,再次输入访问其他浏览器,或者操作原生应用的元素driver.switch_to.context('NATIVE_APP')driver.quit()#1.确保混合app开启webview debug模式#2.确定对应设备的webview版本,选择匹配其版本的chromedriver#3.代码自动化webview种的内容需要切到webview对应的context种