adb 调试工具
adb工作原理
概念
adb全面Android Debug Bridge ,是一个调试工具
adb构成和工作原理
adb包含3部分
- client : 运行在开发机器中,用来发送adb命令
- daemon守护进程:运行在调试设备中,手机或者模拟器,用来接受并执行adb命令
- server:同样运行在开发机器中,用来管理client和daemon之间的通信
adb 常用命令
adb devices - 列出当前连接的设备
adb shell - 进入设备的shell命令行界面
adb shell dumpsys window windows - 获取所有包名
1
2mFocusedApp=AppwindowToken{53309da token=Token{2e2fa785
ActivityRecord{2928d4fc uo com.android.settings/.settingst 1127333}}}包名:com.android.settings (决定唯一性)
界面名:.settings (一个界面对应一个界面名,类似于命名空间)adb shell am start -w 包名/界面名 - 获取app启动时间
- ThisTime:界面启动耗时(ms)
- TotalTime:应用自身启动耗时 = ThisTime + 应用application等资源启动时间(ms)
- waitTime:系统启动应用耗时 = TotalTime + 系统资源启动时间(ms)
adb install <apk文件路径> - 安装应用程序到设备
adb uninstall <包名> - 卸载应用程序
adb pull <设备文件路径> <保存到本地的路径> - 从设备中拷贝文件到本地
adb push <本地文件路径> <设备文件路径> - 将本地文件推送到设备
adb logcat - 查看设备的日志信息
- 关于发生崩溃的时候,需要找到日志中”at” 前面,第一个字符是E的就是错误信息
adb backup - 备份应用程序和数据
adb restore - 恢复应用程序和数据
adb reboot - 重启设备
adb-Monkey
Monkey是Android平台上一个用于自动化压力测试和UI测试的命令行工具。
- adb shell monkey -p <包名> <事件数量> - 对指定包名的应用程序执行指定数量的随机事件
- adb shell monkey -p <包名> –pct-touch <触摸事件的百分比> –pct-motion <滑动事件的百分比> - 指定触摸事件和滑动事件的百分比,并对应用程序执行随机事件
- adb shell monkey -p <包名> -v <事件数量> - 显示详细的事件信息
- adb shell monkey -p <包名> -s <种子值> <事件数量> - 使用指定的种子值来执行随机事件
- adb shell monkey -p <包名> –throttle <延迟时间> - 设置事件之间的延迟时间,以便模拟用户的操作速度
- adb shell monkey -p <包名> -f <脚本文件> <事件数量> - 使用指定的事件脚本文件来执行事件
appium
环境安装
从2022年1月1号开始,Appium核心团队不会再维护Appium 1.x版本了
当您安装Appium 1.x时, 所有可用的驱动程序将与主Appium Server同时安装
在Appium V2版本中驱动和Appium Server是分开的,驱动可以分开安装和升级
安装Appium 2.0 (例如, 通过npm install -g appium
) , 将只安装Appium Server, 但没有驱动程序. 要安装驱动程序
安装jdk环境+ sdk环境
安装appium - 开源跨平台,支持IOS,Android
客户端安装
node 包管理工具 npm安装 appium server
1
$ npm install appium -g
appium 驱动安装
设置环境变量,跳过chrome 安装(会自动安装,国内下载不了,直接跳过)
uiautomator2 - 安装UIAutomator2,用于安卓设备的驱动程序
1
$ appium driver install uiautomator2
images - 图像识别 (不低于16 node版本)
1
$ appium plugin install images
XCUITest - 安装XCUITest,用于iOS设备的驱动程序。
1
$ appium driver install xcuitest
检查安装 - appium driver list
安装appium-inspector - appium可视化界面(主要是用于元素定位) ; 或者使用web版Appium Inspector by Appium Pro,但需要注意开启cors跨域 –allow-cors
模拟器
第三方库appium-python-client
appium 2.0 使用
appium启动命令
1 | # 启动appium 并使用images插件 |
基础python代码 - 图片识别案例
1 | import os |
基础API
应用跳转
1 | driver.start_activity(appPackage, appActivity) |
元素定位
- ID: 通过元素的唯一标识符进行定位。
- XPath: 通过 XML 路径语言定位元素。XPath 允许使用复杂的路径表达式来查找元素。
- Accessibility ID: 使用可访问性标识符定位元素,特别适合于 iOS 和 Android 应用。
- Class Name: 根据元素的类名定位。
- Name: 通过元素的名字定位,这通常用于 iOS 应用。
- CSS Selector: 使用 CSS 选择器定位元素(主要用于 Web 测试)。
- Android UI Automator: 适用于 Android 应用的特定定位方式。
- iOS Predicate: 适用于 iOS 应用的复杂查询。
1 | from appium.webdriver.common.appiumby import AppiumBy |
元素操作
- 点击 (Click): 使用
.click()
方法模拟用户点击。 - 输入 (Send Keys): 使用
.send_keys()
方法输入文本。 - 获取文本 (Get Text): 使用
.text
属性获取元素的文本内容。 - 获取属性 (Get Attribute): 使用
.get_attribute()
方法获取元素的属性值。 - 获取元素尺寸 (Get Size): 使用
.size
属性获取元素的尺寸。 - 获取位置 (Get Location): 使用
.location
属性获取元素的位置坐标。 - 拖动 (Drag and Drop): 通过拖放操作可以模拟用户的拖动行为。
- 滑动 (Swipe): 在触摸屏设备上,可以通过手势操作模拟滑动。
- 捏合(Pinch) : 两个手指的放大或缩小手势
可以对拖动,滑动,捏合进行封装,能够达到简写方式
1 | # 元素点击 |
动态元素
等待 (Wait): 使用显式等待 (
WebDriverWait
) 或隐式等待来等待元素出现或满足条件。显式等待 (
WebDriverWait
): 显式等待是在代码中定义等待条件,直到某个条件成立或者超时1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
'''
WebDriverWait(driver, 10) 创建一个等待实例,最多等待 10 秒。
EC.visibility_of_element_located 是等待条件,表示等待指定 ID 的元素可见。
wait.until() 方法会等待条件满足或超时。
'''
# 创建显式等待示例
wait = WebDriverWait(driver, 10) # 最多等待 10 秒
# 等待元素可见
element = wait.until(EC.visibility_of_element_located((MobileBy.ID, 'com.example:id/dynamicElementId')))
# 当元素可见时进行操作
element.click()
# 简写
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "element_id"))
).click()隐式等待:隐式等待是在查找元素时,Appium 会在指定的时间内等待元素出现。隐式等待通常设置一次,然后应用于所有的元素查找操作。
1
2
3
4
5
6
7
8
9
10'''
driver.implicitly_wait(10) 设置driver隐式等待时间为10秒,后期都生效
在查找元素时,如果元素没有立即找到,Appium 将会等待最多 10 秒。
'''
# 设置隐式等待时间
driver.implicitly_wait(10) # 最多等待 10 秒
# 查找元素
element = driver.find_element(MobileBy.ID, 'com.example:id/dynamicElementId')
# 进行操作
element.click()强制等待: 直接使用sleep() , 让程序暂停一段时间
1
2import time
time.sleep(1) # 单位s
轮询 (Polling): 通过不断循环来判断元素状态来处理可能延迟出现的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 轮询检查元素是否可见
timeout = 10
start_time = time.time() # 记录时间点
while True:
try:
element = driver.find_element(MobileBy.ID, 'com.example:id/dynamicElementId')
if element.is_displayed():
print("Element is visible")
break
except:
pass
elapsed_time = time.time() - start_time # 当超过时间点,则跳出循环
if elapsed_time > timeout:
print("Timeout waiting for element")
break
time.sleep(0.5) # 每 0.5 秒轮询一次重试 (Retry): 在执行操作之前重试定位,以应对元素状态变化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# 定义重试次数
max_retries = 5 # 最大重试次数
attempts = 0 # 当前重试次数
element = None # 记录元素的变量
while attempts < max_retries:
try:
# 尝试定位元素
element = driver.find_element(MobileBy.ID, 'com.example:id/dynamicElementId')
if element.is_displayed():
print("Element found and is visible")
break
except NoSuchElementException:
print("Element not found, retrying...")
attempts += 1
time.sleep(2) # 等待 2 秒后重试
if not element: # 当变量还是为None时,则提出错误
print("Failed to find element after several retries")
# 如果元素进行操作
if element:
element.click()
元素交互
链式操作 (Chained Actions): 通过 Action Chains 支持多步操作,如拖放、点击和移动。
1
2
3
4
5
6
7
8
9
10
11
12
13from appium.webdriver.common.touch_action import TouchAction
# 创建 TouchAction 实例
action = TouchAction(driver)
# 链式操作: 拖放
action.press(source_element).wait(1000).move_to(target_element).release().perform()
'''
TouchAction 用于定义手势操作。
press():按下源元素。
wait(1000):等待 1000 毫秒。
move_to():移动到目标元素。
release():释放动作。
perform():执行整个操作链。
'''上下文切换 (Context Switch): 在混合应用(如包含 WebView 的应用类似于web的iframe)中切换上下文来执行操作。
1
2
3
4
5
6
7
8
9
10
11
12contexts = driver.contexts
print(contexts) # 输出上下文列表
# 切换到 WebView 上下文
driver.switch_to.context('WEBVIEW_com.example')
# 执行 Web 操作
web_element = driver.find_element(MobileBy.CSS_SELECTOR, 'button')
web_element.click()
# 切换回原生上下文
driver.switch_to.context('NATIVE_APP')
应用操作
源码:~/appium/webdriver/extensions/application.py
- driver.background_app(time) - 将应用挂入后台一段时间
- driver.is_app_installed(app_id) - 检查是否安装了某个应用程序
- driver.install_app(path) - 安装应用程序
- driver.remove_app(app_id) - 删除应用程序
- driver.terminate_app(app_id) - 终止程序
- driver.activate_app(app_id) - 启动或者将后台唤醒
- driver.query_app_state(app_id) - 检查程序状态
- driver.driver.current_url() - 获取当前url
- driver.current_window_handle() - 返回当前窗口句柄
- driver.window_handles() - 返回所有句柄
- driver.close() - 关闭当前窗口
- driver.quit() - 退出程序驱动,并关闭全部窗口
- driver.save_screenshot(filename) - 将当前窗口保存为png格式图片,返回布尔值
- driver.get_screenshot_as_png() - 以二进制数据形式返回当前窗口截图
- driver.get_screenshot_as_base64() - 以base64数据形式返回当前窗口截图
- driver.execute_scipt() - 执行javascript代码; 例如返回设备信息:device_info = driver.execute_script(“mobile: deviceInfo”) ;移动到指定坐标:driver.execute_script(‘mobile: touch:tap’, {‘x’: 100, ‘y’: 200}) ; 获取网络状态:network_status = driver.execute_script(‘mobile: networkConnection’)
- session_id = driver.session_id - 获取会话id
appium服务器操作
- get_status() - 获取appium服务器状态
- start_session() - 创建一个含有新功能的新会话
appium2.0 新特性和扩展
插件架构 (Plugin Architecture): 允许用户添加自定义插件来扩展功能。
插件架构是 Appium 2.0 的一项重要特性,它允许用户通过安装自定义插件来扩展 Appium 的功能。插件可以添加新的命令、修改现有功能,或者与其他工具和服务进行集成。
可扩展性: 通过插件架构,用户可以根据特定的需求扩展 Appium 的功能,而不需要直接修改 Appium 的核心代码。
社区插件: Appium 社区和开发者可以发布和分享插件,使得其他用户可以利用这些插件来满足特定的测试需求。
插件管理: 提供了方便的命令行工具来安装、卸载和管理插件。
插件安装:
- 安装插件:
1
appium plugin install <plugin-name>
- 列出已安装插件:
1
appium plugin list
- 卸载插件:
1
appium plugin uninstall <plugin-name>
增强的 CLI (Command Line Interface): 提供了更强大的命令行工具,便于操作和调试。
Appium 2.0 的 CLI 工具进行了显著的增强,使得用户可以更方便地操作和调试 Appium 服务器及其相关功能
常用命令示例
启动 Appium 服务器:
1
appium
启动带有特定配置的 Appium 服务器:
1
appium --use-plugins <plugin-name>
查看 CLI 选项:
1
appium --help
改进的服务器配置 (Server Configuration): 提供更灵活的配置选项,以适应不同的测试需求。
使用环境变量配置:
1
2export APPIUM_LOG_LEVEL=debug
appium使用配置文件:
可以创建一个 JSON 格式的配置文件
appium-config.json
来定义服务器参数。例如:1
2
3
4
5{
"logLevel": "debug",
"port": 4723,
"usePlugins": ["appium-device-config-plugin"]
}然后通过以下命令启动 Appium 服务器:
1
appium --config appium-config.json
示例:
如果你需要调整日志级别和启用某些插件,可以通过环境变量和配置文件来实现。例如,将日志级别设置为
debug
并启用appium-device-config-plugin
插件:1
2export APPIUM_LOG_LEVEL=debug
appium --use-plugins appium-device-config-plugin
对于Android一些特别包名和操作
设置 (Settings)
1 | appPackage = 'com.android.settings' |
通讯录 (Contacts)
1 | appPackage = 'com.android.contacts' |
电子邮件 (Email)
1 | appPackage = 'com.android.email' |
短信 (SMS)
1 | appPackage = 'com.android.mms' |
电话 (Dialer)
1 | appPackage = 'com.android.dialer' |
设置为主屏幕 (Home)
如果您想直接返回主屏幕,您可以使用以下代码:
1 | driver.start_activity(package='com.android.launcher', activity='.Launcher') |
示例:返回主屏幕
如果您想在 Appium 测试完成后返回主屏幕,可以使用以下示例代码:
1 | # 返回主屏幕 |
使用 start_activity
也可以用 start_activity
来直接启动特定的应用:
1 | driver.start_activity(appPackage, appActivity) |