python之移动端测试—appium

Appium

  • Appium介绍
  • 环境准备
  • 新版本appium的用法介绍
  • 元素定位函数被封装,统一使用By.xxx(定位方式):
  • 通过文本定位的写法
  • 一个简单的请求示例
  • APP操作api
  • 基础apk安装卸载
  • 发送,拉取文件
  • uiautomatorviewer工具使用
  • 获取页面元素及属性
  • 模拟事件操作
  • 模拟手机手势操作
  • 手机操作
  • 等待的三种方式
  • FAQ
  • Appium介绍

    Appium是一个开源的自动化测试工具,其支持IOS、web、安卓平台上的应用。可以通过appium来控制安卓设备的操作(其实就是模拟人的行为,跟selenium类似)。

    实现原理:

    环境准备

    1.安装jdk :sdk依赖于java环境。双击jdk默认安装即可

  • 配置环境变量:在高级–环境变量-添加JAVA_HOME,写入刚刚jdk的安装路径即可
  • 2.安装android sdk:

  • 百度网盘搞个android_sdk包,解压至本地目录。然后配置环境变量:高级–环境变量-添加ANDROID_HOME,写入sdk的tools路径和platform-tools路径
  • 3.手机(建议真机)或连接逍遥模拟器的方法:点这里!

    我的逍遥模拟器地址:127.0.0.1:21513

    4.电脑安装appium server:
    方式一:可以直接下载exe包安装

    方式二:通过命令行安装:

  • 先安装nodejs,下载地址nodejs.org.安装完成后通过node -v检查是否安装成功
  • 再安装cnpm :npm install -g cnpm –registry=https://registry.npm.taobao.org (由于npm国内下载较慢,
    建议使用淘宝镜像安装)
  • cnpm安装appium : cnpm install -g appium 如果报错runscriptError改为这样安装即可:npm install -g appium –registry=https://registry.npm.taobao.org
  • 启动appium : 直接命令行输入appium
  • 安装appium-python库:pip install Appium-Python-Client —–用来作为通过python操控手机的介质
  • 备注:adb命令见:点这里!adb命令大全

    新版本appium的用法介绍

    元素定位函数被封装,统一使用By.xxx(定位方式):

    def loginA(driver):
        loginBtn=driver.find_element(By.CLASS_NAME,'net.qiujuer.genius.ui.widget.Button')
        loginBtn.click()
        #账号:158*******8
        #密码:zx*****7
        accountBtn=driver.find_element(By.ID,'com.lockin.loock:id/et_phone_num')
        accountBtn.send_keys("158*******8")
        pwdBtn=driver.find_element(By.ID,'com.lockin.loock:id/et_password')
        pwdBtn.send_keys('zx*****7')
    
        checkBtn=driver.find_element(By.ID,'com.lockin.loock:id/checkbox_login')
        checkBtn.click()
    
        logBtn=driver.find_element(By.ID,'com.lockin.loock:id/btn_login')
        logBtn.click()
        print("账号登录成功")
    

    通过文本定位的写法

    def online(driver):
        #点击直播视图区域
        locateonline=driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,'new UiSelector().text("实时视频")')
        # locateonline=driver.find_element(By.A,' ')
        locateonline.click()
    

    使用元素的文本内容(text)进行定位:
    python
    element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,‘new UiSelector().text(“文本内容”)’)

    使用元素的部分文本内容(contains)进行定位:
    python
    element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,‘new UiSelector().textContains(“部分文本内容”)’)

    使用元素的正则表达式匹配文本内容(matches)进行定位:
    python
    element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,‘new UiSelector().textMatches(“正则表达式”)’)

    使用元素的开头文本内容(startsWith)进行定位:
    python
    element = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,‘new UiSelector().textStartsWith(“开头文本内容”)’)

    不同的自动化被测手机系统or 平台系统,需要切换不同的对应配置:


    以下都是旧版本appium的使用方法

    一个简单的请求示例

    需求:打开安卓设备的一个app:
    1.先设置好连接设备的信息,如设备平台,版本,设备号
    2.获取app名称以及启动程序
    3.通过appium发送请求

    from appium import  webdriver
    
    devices_info={}
    #连接的参数获取,都可以通过adb命令来获取
    #获取设备平台,版本,设备号。若是真实手机:完整的Device name要加上品牌和型号:比如这台设备时huawei的,型号是MAR_AL00,device name就是huawei-MAR_AL00_5G05475c0005
    
    devices_info['platformName']='Android'
    devices_info['platformVersion']='5.1.1'
    #模拟器的设备
    devices_info['deviceName']='127.0.0.1:21503'
    
    #app信息:adb命令获取,记得一定要先把app开启。logcat | grep -i displayed
    # devices_info['appPackage']='com.android.settings'
    # devices_info['appActivity']='.Settings'
    devices_info['appPackage']='com.songqin.sqoa'
    devices_info['appActivity']='.MainActivity'  #应用启动名
    #发送命令,连接手机
    #这里的端口是appium的端口号
    driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',devices_info)
    

    ps:真机手机deviceName的获取方法:点我

    APP操作api

    基础apk安装卸载

    import os
    from appium import  webdriver
    
    #server启动参数
    devices_info={}
    #连接的参数获取
    #获取设备平台,版本,设备号
    devices_info['platformName']='Android'
    devices_info['platformVersion']='5.1.1'
    devices_info['deviceName']='127.0.0.1:21503'
    devices_info['appPackage']='com.songqin.sqoa'
    devices_info['appActivity']='.MainActivity'
    
    driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',devices_info)
    
    # 安装apk到手机上
    driver.install_app(r'F:\Users\admin\PycharmProject\android_test\sqoa.apk')
    #通用路径写法
    apk_path=os.getcwd()+os.sep+'sqoa.apk'
    driver.install_app(apk_path)
    
    #卸载apk,appid是需要卸载的app包名
    app_id='com.sqoa.apk'
    driver.remove_app(app_id)
    
    #判断app是否已安装
    if driver.is_app_installed(app_id):
        print('该apk已被安装')
        driver.remove_app(app_id)
    else:
        driver.install_app(apk_path)
    
    driver.quit()
    

    发送,拉取文件

    将本地pc文件通过push_file()方法发送到安卓设备上:
    1.读取文件内容;
    2.将读取到的byte类型数据先通过utf-8转成人看得懂的数据类型,然后再通过base64转码成手机可识别的数据类型,并对其进行编码,最后将其转为str类型。
    3.通过push_file方法发送到手机,并指定文件的名称。

    import base64
    import os
    from appium import  webdriver
    
    devices_info={}
    #连接的参数获取
    #获取设备平台,版本,设备号
    devices_info['platformName']='Android'
    devices_info['platformVersion']='5.1.1'
    devices_info['deviceName']='127.0.0.1:21503'
    devices_info['appPackage']='com.songqin.sqoa'
    devices_info['appActivity']='.MainActivity'
    
    driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',devices_info)
    
    # 发送文件到手机
    with open('a.txt','r') as f:
        data=f.read()
        # 需要将读取到的byte类型数据转码发送
        b64_data=str(base64.b64encode(data.encode('utf-8')),'utf-8')
        # 发送文件到手机,并指定名字
        driver.push_file('/sdcard/hello.txt',b64_data)
    
    driver.close()
    

    将设备上的文件拉取到本地,并且显示出数据

    从安卓设备拉去文件并显示数据
    sour_data=driver.pull_file('/sdcard/hello.txt')
    # 解码base64数据
    data=str(base64.b64decode(sour_data),'utf-8')
    print(data)
    

    获取页面源码关键字,做判断

    # 获取页面源码
    if '开发者选项' in driver.page_source:
        print("找到元素")
    else;
        print("未找到元素")
    

    uiautomatorviewer工具使用

    简介:uiautomatorviewer就是用来扫描和分析Android应用程序的UI控件工具。

    如何使用?
    1.进入android_sdk的tools目录,打开uiautomatorviewer
    2.电脑连接安卓设备或模拟器
    3.点击启动待测试的app
    4.点击uiautomatorviewer左上角device screenshot 会生成app的UI控件截图
    5.选择截图上需要查看的控件,即可浏览该控件的id,calss ,text 坐标等信息

    过程中给遇到双击闪退问题的解决方案,其他的都试过,只有这种方法最终才解决掉:https://blog.csdn.net/weixin_49554079/article/details/130013339

    获取页面元素及属性

    获取单个元素:
    data=driver.find_element_by_id(“com.android.settings:id/title”)

    data=driver.find_element_by_xpath(‘’//*[contains(@text,‘WLAN’)]‘’)

    获取多个元素:
    elements=driver.find_elements_by_class_name(“android.widget.TextView”)

    在输入框中输入内容,清空内容

    import base64
    import os
    from appium import  webdriver
    
    devices_info={}
    devices_info['platformName']='Android'
    devices_info['platformVersion']='5.1.1'
    devices_info['deviceName']='127.0.0.1:21503'
    devices_info['appPackage']='com.songqin.sqoa'
    devices_info['appActivity']='.MainActivity'
    
    driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',devices_info)
    
    input_content=driver.find_element_by_id("com.android.settings:id/search").send_keys("微信")
    
    input_content.clear()
    driver.close_app()
    driver.close()
    

    获取元素值:
    driver.find_element_by_id(“com.android.settings:id/search”).text

    获取属性值:driver.find_element_by_id(“com.android.settings:id/search”)。get_attribute(“name”)

    获取坐标:
    driver.find_element_by_id(“com.android.settings:id/search”).location

    获取包名、应用名
    driver.current_package
    driver.current_activity

    模拟事件操作

    滑动事件:
    从一个坐标位置滑动到另一个坐标位置,是两点之间的滑动。

    方法:swipe(start_x,start_y,end_x,end_y,duration=None)
    参数说明:
    1.start_x,start_y代表起点的x,y轴坐标
    2.end_x,end_y代表终点的x,y轴坐标
    3.duration代表滑动这个操作一共持续的时间长度。

    wlan_location=driver.find_element_by_id("com.songqin.sqoa:id/title").location
    version_location=driver.find_element_by_id("com.songqin.sqoa:id/version").location
    driver.swipe(wlan_location['x'],wlan_location['y'],version_location['x'],version_location['y'],3000)
    
    

    滚动事件:
    从一个元素滚动到另一个元素,直到页面自动停止。

    方法:
    scroll(orgin_el,dest_el)
    参数说明:
    1.orgin_el代表开始元素位置,dest_el代表结束元素位置

    wlan_location=driver.find_element_by_id("com.songqin.sqoa:id/title") 
    version_location=driver.find_element_by_id("com.songqin.sqoa:id/version") 
    driver.scroll(wlan_location,version_location)
    

    拖拽事件drag:
    将一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置。

    方法:
    drag_and_drop(orgin_el,dest_el)
    参数说明:
    1.orgin_el代表开始元素位置,dest_el代表结束元素位置

    wlan_location=driver.find_element_by_id("com.songqin.sqoa:id/title") 
    version_location=driver.find_element_by_id("com.songqin.sqoa:id/version") 
    driver.drag_and_drop(wlan_location,version_location)
    

    将应用置于后台,模拟热启动:
    driver.background_app(seconds)
    seconds代表停留在后台的时间,单位s

    模拟手机手势操作

    模拟手点击屏幕操作:
    TouchAction(driver).tap(element,x,y)
    element:被定位到的元素
    x:元素坐标的x轴数据
    y:元素坐标的y轴数据

    wlan=driver.find_element_by_id(“com.songqin.sqoa:id/title”)
    #通过元素定位方式点击屏幕
    TouchAction(driver).tap(wlan).perform()
    #通过元素的x,y轴坐标来定位点击屏幕
    TouchAction(driver).tap(wlan.location[‘x’],wlan.location[‘y’]).perform()

    模拟手按下操作:
    注意:一定要release当前的操作!!!否则会报错

    方法:
    TouchAction(driver).press(element,x,y)
    release() #结束动作,手离开屏幕
    wait()等待操作

    参数说明:
    element:被定位到的元素
    x:元素坐标的x轴数据
    y:元素坐标的y轴数据

    wlan=driver.find_element_by_id("com.songqin.sqoa:id/title")
    #按下操作
    TouchAction(driver).press(wlan).release().perform()
    #按下屏幕,等待3s,然后释放
    TouchAction(driver).press(wlan).wait(3000).release().perform()
    #长按3s
    TouchAction(driver).long_press(id,id.location['x'],id.location['y'],3000).release().perform()
    

    手按住屏幕向上拖动:
    方法:
    move_to(element=None,x=None,y=None)

    wlan=driver.find_element_by_id("com.songqin.sqoa:id/title")
    bluetooth=driver.find_element_by_id("com.songqin.sqoa:id/blue")
    #根据元素方式拖动
    TouchAction(driver).press(wlan).move_to(bluetooth).release().perform()
    #根据坐标数据向上拖动
    TouchAction(driver).press(x=200,y=1000).move_to(x=100,y=200).release().perform()
    
    手机操作

    获取手机时间:
    driver.device_time

    获取手机宽高
    driver.get_window_size()

    获取手机按钮:
    driver.keyevent(24)
    数字代表按键,参照adb的规则

    打开手机通知栏:
    driver.open_notifications()

    获取手机网络
    driver.network_connection
    driver.set_network_connection(6) #将网络设置为ipv6
    driver.network_connection

    截图
    driver.get_screencap_as_file(os.getcwd()+od.sep+‘hi.png’)

    案例:
    给手机设置图形锁密码

    from appium import  webdriver
    from appium.webdriver.common.touch_action import TouchAction
    
    devices_info={}
    devices_info['platformName']='Android'
    devices_info['platformVersion']='5.1.1'
    devices_info['deviceName']='127.0.0.1:21503'
    devices_info['appPackage']='com.android.launcher3'
    devices_info['appActivity']='.Launcher'
    
    driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub',devices_info)
    driver.implicitly_wait(30)
    
    kn=driver.find_element_by_xpath("//*[contains(@text,'知道了')]").click()
    if "设置" in driver.page_source:
        #打开设置
        driver.find_element_by_xpath("//*[contains(@text,'设置')]").click()
        #滑动页面,使当前页面可以显示安全栏
        wlan=driver.find_element_by_xpath("//*[contains(@text,'WLAN')]")
        safe=driver.find_element_by_xpath("//*[contains(@text,'安全')]")
        TouchAction(driver).press(wlan).move_to(safe).release().perform()
        # 点击安全
        safe.click()
        #点击屏幕锁定、图案
        driver.find_element_by_xpath("//*[contains(@text,'屏幕锁定')]").click()
        driver.find_element_by_xpath("//*[contains(@text,'图案')]").click()
    
        #绘制图形
        TouchAction(driver).press(x=220,y=330).wait(500).move_to(x=220,y=550).wait(500)\
            .move_to(x=660,y=550).wait(500).move_to(x=870,y=970).release().perform()
    
    driver.close_app()
    driver.close()
    

    等待的三种方式

    1.显示等待:WebDriverWait(driver,timeout,poll-frequency).until(method)
    参数说明:
    timeout:设置的超时时间
    poll_frequency : 每次搜索间隔时间,默认为0.5s
    method : 定位方法(一个匿名函数)

    例:
    WebDriverWait(driver,5,1).until(lambda x:x.find_element_by_id(id_value))
    lambda函数中x代表传入的值driver
    函数运行过程:
    1.实例化WebDriverWait类,传入driver对象,之后driver对象被赋值给webdriverwait的一个类变量self.driver
    2.until为webdriverwait的方法,until方法传入method方法,之后method方法会被传入self.driver
    3,搜索到元素后until返回定位对象,没有搜索到函数until返回超时异常错误。

    2.强制等待:time.sleep(5)
    3.隐式等待:driver.implicitly(30)

    FAQ

    1.遇到UiAutomator exited unexpectedly with code 0, signal null

    解决方案:可能是appium与uiautomator版本不兼容导致,更换请求为UIAutomator2即可。代码中配置:devices_info[‘automationName’]=‘UIAutomator2’

    2.提示报错信息Original error: Could not find ‘apksigner.jar’

    原因:android-sdk缺少apksigner.jar的jar依赖包
    在该路径下增加apksigner.jar包:C:\Users\PC\AppData\Local\Android\Sdk

    3.出现错误:Could not sign with default certificate

    解决方案:以管理员身份打开appium

    3.报错ziplagi

    appium版本太旧与Android sdk不兼容导致,更新appium版本解决。我的appium版本更新到v2.5.1版本ok.

    4.报错No route found for //session <– POST //session 404 42 ms

    新版本appium的请求默认地址修改了,因此访问的时候只要这样就可以http://127.0.0.1:4723,不用加后面的/wd/hub

    5、uiautomatorviewer报错:Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncExcept…

    1、在cmd命令窗口中输入 adb root 即可;
    2、重启手机无效;
    3、重新把手机拔了再插;
    4、重启appuim;
    5、重启uiautomatorviewer.bat;
    6、打开手机开发者权限,将USB调试按钮重新启动就好了;
    好吧,以上所有方法都试完了,如果解决了,恭喜你们,我不符合以上情况。
    7、各总尝试后发现:关闭界面中的动态不停地进行绘制的元素-进度条(成功)。

    作者:weixin_43973848

    物联沃分享整理
    物联沃-IOTWORD物联网 » python之移动端测试—appium

    发表回复