python自动化(四)app自动化:4.appium详解

一.appium desktop简介

Appium是一个开源的,适用于原生或混合移动应用( hybrid mobile apps )的自动化测试工具,Appium应用WebDriver: JSON wire protocol驱动安卓和iOS移动应用。它是继承自selenium的webdriver,所以它支持selenium的大部分API,且也有一些特殊的使用方式。

appium desktop是一款C/S架构的软件,其内集成了appium service。我们一般主要使用appium desktop来完成元素的定位及启动appium service。

使用appium desktop定位元素

(1)连接真机或者模拟器

连接真机时,需要使用文件传输模式,且在开发者选项中设置USB调试模式

(2)在appium desktop中启动appium server

python自动化(四)app自动化:4.appium详解_第1张图片

(3)启动 Inspector Session,创建一个session会话

python自动化(四)app自动化:4.appium详解_第2张图片

  • Capability的讲解方式:

是一组设置的键值对的集合,其中键对应设置的名称,而值对应设置的值,主要用于通知appium服务器建立需要的session。

Capability的使用方式可以参考官方文档:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

我们这里讲解几个常用的key_value。
platformName: 设置被测设备的系统,如:Android
platformVersion:被测设备系统的版本
deviceName:被测设备的序列号(使用adb devices查看)
appPackage:被测app的包名
appActivity:被测app需打开的页面的活动名
noReset:启动时是否不重置app,可以跳过登录,首次打开的弹出等(true或者false)
unicodeKeyboard:设置是否允许中文输入。(true或者false)
resetKeyboard:设置是否允许中文输入。(true或者false)
desired_caps:# 在首次运行测试用例时,不关闭app。默认在首次运行测试用例时会先关闭app,再打开

  • 设备各种信息的获取方式:

1.获取连接的设备信息:adb devices

如果设备未连接:adb connect 127.0.0.1:21503来手动连接。adb disconnect 127.0.0.1:21503手动断开连接

如果adb devices一直获取不到设备信息,可以将sdk下的adb.exe复制到模拟器目录下替换原来的adb.exe(需关闭所有adb进程)

如果还是adb连接不上设备,可以adb kill-server,然后再连接

2.获取app的包名:

方式一:如已安装对应的app:adb shell pm list packages -3(-3表示只看第三方的app)

方式二:如还未安装对应的app:aapt d badging 安装包的路径

3.获取app的活动名:

方式一:如已安装对应的app:adb shell dumpsys activity | findstr mFocusedActivity(获取正在运行的app的包名和活动名)

python自动化(四)app自动化:4.appium详解_第3张图片

方式二:如还未安装对应的app:aapt d badging apk 安装包的路径

4.安装apk软件

adb install apk文件路径

(4)点击start session,创建连接

python自动化(四)app自动化:4.appium详解_第4张图片

(5).appium desktop常用功能介绍

python自动化(四)app自动化:4.appium详解_第5张图片
我们常用定位元素功能来辅助我们编写脚本

二.Appium常用API

1.生成对应的驱动driver

第一步:导入webdriver

from appium import webdriver

第二步:设置Capability(被测设备及App的相关信息)

# 设置Capability(被测设备及App的相关信息)
desired_caps ={
     }
desired_caps['platformName'] = 'Android' # 设置被测设备的系统
desired_caps['platformVersion'] = '7.1.2' # 被测设备系统的版本
desired_caps['deviceName'] = '127.0.0.1:21503 device' # 被测设备的序列号
desired_caps['appPackage'] = 'com.jingdong.app.mall' # 被测app的包名
desired_caps['appActivity'] = '.MainFrameActivity' # 被测app需打开的页面的活动名
desired_caps['noReset'] = 'true' # 启动时是否不重置app,可以跳过登录,首次打开的弹出等
desired_caps['unicodeKeyboard'] = 'true' # 设置中文输入
desired_caps['resetKeyboard'] = 'true' # 设置中文输入
desired_caps['desired_caps'] = 'true' # 在首次运行测试用例时,不关闭app。默认在首次运行测试用例时会先关闭app,再打开

第三步:创建一个driver

格式:webdriver.Remote(‘http://appium server的ip:端口号/wd/hub’,Capability信息)

from appium import webdriver
# 设置Capability(被测设备及App的相关信息)
desired_caps ={
     }
desired_caps['platformName'] = 'Android' # 设置被测设备的系统
desired_caps['platformVersion'] = '7.1.2' # 被测设备系统的版本
desired_caps['deviceName'] = '127.0.0.1:21503 device' # 被测设备的序列号
desired_caps['appPackage'] = 'com.jingdong.app.mall' # 被测app的包名
desired_caps['appActivity'] = '.MainFrameActivity' # 被测app需打开的页面的活动名
desired_caps['noReset'] = 'true' # 启动时是否不重置app,可以跳过登录,首次打开的弹出等
desired_caps['unicodeKeyboard'] = 'true' # 设置中文输入
desired_caps['resetKeyboard'] = 'true' # 设置中文输入
# 生成对应的driver
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)

2.app元素定位

Appium中元素定位的方式:

(1)ID定位:(本质是找app页面元素的resource-id属性的值),当页面有多个相同id的元素时,就不能使用id定位了。

方式一:driver.find_element_by_id('com.xueqiu.android:id/home_search')
方式二:driver.find_element(MobileBy.ID,'com.xueqiu.android:id/home_search')

(2)class name 定位(不推荐,一般定位不准确)

driver.find_element_by_class_name('class值')
driver.find_element(MobileBy.CLASS_NAME,'class值')

(3)xpath定位(使用相对xpath,绝对xpath太长会定位失败)

driver.find_element_by_xpath('//*[@resource-id="com.xueqiu.android:id/name" and @text="阿里巴巴"]')
driver.find_element(MobileBy.XPATH,'//*[@resource-id="com.xueqiu.android:id/name" and @text="阿里巴巴"]')
driver.find_element(MobileBy.XPATH,'//*[contains(@text,"次外出")]').click()

Appium中定位元素的方式与selenium十分相似,可以参考selenium的使用。

还包括一些Android和ISO特有的一些定位方式,需要时自己去查看

其他定位工具(uiautomatorviewer)

uiautomatorviewer是sdk自带的一个工具,也可以定位元素。
python自动化(四)app自动化:4.appium详解_第6张图片
python自动化(四)app自动化:4.appium详解_第7张图片

这个工具在我们的sdk目录的tools目录下,运行该文件即可打开uiautomatorviewer工具。uiautomatorviewer和appiunm的定位工具不能同时打开。

3.app控件的交互

元素的常用方法

appium中元素的常用方法与selenium也十分相似,所以我们可以参考selenium中的方法。

python自动化(四)app自动化:4.appium详解_第8张图片
python自动化(四)app自动化:4.appium详解_第9张图片
python自动化(四)app自动化:4.appium详解_第10张图片

import pytest
from appium import webdriver
from selenium.webdriver.common.by import By
class TestXueQiu:
    def setup(self):
        # 设置Capability(被测设备及App的相关信息)
        desired_caps = {
     }
        desired_caps['platformName'] = 'Android'  # 设置被测设备的系统
        desired_caps['platformVersion'] = '5.1.1'  # 被测设备系统的版本
        desired_caps['deviceName'] = '127.0.0.1:21503 device'  # 被测设备的序列号
        desired_caps['appPackage'] = 'com.xueqiu.android'  # 被测app的包名
        desired_caps['appActivity'] = '.main.view.MainActivity'  # 被测app需打开的页面的活动名
        desired_caps['noReset'] = 'true'  # 每次打开被测app时,不清除之前的数据
        desired_caps['unicodeKeyboard'] = 'true'  # 重置键盘,如果需要输入中文需要设置这一项
        desired_caps['resetKeyboard'] = 'true'  # 允许重置键盘,如果需要输入中文需要设置这一项
        # 生成对应的driver
        self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
        # 设置隐私等待
        self.driver.implicitly_wait(5)
    def teardown(self):
        self.driver.quit()  
    def test_xueqiu_002(self):
        """
        1.打开雪球app
        2.定位首页搜索框
        3.判断搜索框是否可用
        4.打印搜索框的name值
        5.点击搜索框输入’alibaba‘
        6.判断阿里巴巴是否可见
        7.如果可见打印“搜索成功”,否则打印“搜索失败”
        :return:
        """
        ele_search = self.driver.find_element_by_id('com.xueqiu.android:id/home_search')
        ele_search_enable = ele_search.is_enabled()
        print('\n搜索框是否可用:',ele_search_enable)
        ele_search_name = ele_search.get_attribute('name')
        print('搜索框的name:',ele_search_name)
        print('搜索框的坐标:',ele_search.location)
        print('搜索框的长宽:',ele_search.size)
        if ele_search_enable:
            ele_search.click()
            self.driver.find_element_by_id('com.xueqiu.android:id/search_input_text').send_keys('alibaba')
            ele_ali = self.driver.find_element_by_xpath('//*[@resource-id="com.xueqiu.android:id/name" and @text="阿里巴巴"]')
            ele_ali_displayed = ele_ali.is_displayed()
            # print('阿里巴巴是否可见:',ele_ali_displayed)
            if ele_ali_displayed:
                print('搜索成功')
            else:
                print('搜索失败')

4.等待

appium中的等待跟selenium中一样。这里不再讲解

5.触碰操作自动化

我们可以使用TouchAction来完成对手机触碰的操作

TouchAction的使用格式

格式:

action = TouchAction(self.driver) # 实例化一个touchaction对象
action.方法 # 给action添加方法
action.perform() # 执行action

Touchaction的常用方法:

1.按下:

action.press(ele)----------在对应元素的位置按下,参数为某个元素
action.press(x=a,y=b)----------在(a,b)坐标的位置按下,参数为x,y

2.释放:

action.release()-----释放操作

3.移动:

action.move_to(ele)----------移动到对应元素的位置,参数为某个元素
action.move_to(x=a,y=b)----------移动到(a,b)坐标的位置,参数为某个元素

4.长按

action.long_press(ele)-------在对应元素的位置长按,参数为某个元素
action.long_press(x=a,y=b)-------在(a,b)坐标的位置长按,参数为x,y

5.等待

action.wait(200)------等待200毫秒

6.点击

action.tap(ele)----------点击对应元素的位置,参数为某个元素
action.tap(x=a,y=b)----------点击(a,b)坐标的位置,参数为某个元素

实现屏幕滑动

方式一:action.press(ele1).move_to(ele2).release()---------从元素ele1滑动到元素ele2
方式二:action.press(x=70,y=1160).move_to(x=70,y=610).release()-----从(701160)滑动到(70610)
注意,方式二的定位跟手机屏幕大小有关,兼容性不太好,可以进行改进,详见方式3
方式三:
win_size= self.driver.get_window_size() #获取设备屏幕的大小
width = win_size['width'] #屏幕的宽
height = win_size['height'] #屏幕的长
x = int(width/2)
y1 = int(height * 4/5)
y2 = int(height * 1/5)
action = TouchAction(self.driver)
action.press(x=x,y=y1).move_to(x=x,y=y2).release() #实现滑动,而且清楚了屏幕大小对坐标点的影响
action.perform()

6.高级定位技巧

(1)xpath高级运用

python自动化(四)app自动化:4.appium详解_第11张图片
python自动化(四)app自动化:4.appium详解_第12张图片

举例:

//*[@resource-id="com.xueqiu.android:id/name" and @text="阿里巴巴"]--------定位resource-id="com.xueqiu.android:id/name和text="阿里巴巴"的任何元素
//*[@text='BABA']/../../../..//*[@resource-id='com.xueqiu.android:id/current_price']----定位text='BABA'的任意元素的父节点的父节点的父节点的父节点的子孙节点中resource-id='com.xueqiu.android:id/current_price的任意类型的元素

(2)uiautomator定位

python自动化(四)app自动化:4.appium详解_第13张图片
python自动化(四)app自动化:4.appium详解_第14张图片
python自动化(四)app自动化:4.appium详解_第15张图片
python自动化(四)app自动化:4.appium详解_第16张图片
python自动化(四)app自动化:4.appium详解_第17张图片
python自动化(四)app自动化:4.appium详解_第18张图片

举例:

1.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/login_account")')--使用resourceId定位
2.driver.find_element_by_android_uiautomator('new UiSelector().textContains("帐号密码登录")')---使用text模糊匹配定位
3.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/tab_name").text("我的")')----使用resourceId和text组合定位

python自动化(四)app自动化:4.appium详解_第19张图片

# uiautomator实现滚动查找页面元素
self.driver.find_element_by_android_uiautomator('new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("持有封基").instance(0));').click()
       ----滚动查找页面text为‘持有封基’的元素

7.特殊控件toast的识别

python自动化(四)app自动化:4.appium详解_第20张图片
python自动化(四)app自动化:4.appium详解_第21张图片

8.appiunm设备交互api

python自动化(四)app自动化:4.appium详解_第22张图片

(1)模拟来电

self.driver.make_gsm_call('13118172284',GsmCallActions.CALL)
# 第一个参数:来电号码
# 第二个参数:行为(GsmCallActions.CALL--表示来电话)

(2)模拟短信

self.driver.send_sms('131-181-72284','hello.sb')
# 第一个参数:号码
# 第二个参数:发送的信息

(3)模拟网络切换

self.driver.set_network_connection(1)
# 参数:需要设置的网络等级
# 0:数据模式关闭,wifi模式关闭,飞行模式关闭
# 1:数据模式关闭,wifi模式关闭,飞行模式开启
# 2:数据模式关闭,wifi模式开启,飞行模式关闭
# 4:数据模式开启,wifi模式关闭,飞行模式关闭
# 6:数据模式开启,wifi模式开启,飞行模式关闭

(3)截屏

self.driver.get_screenshot_as_file('./kkk.png')

9.获取元素属性

格式:element.get_attribute(‘属性名’)

element1.get_attribute('text')--------获取元素element1的text属性的值

常用的属性:

text----文本
resource-id----id属性
class----class属性
content-desc
checkable----是否可检测
checked----是否已检测
enable----是否可操作
fousable----是否可聚焦
focused----是否已聚焦
scrollable----是否可滚动
long-clickable----是否可长按
selected----是否已选择
bounds----坐标值

10.断言

(1)普通断言(常用)

格式:assert 条件

条件为真,用例通过,条件为假,用例失败

(2)hamcrest框架断言

python自动化(四)app自动化:4.appium详解_第23张图片

官网:https://github.com/hamcrest/PyHamcrest

使用方法:

安装:pip install PyHamcrest

导入:from hamcrest import *

运用:assert_that(要断言的对象,断言方法,‘失败提醒信息’)-----失败提醒信息参数可以不加

# 常用的断言匹配方法
#对象的断言方法:
	assert_that('ass',equal_to('ass'))---匹配相等对象
	assert_that('shj',has_length(3))----匹配对象的长度是否满足
	assert_that(element1,has_property('text'))---匹配元素element1有text属性
	assert_that(element1,has_property('text','我的'))--匹配元素element1有text属性,且属性值为‘我的’
	assert_that(6,close_to(8,2))---匹配接近给定的数字值

这里我们只介绍了几种方法,更多的可以自己去官网查看

11.获取页面源码

driver.page_source

三.android web页面测试

1.appium多架构支持

appium支持原生,web,混合等多种架构app的测试。

  • 原生app:单纯的app,需要安装apk文件
  • web应用:应用在浏览器中,不需要安装apk文件
    python自动化(四)app自动化:4.appium详解_第24张图片

2.web页面app测试

(1)环境准备

python自动化(四)app自动化:4.appium详解_第25张图片

1.获取浏览器驱动。chromedriver

第一步:查看浏览器版本

第一种方式:使用详情查看,这种有可能看不到

python自动化(四)app自动化:4.appium详解_第26张图片

第二种方式:使用真机或模拟器中的浏览器,访问https://liulanmi.com/labs/core.html查看

python自动化(四)app自动化:4.appium详解_第27张图片

2.下载对应的driver

国内镜像:https://npm.taobao.org/mirrors/chromedriver/

github:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md

3.脚本编写driver配置

caps = {
     }
caps['platformName'] = 'Android' # 被测设备为Android
caps['platformVersion'] = '5.1.1' # 被测设备系统版本
caps['deviceName'] = '127.0.0.1:21503' # 被测设备
caps['browserName'] = 'Browser' # 设置使用默认浏览器
caps['chromedriverExecutable'] = 'E:/driver/app_driver/chromedriver.exe' # 设置chromedriver的路径
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)

(2)元素定位

webview测试,不像原生app。不能使用appium的inspector和uiautomator来定位元素

方法:在PC的chrome浏览器上,使用:chrome://inspect,来渲染手机端的浏览器。实现定位

python自动化(四)app自动化:4.appium详解_第28张图片

这样要求手机端必须能访问到google网址,需要。可以网上下载离线开发调试工具包

解决办法:https://www.cnblogs.com/slmk/p/7591126.html

定位方法:跟web页面一样

3.混合应用测试

(1)如何判断一个页面是原生页面,还是webview(h5)页面

python自动化(四)app自动化:4.appium详解_第29张图片

(2)什么是webview

python自动化(四)app自动化:4.appium详解_第30张图片

(3)抓取webview的前提

python自动化(四)app自动化:4.appium详解_第31张图片

(4)混合页面

原生页面元素使用app的定位方式,webview页面的元素使用chrome://inspect定位

python自动化(四)app自动化:4.appium详解_第32张图片

(5)获取混合app中,定位webview需要的chromedrier的版本

测试混合应用app,出了需要设置apppackage和appactivity外,还需要设置chromedrier路径。

获取chromedrier版本的方法:

第一步:获取app中webview的包名

在这里插入图片描述

第二步:通过包名获取版本信息

在这里插入图片描述

四.Capability的高级使用

1.newCommandTimeout

newCommandTimeout设置appium等待下一个请求发送的间隔时间,默认是60s

在自动化用例中,存在上传下载大文件时,可以设置newCommandTimeout长一些

caps['newCommandTimeout'] = 300
# 设置appium等待时间为300s

2.udid

udid设置自动化要使用的设备,用于多设备的情况。默认是选择设备列表中的第一个设备

caps['udid'] = 'asiodf'
# 选择设备asiodf

实际上deviceName并不能决定我们选择的设备。udid才可以

3.autoGrantPermissions

autoGrantPermissions用于处理权限授予的弹框,值为false或者true

注意:如果noReset为true,autoGrantPermissions则不生效

4.noReset

noReset表示在建立session时,是否不关闭app,清除app数据,卸载app。值为true或者false

5.fullReset

fullReset与noReset相反,在建立session时,是否关闭app,清除app数据,并且卸载app。值为true或者false

6.dontStopAppOnReset

dontStopAppOnReset:在脚本开始运行时,不关闭app。默认为false,会关闭app

五.appium原理与协议分析

本节重点:理解客户端,appium server,uiautomator2-server的协议

1.appium客户端协议

appium客户端主要使用webdriver和Mobile JSON Wire Protocol协议(底层还是HTTP),支持多语言。

(1)webdriver协议

webdriver协议是w3c协议的一种,定义了操作web端浏览器的各种接口和协议规范。

我们使用appium或者selenium编写脚本,实际上就是使用webdriver协议。来实现自动化用例

(2)Mobile JSON Wire Protocol协议

Mobile JSON Wire Protocol协议是appium开发团队,在webdriver协议之上封装的一套协议,用于解决对移动端的一些操作支持。Mobile JSON Wire Protocol协议也是w3c组织的一员。

appium客户端使用两大协议将自动化的请求发送到appium server,appium server再遵循特定的协议将请求发送给uiautomator服务端,由uiautomator服务端来实际完成各种自动化操作

十.实战

1.企业微信自动打卡

#! /usr/bin/python
# -*- coding: utf-8 -*-
import time

import pytest
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy




class TestAutoClock:
    def setup(self):
        caps = {
     }
        caps['platformName'] = 'Android' # 被测设备为Android
        caps['platformVersion'] = '5.1.1' # 被测设备系统版本
        caps['deviceName'] = '127.0.0.1:21503' # 被测设备
        caps['appActivity'] = '.launch.WwMainActivity' # 被测app要打开的页面
        caps['appPackage'] = 'com.tencent.wework' # 被测app的包名
        caps['noReset'] = 'true' # 启动时是否不重置app,可以跳过登录等
        caps['unicodeKeyboard'] = 'true' # 设置中文输入
        caps['resetKeyboard'] = 'true' # 设置中文输入
        caps['settings[waitForIdleTimeout]'] = 0
        self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',caps)
        self.driver.implicitly_wait(15)

    def teardown(self):
        self.driver.quit()

    def test_autoclock(self):
        """
        企业微信自动打卡
        :return:
        """
        self.driver.find_element(MobileBy.XPATH,'//*[@text="工作台"]').click()
        # self.driver.find_element_by_android_uiautomator('new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("").instance(0));').click()
        # 滚动查找
        self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("打卡").instance(0));').click()
        self.driver.find_element(MobileBy.XPATH,'//*[@text="外出打卡"]').click()

        # 查找text包含xx的元素
        self.driver.find_element(MobileBy.XPATH,'//*[contains(@text,"次外出")]').click()
        time.sleep(2)
        assert '外出打卡成功' in self.driver.page_source
        
if __name__ == "__main__":
    pytest.main(['-vs','test_wework_autoclock.py'])

你可能感兴趣的:(python自动化,python,android,selenium,软件测试)