移动端自动化

移动端测试环境搭建

  移动端自动化测试的基础环境配置需要搭建下面三个环境:

    1、Java环境
    2、AndroidSDK环境
    3、Android模拟器

  下载链接: https://pan.baidu.com/s/1XP5ki3uHy4b7giiePv5QhA 提取码: mb4p

环境说明

  Java:Android的应用层开发使用的是Java语言,所以需要使 Java环境。

  AndroidSDK:提供Android开发的软件开发工具包。

  Android模拟器:模拟安卓手机的一个程序。

Java环境安装

  下载JDK1.8安装即可,详见:https://www.cnblogs.com/lyang-a/p/11462369.html

AndroidSDK环境安装

  AndroidSDK下载的官网地址:https://www.androiddevtools.cn/

  Window 平台解压后,进入解压缩目录,双击 SDK Manager.exe ,下载所需工具包即可。
  Mac平台解压后,进入解压缩目录,进入tools目录,双击 android 这个文件,打开 Android SDK Manager, 下载所需工具包。

  参考地址:https://www.pianshen.com/article/399239299/

AndroidSDK环境变量配置:

  注意:android-sdk 文件夹需注意,路径中不要有中文。

1. 进入我的电脑 -> 属性 -> 高级系统设置 -> 环境变量

2. 在系统变量下点击新建 -> 变量名: ANDROID_HOME -> 变量值(文件路径): D:android-sdk -> 点击确定按钮

3. 在系统变量下找到系统的path变量,最后添加:;%ANDROID_HOME%platform-tools;%ANDROID_HOME%	ools;(最前面是一个分号,如果path变量最后已有分号,可不用添加) -> 点击确定按钮

mac平台的AndroidSDK环境变量配置:

1.进入命令行, 
	vim ~/.bash_profile
2.设置环境变量
    ANDROID_HOME=电脑存放的路径/android-sdk-macosx
    PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools
    export ANDROID_HOME 
    export PATH
3. 重写打开终端

验证环境变量是否配置成功:

adb version

  android_sdk中的adb.exe版本和夜神模拟器中的nox_adb命令版本不一致,则会报错:

  解决办法:

    1、把android_sdkplatform-tools目录下adb.exe复制一份,名字修改为:nox_adb.exe

    2、把夜神模拟器中bin目录下的nox_adb.exe进行替换

    3、重启夜神模拟器

    4、打开终端输入 【adb devices】即可发现连接的设备

adb命令

  adb全名Andorid Debug Bridge,是一个调试工具,它可以在电脑通过终端命令操作安卓手机或者模拟器。

adb的工作原理

  adb 包含三个部分:

    1、Client端:运行在开发机器中,即你的开发PC机。用来发送adb命令。

    2、Daemon守护进程:运行在调试设备中, 即手机或模拟器,用来接收和执行adb命令。

    3、Server端:作为一个后台进程同样运行在开发机器中, 用来管理PC中的Client端和手机的Daemon之间的通信。

adb的常用命令

查看adb版本

adb version

adb --version

获取包名和界面名

  包名:app的唯一标识,好比身份证号码
  界面名:app中显示界面对应的名字

示例:

  1、打开设置

  2、打开终端输入命令

    Windows过滤使用 findstr ,Mac过滤使用 grep

Windows:
	adb shell dumpsys window windows | findstr mFocusedApp
	
Mac:
	adb shell dumpsys window windows | grep mFocusedApp

  3、得到结果数据

mFocusedApp=AppWindowToken{d02598c token=Token{85dfcde ActivityRecord{11a3419 u0 com.android.settings/.Settings t38}}}

  此处包名为:com.android.settings

  界面名为:.Settings

文件传输

  将电脑上的文件发送到手机

adb push 电脑的文件的路径 手机的文件夹的路径

# 示例
adb push D:2233.png /sdcard

  将手机上的文件发送到电脑

adb pull 手机的文件的路径 电脑的文件夹的路径

# 示例
adb pull /sdcard/2233.png D:

安装程序

adb install apk路径

adb install -r apk路径

  -r 覆盖安装

# 示例
adb install -r bug.apk

卸载程序

  卸载程序时需先查询到指定软件的包名,根据包名进行删除

adb uninstall 包名

# 示例
adb uninstall cn.itcast.myapplication

查看连接设备

# 查看手机的连接状态adb devices
# -s:指定某个设备例:
# 指定某个设备运行命令adb -s 设备号 命令
	adb -s 设备号 push xxx
	adb -s 设备号 install xxx
	adb -s 127.0.0.1:62001 install D:/bug.apk

进入Android系统终端

  进入Android手机中的linux系统中,Android系统是基于Linux系统的。

adb shell

开启/关闭adb服务

adb kill-server    # 关闭adb服务

adb start-server   # 开启adb服

查看App启动时间

adb shell am start -W 包名/界面名

  ThisTime:该界面启动耗时时间(毫秒),如果关心应用有界面Activity启动耗时,参考ThisTime
  TotalTime:应用自身启动耗时时间(毫秒),如果只关心某个应用自身启动耗时,参考TotalTime
  WaitTime: 系统启动应用的耗时时间(毫秒),如果关心系统启动应用耗时,参考WaitTime

查看手机上所有的包名

adb shell pm list packages

查看日志

adb logcat

  过滤级别:级别从高到低(E > W > I > D > V),E 表示错误、W表示警告

# 过滤日志级别adb logcat *:级别

另一种查看包名的方式:

  1、先 【adb logcat | findstr START】

  2、再打开想要查看的程序

查看电池

adb shell dumpsys battery

查看内存

adb shell dumpsys meminfo

查看cpu

adb shell top

  s:表示按什么排序

例:adb shell top -s 9  # 按照CPU使用率进行排序

monkey介绍

  monkey是用来做Android的压力测试的(ios不能做),要想对ios做压力测试需用到 fastmonkey这个第三方工具。

  monkey主要用来测试App的健壮性。monkey测试、健壮性测试、压力测试。

  命令:

adb shell monkey 选项 操作次数

  一次操作表示一次次数,比如:手指按下一次、移动一次、手指抬起一次都表示一次操作,共完成了3次操作。

monkey命令的选项

  -p  包名,要测试哪个应用程序

  -v  日志级别,一般用两个-v即可

  -s  seed值,用来复现bug,当seed值相同时,monkey所产生的事件序列也相同

  --throttle  事件的间隔时间,单位:毫秒,一般300毫秒左右就可以。

  --pct-xxx  设置事件的百分比

    --pct-touch 点击事件

    --pct-motion 滑动事件

monkey输出日志

  将monkey操作的日志保存到日志中使用【>】进行写入

adb shell monkey -p 包名 操作次数 > 日志的路径

monkey的操作

adb shell monkey -p 包名 -v -v [--pct-touch 百分比数字] --throttle 2000 次数 > 日志的路径

  提示:使用 【-v -v】可以详细的查看执行的操作

  查看日志,如果有 monkey finished表示执行过程中没有问题,如果没有在终端需要观察 anr 或 exception异常信息

  尝试复现,使用 -s 参数。例:adb shell monkey -v -v -s 1628066493671 20

  

移动端自动化测试环境搭建

  Android自动化测试需要搭建下面5个环境,如下:

   1、Java环境

   2、AndroidSDK环境

   3、Android模拟器

   4、Appium Desktop(Appium 服务端)

   5、Appium-Python-Client(Appium Python客户端)

具体执行流程:

  1、先通过Appium-Python-Client工具编写操作手机App的Python代码;

  2、当运行编写好的Python代码时会连接Appium服务端;

  3、Appium服务端通过解析操作的代码会启动手机上对应的App,把Python代码操作手机App的效果会呈现出来,最终完成自动化测试。

Appium Desktop(Appium 服务端)介绍

  Appium Desktop是一款适用于Mac,Windows和Linux的开源应用程序,它以美观而灵活的用户界面提供强大的Appium服务。

作用:

  Appium服务端通过解析代码,驱动Android设备来执行自动化测试脚本。

  下载地址:https://github.com/appium/appium-desktop/releases/

Appium-Python-Client介绍

  它是移动端定位App元素和操作App元素的一个第三方库,它还负责与Appium服务器建立连接,并将测试脚本的指令发送到Appium服务器,Appium服务器再驱动手机或者模拟器展示相关的效果,类似于web端自动化测试中的Selenium库。

  Appium库是基于Selenium库开发的,Appium库中的WebDriver类是继承Selenium库中的WebDriver类。

安装Python语言的Appium客户端库:

pip install Appium-Python-Client

appium入门示例

需求:

  使用 Appium-Python-Client 库 打开Android模拟器的设置界面

实现步骤:

  1、开启appium服务器

  2、启动Android模拟器,打开设置界面

  3、打开电脑终端,输入查看包名和界面名的adb命令

adb shell dumpsys window windows | grep mFocusedApp

  4、编写Python的Appium客户端代码,实现打开Android模拟器的设置界面

import time

from appium import webdriver

# 创建子弹,封装启动app的参数
desired_capabilities = {
    # 连接手机的平台名称
    "platformName": "Android",
    # 连接手机的平台版本,也就是手机的操作系统版本, 至少匹配大版本,比如:写7
    "platformVersion": "7.1",
    # 设备名称,随便写, 但是不能为空
    "deviceName": "127.0.0.1:62001",
    # 启动程序的包名
    "appPackage": "com.android.settings",
    # 启动程序的界面名
    "appActivity": ".Settings"
}
# 连接appium服务器,并创建驱动对象
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 延时2秒钟
time.sleep(2)
# 退出app
driver.quit()

参数说明:

platformName: 连接手机的平台名称
platformVersion: 手机的操作系统版本
deviceName: 设备名称,随便写, 但是不能为空
appPackage: 启动程序的包名
appActivity: 启动程序的界面名

其它参数说明:

# 设置输入中文,默认不支持,下面两个参数一般都是配合使用
unicodeKeyboard 使用 Unicode 输入法,默认值 false
resetKeyboard 重置输入法到原有状态,如果单独使用,将会被忽略,默认值 false

noReset:不重置应用,默认为false
noSign 跳过检查和对应用进行 debug 签名的步骤,默认值 false,appium 默认会对应用进行重签名,可能导致官方服务器不认,一般设置成True
autoGrantPermissions 自动同意app所需要的各种权限,默认是false

uiautomatorviewer

  uiautomatorviewer是一个手机端查看控件的特征信息的一个工具。

示例:

  查看手机端设置程序右上角的放大镜按钮的 resource-id

步骤:

  1、打开在电脑终端输入 uiautomatorviewer;
  2、启动android模拟器,打开设置应用;
  3、打开终端输入uiautomatorviewer进行打开,打开后点击左上角的第三个按钮,关联手机屏幕;
  4、点击放大镜按钮;
  5、查看Node Detail 中的 resource-id 信息。

说明:

  resource-id 好比 html元素的id,但是在手机端 resource-id这个属性值可以重复。

  class 好比 html元素的class,表示类属性。

  在手机端定位一般都使用xpath,更加灵活和方便。

元素定位操作

  根据元素的特征信息进行元素的定位,比如:利用xpath根据元素的属性信息进行定位

注意点:

  元素的定位基于当前屏幕范围内的可见元素。

手机端元素的定位方式:

  id定位

  class定位

  xpath定位

定位一个元素的方法:

  使用id定位一个元素:driver.find_element_by_id(resource-id),定位的是resource-id属性值

  使用class定位一个元素:driver.find_element_by_class_name(class_value),定位的是class属性值

  使用xpath定位一个元素:driver.find_element_by_xpath(xpath_value),根据xpath表达式定位元素

  定位content-desc元素:driver.find_element_by_accessibility_id

  注意:定位一个元素时,如果多个元素都有相同的特征信息,使用该方法定位到的是第一个。

定位一组元素的方法:

  使用id定位一组元素:driver.find_elements_by_id(resource-id)

  使用class定位一组元素:driver.find_elements_by_class_name(class_value)

  使用xpath定位一组元素:driver.find_elements_by_xpath(xpath_value)

定位一个元素的示例:

"""
	使用id定位设置界面的放大镜并点击
	使用class定位搜索框并输入内容“显示” 
	使用xpath定位返回按钮并点击
"""
import time

from appium import webdriver

# 创建字典,封装启动app的参数
desired_capabilities = {
    # 连接手机的平台名称
    "platformName": "Android",
    # 连接手机的平台版本,也就是手机的操作系统版本, 至少匹配大版本,比如:写7
    "platformVersion": "7.1",
    # 设备名称,随便写, 但是不能为空
    "deviceName": "127.0.0.1:62001",
    # 启动程序的包名
    "appPackage": "com.android.settings",
    # 启动程序的界面名
    "appActivity": ".Settings",
    # 设置支持中文输入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 连接appium服务器,并创建驱动对象
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 使用id定位放大镜
search_button = driver.find_element_by_id("com.android.settings:id/search")
# 点击放大镜
search_button.click()
time.sleep(0.5)

# 使用class定位搜索框
search_box = driver.find_element_by_class_name("android.widget.EditText")
# 默认输入不了中文,需要设置启动app参数,unicodeKeyboard和resetKeyboard这两个参数为True
search_box.send_keys("显示")
time.sleep(0.5)

# 使用xpath定位返回按钮
# back_button = driver.find_element_by_xpath("//android.widget.ImageButton[@content-desc='收起']")
# 简单操作
back_button = driver.find_element_by_xpath("//*[@content-desc='收起']")
back_button.click()

# find_element_by_accessibility_id 可以用于定位content-desc的属性值
# back_button = driver.find_element_by_accessibility_id("收起")
# back_button.click()


time.sleep(2)
# 退出app
driver.quit()

  说明:输出的信息里面有空行,是因为定位class为android.widget.TextView的元素,没有内容。

定位一组元素的示例:

"""
需求:
	通过程序打开android手机或者模拟器的设置界面
	通过id定位所有resource-id为 android:id/title 的元素,并打印每一个元素的文本内容
	通过class定位所有的class为 android.widget.TextView 的元素,并打印每一个元素的文本内容
	通过xpath定位所有包含 '设' 的元素,并打印每一个元素的文本内容。
"""
import time

from appium import webdriver

# 创建字典,封装启动app的参数
desired_capabilities = {
    # 连接手机的平台名称
    "platformName": "Android",
    # 连接手机的平台版本,也就是手机的操作系统版本, 至少匹配大版本,比如:写7
    "platformVersion": "7.1",
    # 设备名称,随便写, 但是不能为空
    "deviceName": "127.0.0.1:62001",
    # 启动程序的包名
    "appPackage": "com.android.settings",
    # 启动程序的界面名
    "appActivity": ".Settings",
    # 设置支持中文输入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 连接appium服务器,并创建驱动对象
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 定位id为android:id/title的所有元素
title_list = driver.find_elements_by_id("android:id/title")
for element in title_list:
    # 获取元素的内容
    print(element.text)

time.sleep(0.5)
# 定位class为android.widget.TextView的所有元素
text_view_list = driver.find_elements_by_class_name("android.widget.TextView")
for text_view in text_view_list:
    # 获取元素的内容
    print(text_view.text)
time.sleep(0.5)
# 使用xpath定位文本内容包含 设 的所有元素

element_list = driver.find_elements_by_xpath("//*[contains(@text, '设')]")
for element in element_list:
    # 获取元素的内容
    print(element.text)

time.sleep(2)
# 退出app
driver.quit()

定位单个元素和定位一组元素的注意点:

  使用find_elements_by_xx,如果传入的特征信息没有定位到元素,则返回一个空列表,比如: []

  使用find_element_by_xx,如果传入的特征信息没有定位到元素,则会抛出一个NoSuchElementException的异常。

元素等待

应用场景:

  由于某些原因,我们想定位的元素没有立刻出来,此时如果直接定位可能会报错,比如有以下原因:

  1、由于网络速度原因
  2、服务器处理请求原因
  3、电脑配置原因

元素等待的分类:

  隐式等待

  显示等待

隐式等待

应用场景

  当定位所有元素时,设置超时时间为同一个值的时候,此时使用隐式等待,设置隐式等待能够作用于所有元素。

注意点

  当定位的元素,超过指定时间了还没有定位到,此时会抛出一个 NoSuchElementException异常

操作代码

driver.implicitly_wait(10)

显示等待

应用场景:

  当定位每个元素时,设置超时时间不一样时,此时使用显示等待, 它只能作用于某个元素的。

注意点:

  当定位的元素,超过指定时间了还没有定位到,此时会抛出一个 TimeoutException异常

操作代码:

WebDriverWait(driver, 超时时间, 搜索时间间隔).until(lambda定位元素的函数)

示例:

"""
	打开Android手机或者模拟器中的设置,使用显示等待定位 “返回” 按钮,超时时间设置为5秒,每1秒查找一次。
"""
import time

from appium import webdriver

# 封装启动app的参数
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

desired_capabilities = {
    "platformName": "Android",
    "platformVersion": "7.1",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    "appActivity": ".Settings",
    # 设置支持中文输入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 连接appium服务器,并创建驱动对象
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

# 显示等待,如果元素没有定位到则会抛出 TimeoutException异常
# WebDriverWait(driver, 5, 1).until(lambda current_driver: driver.find_element_by_xpath("//*[@content-desc='收起']"))


def element_wait(timeout, poll_frequency, element):
    WebDriverWait(driver, timeout, poll_frequency).until(lambda current_driver: driver.find_element(*element))


element_wait(5, 1, (By.XPATH, "//*[@content-desc='搜索设置']"))
element_wait(5, 1, (By.XPATH, "//*[@content-desc='收起']"))

time.sleep(3)
driver.quit()

隐式等待和显示等待的区别

  作用域不同

    显示等待作用于单个元素有效

    隐式等待作用于所有元素有效

   相同点:他们都是在找不到元素时触发元素等待

  方法不同

    显示等待方法封装在WebDriverWait类中

    隐式等待直接通过driver.implicitly_wait()方法来设置

  抛出的异常不用

    隐式等待超时没有找到,会抛出NoSuchElementException异常

    显示等待超时没有找到,会抛出TimeoutException异常

元素操作方法

点击元素

# 对元素进行点击操作
element.click()

输入和清空输入框内容

# 对文本框进行输入内容操作
element.send_keys(value)
# 对文本框进行清空内容操作
element.clear()

获取元素的文本内容

  比如:按钮、文本框、输入框等控件可以获取它们的文本内容

# 通过text属性获取元素的文本内容
element.text

获取元素的位置和大小

# 获取元素的位置
element.location
# 获取元素的大小
element.size

获取元素的属性值

  当定位到元素后,想要使用元素的属性信息时,此时就要获取元素的属性值了。

# 根据属性名获取属性值,value表示属性名
element.get_attribute(value)

示例:

import time

from appium import webdriver

# 封装启动app的参数
desired_capabilities = {
    "platformName": "Android",
    "platformVersion": "7.1",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    "appActivity": ".Settings",
    # 设置支持中文输入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 连接appium服务器,并创建驱动对象
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)

search_button = driver.find_elements_by_id("com.android.settings:id/search")
# 点击操作
search_button.click()

search_text = driver.find_element_by_class_name("android.widget.EditText")
# 根据属性名获取属性值, resourceId:获取resource_id属性对应的值
resource_id = search_text.get_attribute("resourceId")
print(resource_id)
# 对文本框进行输入内容操作
search_text.send_keys("显示")
# 通过text属性获取元素的文本内容
element = search_text.text
print(element)
# 对文本框进行清空内容操作
search_text.clear()

back_button = driver.find_element_by_class_name("android.widget.ImageButton")
# 根据属性名获取属性值, name:获取text或content-desc属性对应的值
name = back_button.get_attribute("name")
print(name)
# 获取元素的位置
location = back_button.location
# 获取元素的大小
size = back_button.size
print("location:", location)
print("size:", size)

time.sleep(3)
driver.quit()

滑动和拖拽操作

  在做自动化测试中,有些元素需要滑动几次屏幕后才会发现,才能进行定位元素的,此时需要用到滑动或者拖拽操作。

滑动操作方法

swipe()方法:

   根据开始和结束的坐标点进行滑动

  语法:

driver.swipe(开始x坐标, 开始y坐标, 结束x坐标, 结束y坐标, 滑动这次操作共持续的时间(毫秒))

scroll()方法:

   根据开始元素位置和结束元素位置进行滑动

 语法:

driver.scroll(开始元素, 结束元素, 滑动这次操作共持续的时间(毫秒))

  提示:这个两个方法都用滑动惯性,想要滑动的惯性小,把持续时间设置大一些,比如: 5000毫秒

拖拽操作方法

drag_and_drop()方法:

   根据两个元素的位置进行滑动,从第一个元素的位置滑动到第二个元素的位置。

 语法:

driver.drag_and_drop(开始元素, 结束元素)

  提示: 这个drag_and_drop没有滑动惯性,没有持续时间参数。

为了更好的看到滑动效果,建议开启指针,开启指针位置(模拟器):

  1、打开设置,找到关于平板电脑,点击进去

  2、找到版本号,连点5下,方可打开开发者模式

  3、回到设置界面,点击开发者选项

  4、找到输入 --> 指针位置,开启该功能即可

示例:

import time

from appium import webdriver

# 封装启动app的参数
desired_capabilities = {
    "platformName": "Android",
    "platformVersion": "7.1",
    "deviceName": "127.0.0.1:62001",
    "appPackage": "com.android.settings",
    "appActivity": ".Settings",
    # 设置支持中文输入
    "unicodeKeyboard": True,
    "resetKeyboard": True
}
# 连接appium服务器,并创建驱动对象
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)


def swipe_operation(start_x, start_y, end_x, end_y, duration=0):
    driver.swipe(start_x, start_y, end_x, end_y, duration)


# swipe_operation(200, 300, 200, 1000)
# swipe_operation(200, 1000, 200, 300, 3000)

window_size = driver.get_window_size()
print(window_size)
x = window_size["width"] / 2
start_y = window_size["height"] / 4 * 3
end_y = window_size["height"] / 4
swipe_operation(x, start_y, x, end_y)


show_control = driver.find_element_by_xpath("//*[@text='显示']")
wallpaper_control = driver.find_element_by_xpath("//*[@text='更换壁纸']")

# scroll:两元素之间的滑动,有惯性
# driver.scroll(show_control, wallpaper_control)
driver.scroll(show_control, wallpaper_control, 3000)


# drag_and_drop:两元素之间的拖拽,无惯性
driver.drag_and_drop(show_control, wallpaper_control)

time.sleep(3)
driver.quit()

滑动和拖拽方法的选择

  有惯性
   坐标之间滑动使用:swipe()方法
   元素之间滑动使用:scroll()方法
  无惯性
   元素之间拖拽使用:drag_and_drop()方法

测试设置界面的搜索功能

"""
需求:
    利用pytest框架完成自动化测试设置界面的搜索功能
	测试数据为: 电池、WLAN
"""
import time
import pytest

from appium import webdriver


class TestSettingSearch:
    data_list = [
        {"search_data": "电池", "except_value": True},
        {"search_data": "WLAN", "except_value": True},
        {"search_data": "ee", "except_value": False}
    ]

    def setup(self):
        # 封装启动app的参数
        desired_capabilities = {
            "platformName": "Android",
            "platformVersion": "7.1",
            "deviceName": "127.0.0.1:62001",
            "appPackage": "com.android.settings",
            "appActivity": ".Settings",
            # 设置支持中文输入
            "unicodeKeyboard": True,
            "resetKeyboard": True
        }
        # 连接appium服务器,并创建驱动对象
        self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities)
        # 设置隐式等待
        self.driver.implicitly_wait(2)

    def teardown(self):
        time.sleep(3)
        self.driver.quit()

    @pytest.mark.parametrize("data", data_list)
    def test_search_value(self, data):
        print("数据为:", data)
        # 定位放大镜控件
        self.driver.find_element_by_id("com.android.settings:id/search").click()
        # 定位搜索框
        search_text = self.driver.find_element_by_id("android:id/search_src_text")
        # 向搜索框输入内容
        search_text.send_keys(data["search_data"])

        search_content = self.driver.find_elements_by_id("com.android.settings:id/title")
        if data["except_value"]:
            assert len(search_content) > 0
        else:
            assert len(search_content) == 0


if __name__ == '__main__':
    pytest.main(["-sv", "--alluredir=allure_data", "--clean-alluredir"])
    # 生成测试报告命令
    # allure generate allure_data --clean
原文地址:https://www.cnblogs.com/lyang-a/p/15100330.html