文章目录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:///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.ymlnew: boss666 old: boss123 2、读取yaml,写入yaml — yml.conf.pyimport 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.ymlnew: 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:///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种来源:https://www./content-4-869301.html |
|