分享

appium

 印度阿三17 2021-02-24

文章目录

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.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:///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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多