你好,哈克农!我叫 Alexander Karpenko,在inDrive担任 QA 工程师。我为新手 QA 专家准备了这篇文章。下面,我将告诉您如何在移动应用程序测试中使用Android Debug Bridge (ADB) 以及为什么首先需要它。
我想你已经具备了测试基础的基本知识,所以我将跳过准备和设置项目的过程。
ADB 的功能在不断扩展,但我将分享一些可以改善您的日常工作流程的有价值的技术。由于我的故事是关于移动应用程序测试的,因此我将专注于 macOS,它可以让您有效地使用所有流行的移动平台。对于其他操作系统,这些示例可能略有不同,但希望 Windows 用户不会反对我。
首先,让我们接触最基本的命令,以确保后面的点按逻辑顺序呈现。
通常,我们使用一台设备,但有时会连接多个设备,例如通过 TCP/IP。在这种情况下,我们必须手动指定要在其上运行命令的设备。
adb devices
— 显示已连接设备的列表(使用-l
开关拉出扩展的属性列表)。如果连接了多个设备并且我们无法立即清楚我们需要哪一个,这将非常有用。
要告诉 ADB 以哪个设备为目标,必须在-s
开关后指定设备的序列号:
adb -s <serial_number> <command>
,其中<serial_number>
是列表中设备的序列号, <command>
是要在设备上执行的命令。
例如,在列表中的特定设备上安装应用程序:
adb -s 32312b96 install user/download/app.apk
另一种常见的情况是当操作同时涉及真实设备和仿真器时,例如,执行者/发起者的不同角色。在这种情况下,设备不是通过它们的序列号而是基于 adb 命令后的—d —e
开关很容易区分的。例子:
adb —d install user/download/app.apk
- 该命令将在真实设备上执行,在模拟器上使用—е
开关。
当设备使用相同的 Wi-Fi 网络时,我们也可以通过 TCP/IP 连接到设备。为此,请使用电缆将设备连接到 PC,并使用以下命令将设备上的操作模式从 USB 更改为 TCP/IP:
adb tcpip 5555
例如,通过通用信息中的电话设置或使用以下命令:
adb shell ifconfig wlan0
如果此时您的设备已与 PC 断开连接,请务必另外指定设备的 S/N。接下来,我们连接到它:
adb connect ip_address:5555
可以使用以下命令禁用设备:
adb disconnect ip_address:5555
adb disconnect
— 禁用我们所有的 TCP/IP 设备。
要返回 USB 模式,请使用以下命令:
adb usb
(小写很重要)。
该应用程序使用以下命令安装:
adb install <apk_path>
,其中<apk_path>
是我们的 APK 应用程序文件的绝对路径。
以下是一些常用的 install 命令后的有用开关:
—d
— 使用降级版本重新安装。否则会出现故障(错误) [INSTALL_FAILED_VERSION_DOWNGRADE]
)。
—r
- 重新安装应用程序并保存数据。
—g
— 在安装过程中授予应用程序清单中指定的所有权限。
例如,使用此开关安装的应用程序不会要求您允许访问地理位置或存储空间以下载照片。
根据包的名称卸载应用程序。为此,您需要知道应用程序是如何在系统中注册的。使用 Shell 和包管理器 (pm)。
运行以下命令以显示所有已安装应用程序的列表:
adb shell pm list packages
该列表可以按应用程序名称过滤。如果列表很大,您将需要它,但我们知道包名称中包含哪个单词:
adb shell pm list packages | grep com.myApp
您还可以输出到单独的文件并在那里找到所需的包:
adb shell pm list packages > /Users/username/packages.txt
现在我们知道了如何找出应用程序包的名称,让我们回到如何从设备中删除它。这可以使用以下命令完成:
adb uninstall com.myApp
adb uninstall -k com.myApp
— 删除应用程序但保存数据和缓存文件。
我将分别展示一个可能经常被证明有用的命令:
adb shell pm clear com.myApp
— 清理应用程序的缓存和数据。
我认为这是一种罕见的情况。但这对某人来说可能会派上用场,就像曾经对我一样。所有已安装的应用程序都将其 APK 文件存储在 /data/app 文件夹中。由于您知道包的名称,因此您可以找到应用程序的安装位置并从那里下载其 APK。为此,请运行以下命令:
adb shell pm path com.myApp
— 显示应用程序的安装目录。
这可能看起来并不那么像样:
package:/data/app/~~YcTsnr19yQR6ENa0q2EMag==/com.myApp—IHasf91SDB0erQLagc8j0Q==/base.apk
但这正是我们需要这条路的样子。让我们先略过一点,看看如何将我们需要的文件从手机复制到 PC。这可以使用以下命令完成:
adb pull <crazyPath> /Users/username/
,其中<crazyPath>
是我们之前命令的输出, /Users/username/
是您要将文件复制到的 PC 上的路径。
让我们简单谈谈检查文本字段。例如,您必须检查可以在文本字段中输入的最大字符数限制。如果您使用单个设备,则可以将不同的传输数据集存储在手机或云中。但是,如果必须在不同的设备上进行测试,可以将测试数据存储在 PC 上并通过以下命令传输到设备:
adb shell input text <text>
例子:
adb shell input text test%stest
— 将输入字符串“test test”。用特殊字符%s
替换空格,否则,只会将空格前面的部分发送到设备。如果我们在传输的文本中使用像!@#
这样的特殊字符,则必须通过在它们前面插入反斜杠 ( \
) 来标记它们。
例如,命令:
adb shell input text test\!\@\#\$%stest
将在屏幕上显示“test!@#$ test”
(ADB 不适用于西里尔字符并生成 NullPointerException 错误)。
剪贴板的内容可以这样传输:
adb shell input text $(pbpaste)
请记住,某些字符可能无法传输,因为它们出现在 PC 上。该问题可以通过使用流式文本编辑器 (sed) 来解决。这是一个扩展命令的示例,我们将缓冲区中的所有空格替换为我们需要的特殊字符,以确保以正确的方式将文本传输到设备:
adb shell input text $(pbpaste | sed -e 's/ /\%s/g')
pbpaste
是缓冲区中包含的文本。
”—e”
开关—允许您执行编辑文本所需的命令。
“s/take this/change_it_to/option”
是要使用的模板(模式)。
/g
是替换特定模板的所有匹配项的标志,无一例外。
请记住,最好在尽可能接近现实生活的环境中进行测试,但知道此选项也可用是有帮助的。
此策略将帮助您检查所需屏幕的深层链接,使用多个屏幕时,或者我们的基础设施有问题并且没有推送通知通过,或者如果它们都没有到达,但您需要检查如何应用程序的行为。
您还可以检查应用程序是否正常工作,并且在推送通知警报中出现无效的深层链接时是否会崩溃。或者在处理我们点击一个不再存在的屏幕的深层链接的情况时,或者它的状态已经改变,或者如果我们一开始就不应该访问那个屏幕,因为推送警报已经在很长一段时间的通知。这样的情况可能很多。
在 Shell ADB 中,我们可以使用 Activity Manager (AM) 来执行命令。
我们开始我们的活动并发送我们想要检查的深层链接。深层链接通常包含分隔屏幕的字符“&”。因此,当通过终端打开时,必须在其前面插入一个反斜杠 (\)。
adb shell am start -W -a android.intent.action.VIEW -d “myApp://open/client/trip\&last_trip=test” com.myApp
am
— 调用活动管理器。
W
— 在执行命令之前等待下载。
a
— 确定要采取的行动。在这种情况下,它是action.View 。
d
— 运行所需的数据。在这种情况下,我们谈论的是深层链接本身,然后是应该用来打开它的应用程序。
将命令传输到终端时,您可能必须手动重新插入引号或用单引号替换它们。如果存在语法错误,您可能会收到相应的消息。
使用此命令截取屏幕截图:
adb shell screencap -p <device_path/screenshot_name.png>
例子:
adb shell screencap -p /sdcard/screencap.png
— 截取屏幕截图并将设备上名为screencap.png
的文件保存到/sdcard/screencap.png
文件夹。
您可以将屏幕截图保存在您的计算机上,如下所示:
adb pull /sdcard/screencap.png
- 默认情况下,该文件被复制到当前用户的目录,即/Users/username/screencap.png
。
或者您可以一次运行整个命令:
adb shell screencap -p /sdcard/screencap.png && adb pull /sdcard/screencap.png
在最新版本的 ADB 中,可以使用以下命令获取屏幕截图:
adb exec—out screencap —p > screen.png
截图文件也会出现在PC上当前用户的目录下。
可以通过在命令末尾添加来手动更改默认路径:
adb exec—out screencap -p > downloads/test/screen.png
— 屏幕截图将出现在/Users/username/downloads/test/screen.png
文件夹中。
如果有兴趣,您还可以通过向bash_profile
添加别名来稍微自动化此过程。在 macOS 中,您可以使用 Automator 服务来创建和设置热键。
使用此命令录制视频:
adb shell screenrecord device_path
。
例子:
adb shell screenrecord /sdcard/screenrecord.mp4
— 使用该命令开始根据默认设置录制设备屏幕三分钟,并将结果保存到设备上的文件/sdcard/screenrecord.mp4
。
您可以使用—time—limit time
开关手动指定录制时间(以秒为单位,但录制时长仍限制为180秒)。
按CTRL + C
可以提前停止录制
也可以使用 pull 命令复制该文件,方法与截屏过程类似。
您还可以使用--help
开关查看此实用程序的附加功能。顺便说一句,它能够更改录制分辨率和比特率,以及为错误报告添加额外数据。
使用-bugreport
开关会很有帮助,它会将有关用于录制的系统的信息添加为视频中的第一帧。
现在我们已经介绍了如何从设备下载一些内容,让我们稍微关注一下如何向设备上传内容。
我们在 PC 上打开它,调整格式和内容,下载到我们的手机,并检查以确保应用程序正确响应未知格式和超大限制。要将文件从 PC 上传到手机,您可以使用以下命令:
adb push /Users/username/file <device_path>
让我们运行命令:
adb push /Users/username/screen.png sdcard
— 这会将我们的screen.png
文件复制到手机的 SD 卡中。
另一个经验示例涉及检查应用程序的状态是否在系统删除后已恢复。折叠应用程序,终止进程 - 此操作模拟系统因为没有足够的可用内存而停止进程时的情况:
adb shell am kill com.myApp
再次运行它并检查是否一切正常。
我们遇到了这种情况:用户在某个屏幕上最小化应用程序。一段时间后,系统会减慢进程并缓存其状态。当用户尝试扩展应用程序时,它会崩溃。当访问缓存中的数据时会发生这种情况,因为片段正在恢复它们的堆栈和状态,但缓存已经是空的。不幸的是,这个错误在测试阶段被忽略了,因为我们之前没有遇到过它,所以它最终在生产中。现在您知道这是可能的,您可以确保不会重复我们的错误。
在尝试找出导致应用程序崩溃的原因时检查日志是个好主意。如果要保存当前的日志缓冲区内容,可以使用以下命令来完成:
adb logcat
— 实时显示日志。
adb logcat —d
— 显示命令运行时的日志信息,而不在设备上添加真实事件。也可以使用以下命令将日志输出到单独的文件: adb logcat —d > file.log
(该文件在当前用户的目录中创建)。
并且命令adb logcat >> file.log
会将日志直接写入文件,添加设备上的所有真实事件。
有几个级别按优先级升序排列:V - 详细,D - 调试,I - 信息,W - 警告,E - 错误,F - 致命,S - 静音,例如:
adb logcat '*:E'
- 将输出带有错误和更高级别的日志。
现在让我们简要介绍一下输出格式和过滤器。您可以使用 -v 开关更改输出到控制台的格式,例如:
adb logcat -v time
— 通过记录时间点顺序输出日志。
adb logcat -v color
— 以不同的颜色显示每个级别的日志(这在阅读时很有帮助)。
adb logcat -v brief
— 显示进程优先级、标记和 PID。
每条日志消息都有一个标签及其相关的优先级。您可以使用它们来减少控制台的输出量:
adb logcat SwrveSDK:I '*:S'
— 将显示我们通过 swrve 服务发送的分析事件。 *:S (-s)
参数表示日志输出仅限于我们明确指定的过滤器表达式。
和往常一样,您可以使用 grep 实用程序来过滤输出:
adb logcat '*:E' —v color | grep com.myApp
传统上,要了解更多信息,您可以随时求助于您的助手adb logcat --help
例如,如果在未连接设备的情况下重现错误,您可以立即连接它并将日志重定向到文件。
为了进一步调试,在收集日志之前,可以在重现bug前预先清空日志缓冲区,消除多余数据。这可以通过以下命令完成:
adb logcat —c
,然后我们重现错误并运行adb logcat —d
对于那些喜欢挖掘成堆日志的人来说,还有另一个工具可以考虑——ADB bugreport。此工具允许您创建带有纯文本格式 ( .txt
) 的完整调试信息的 zip 存档。
adb bugreport /Users/username
— 在指定目录中创建一个 zip 存档。
将有关设备的所有信息,例如dumpstate、dumpsys 和logcat 数据复制到指定文件夹。默认情况下,错误报告存储在 /bugreports 中,可以通过以下方式查看:
adb shell ls /bugreports/
对我们来说最重要的信息存储在bugreport-BUILD_ID-DATE.txt
崩溃监控和 ANR(应用程序无响应)是另一个用于处理崩溃的有趣工具。使用以下命令运行它:
adb shell am monitor
,然后我们重现我们的崩溃。控制台将显示有关崩溃的信息,没有任何多余的细节和三个选项以继续我们的监控工作: (c)ontinue: show crash dialog, (k)ill: immediately kill app, (q)uit: finish monitoring
。
显示配置的模拟器列表:
emulator -list-avds
运行我们需要的模拟器:
emulator @avdname
使用模拟器时,有时需要重新启动服务,并且一旦模拟器启动,服务器必须重置,但通常一个命令就足够了: adb kill-server
。如果这没有帮助,则运行整个脚本:
emulator -list-avds
— 显示配置的模拟器列表。
adb kill-server
— 停止服务器。
emulator -avd avdname
(或emulator @avdname
)— 其中avdname
是模拟器的名称。
adb start—server
— 重新启动服务器。
adb devices
— 显示我们丢失的模拟器应该出现的连接设备列表。
对于你们当中最懒惰的人,可以从命令行创建一个模拟器。例如,以下命令使用具有 API 25 的 x86 系统映像创建一个名为“test”的模拟器:):
avdmanager create avd —n test —k "system—images;android—25;google_apis;x86"
如果所需的映像不可用,您可以使用以下命令预安装它:
sdkmanager --install "system—images;android—25;google_apis;x86"
sdkmanager --list | grep system—images
— 显示可供下载的图像列表
对于模拟器,在运行过程中有时也会出现“幻像”问题,一个常用的命令是在不启动自动快照的情况下“冷启动”模拟器。输出的快照如下:
emulator @avdname —no—snapshot—load
以下是启动模拟器时要考虑的一些更有用的开关:
-no-snapshot-save
— 不会保存自动快照
-no-snapshot
— 不会下载或保存快照
如果模拟器仍然无法正常工作,可以使用将模拟器恢复到原始状态的开关来清除它: -wipe-data
快照创建是保存设备不同状态的一个非常有用的功能。手动,这可以通过模拟器设置或运行以下命令来完成:
adb emu avd snapshot save test
— 保存模拟器的状态,其中test是要存储在设备上的快照的名称
emulator @avdname —snapshot—list
— 运行我们的模拟器 @avd 并在控制台中显示快照列表
接下来,您可以使用以下命令加载以前保存的快照:
adb emu avd snapshot load test
— 其中test是之前保存的快照的名称
adb emu avd snapshot delete test
— 删除名为test的快照
也可以使用我们需要的快照立即运行模拟器:
emulator @avdname -snapshot test
您还可以使用pull
命令从设备获取快照:
adb emu avd snapshot pull test /Users/username/
我们的模拟器可以通过telnet
控制台进行操作。但首先你必须安装它。最简单的方法是通过brew
包管理器,如果你有的话。如果没有,那么是时候找出它是什么以及如何使用它了。因此,使用以下命令安装telnet
: brew install telnet.
接下来,运行我们的模拟器,并在终端的另一个选项卡中,使用以下命令连接到它: telnet localhost port,
示例:
telnet localhost 5554
— 连接到使用端口 5554 的模拟器
完成命令后,我们可以使用模拟器做各种有用的事情,包括使用 geo(例如,命令geo fix 40.748840 -73.984279
将在指定坐标处设置我们想要的位置)、网络或电池,而与往常一样,可以通过帮助找到完整的命令列表。
例如,快照的相同过程在某种程度上被简化了,而上一节中概述的命令被简化为avd snapshot <command>
。
窗口管理器 (wm) 有一些有用的命令来确保设备屏幕上的元素正确显示。它们允许您调整像素密度分辨率,以便您可以浏览所有必要的屏幕尺寸选项,并查看我们的应用程序将如何适应它们,而无需手头有适当数量的设备:
adb shell wm size 1080x1920
— 设置自定义屏幕分辨率,宽1080,高1920。
adb shell wm size reset
— 重置我们所有更改的设置。
adb shell wm density X
— 改变像素密度,其中最小值为 72。值越大,屏幕上的元素越大。
adb shell wm density reset
— 重置我们所有更改的设置。
如果我们在没有任何参数的情况下运行我们的命令,我们将返回所连接设备/模拟器的当前屏幕分辨率和像素密度。
另外,我们可以提到 Monkey - 一种在模拟器或设备上生成随机用户事件的工具,例如点击、敲击和手势,以及一些类似于傻猴子动作的系统级事件。 Monkey 可用于压力测试。
adb shell monkey
— 显示所有 Monkey 参数。
完整场景示例:
adb shell monkey ——throttle 100 ——pct—syskeys 0 —p com.myApp —v 10
--throttle
键——以毫秒为单位设置动作之间的延迟。由于 Monkey 执行所有动作的速度很快,因此当我们想要直观地控制屏幕上发生的事情时,通常会使用此开关(键)。
--pct-syskeys
键——定义在场景中将被按下的系统按钮的百分比。在此示例中,它设置为 0,这意味着不会按下任何系统按钮。
-p
开关 — 正在传输的数据包的名称
-v
开关 — 要执行的操作数
通常,这里涉及的操作意味着撤销应用程序权限,因为权限通常是通过应用程序请求授予的——这可以快速轻松地完成——而撤销权限是通过系统设置完成的。
adb shell dumpsys package com.MyApp | grep permission
— 显示可用应用程序权限的列表,例如, install permissions
— 安装应用程序时授予的强制权限, runtime permissions
— 在特定时刻(例如,访问文件存储时)请求的权限。请注意,如果请求的权限列表中缺少某个权限,您将无法授予对它的访问权限。
因此,必须运行以下命令来撤销我们应用程序的权限:
adb shell pm revoke packageName permissionName
,例如:
adb shell pm revoke com.MyApp android.permission.CAMERA
— 撤销com.myApp
对摄像头的访问。一旦我们返回应用程序并尝试通过它使用相机,我们将看到一个新的许可请求。
grant 命令授予应用程序权限,例如:
adb shell pm grant com.myApp android.permission.CAMERA
— 为我们的应用程序授予对手机摄像头的访问权限。
让我们在这里简要介绍一下电池和待机模式。
adb shell dumpsys battery
— 显示电池信息。
adb shell dumpsys battery set level X
— 设置电池充电水平,其中 X 是充电百分比。
adb shell dumpsys battery unplug
— 模拟电池拔出。
adb shell dumpsys battery reset
— 重置我们所有更改的设置。
现在让我们看看待机模式。从 Android 6 开始,有一个称为打盹模式的功能,用于在用户一段时间未与设备交互并且设备未充电时通过限制应用程序活动来节省电池电量并延长电池寿命。
系统会定期退出打盹模式以完成待处理的后台任务。 App Standby 是另一个类似的 Android 功能。与打盹模式不同,它会跟踪特定应用程序已空闲一段时间的状态,然后激活待机模式。我们的工作是确保应用程序在退出这两种省电模式后正常恢复,它不会崩溃,通知继续通过等等。
要将设备切换到打盹模式,请运行以下命令:
adb shell dumpsys battery unplug
— 拔下电池。
adb shell dumpsys deviceidle step
— 该命令可能必须执行多次,直到显示: Stepped to deep: IDLE
。
在我们用电池完成所有例程之后,最好运行命令:
adb shell dumpsys battery reset
— 将其恢复到原始状态。
此命令还可用于强制设备进入打盹模式:
adb shell dumpsys deviceidle force—idle
— 有时,在此之前,您必须运行命令: adb shell dumpsys deviceidle enable.
您可以使用以下命令从打盹模式重新激活它:
adb shell dumpsys deviceidle unforce
- 不要忘记重置电池状态:
adb shell dumpsys battery reset
。
现在稍微介绍一下 App Standby。要以这种模式部署应用程序,需要运行以下命令:
adb shell dumpsys battery unplug
— 与前一种情况一样断开电池。
adb shell am set—inactive com.myApp true
— 在 App Standby 模式下部署应用程序。
接下来,使用以下命令将我们的应用程序退出 App Standby 模式:
adb shell am set—inactive com.myApp false
。
您可以通过运行以下命令检查应用程序状态:
adb shell am get—inactive com.myApp
adb reboot
— 重启设备(也与真实设备相关)。
adb shell dumpsys package com.myApp
— 显示有关特定应用程序的完整信息。
adb shell dumpsys meminfo com.myApp
— 检查设备上应用程序的内存使用情况,从占用的空间到显示该应用程序使用的数据库以及它们的路径。
adb shell getprop
— 显示可用设备属性的列表(制造商、设备型号、硬件规格等)
显示应用程序可访问的活动列表:
adb shell dumpsys package com.myApp | grep —i Activity
。
显示正在运行的活动的名称:
adb shell dumpsys window | grep Focused
。
运行选定的应用活动:
adb shell am start —n com.myApp/.ActivityClass
— 这样您就可以运行任何已安装的应用程序,包括系统应用程序。示例: adb shell am start -n com.android.settings/.Settings 显示我们的手机设置。
拨打指定电话号码:
adb shell am start —a android.intent.action.CALL tel:+790900000XX
。
在您的网络浏览器中打开一个页面:
adb shell am start —a android.intent.action.VIEW 'https://indriver.com'
我想指出的是,不可能将 Android Debug Bridge 的所有功能都塞进一篇文章中,或者对它们进行彻底的研究。变化在不断发生:今天有效的东西明天可能突然停止工作,当我们寻找特定问题的解决方案时,对某些工具的知识的需求就会出现。但我可以自信地说,我们今天介绍的材料足以让你开始学习,然后继续学习一段时间。
祝您工作顺利,我希望您喜欢潜入激动人心的软件测试世界!