ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Playwright Android API 实战解析:设备连接、launchServer 与 WebView/Chrome 自动化

Playwright Android API 实战解析:设备连接、launchServer 与 WebView/Chrome 自动化 Playwright Android API 实战解析设备连接、launchServer 与 WebView/Chrome 自动化【免费下载链接】playwrightPlaywright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.项目地址: https://gitcode.com/GitHub_Trending/pl/playwrightPlaywright 提供了实验性的 Android 自动化支持可以驱动真机或 AVD 模拟器上的 Chrome for Android 与 Android WebView。本文基于仓库内的 API 文档docs/src/mobile-api/class-android.md结合packages/playwright-core/src/client/android.ts、packages/playwright-core/src/androidServerImpl.ts等源码与tests/android/下的测试用例完整讲解Android入口对象的四个方法devices/connect/launchServer/setDefaultTimeout的参数、默认值与底层实现帮助你在 CI 或本地环境把 Android 设备接入 Playwright 的测试与自动化体系。一、能力范围与前提条件文档明确标注Playwright 对 Android 的支持是experimental实验性的覆盖两个场景Chrome for Android—— 通过device.launchBrowser()获得标准BrowserContext之后与普通页面 API 完全一致Android WebView—— 通过device.webView({ pkg })拿到AndroidWebView再调用webview.page()获得标准Page对象。要跑通这套能力需要准备以下条件来自 class-android.md一台 Android 真机或 AVD 模拟器ADB daemon 正在运行且已与设备完成认证。通常执行一次adb devices即可设备上安装了 Chrome 87 或更新版本在chrome://flags中开启 Enable command line on non-rooted devices。已知限制文档同时列出了三条已知限制在方案评估时应直接纳入尚不支持原始 USB 操作一切底层操作都依赖 ADB设备必须处于唤醒状态才能产出截图建议开启开发者选项中的 Stay awake由于并非所有测试都在真机上跑过部分行为在真实设备上可能不可用。从源码结构看Playwright 通过 backendAdb.ts 直接调用 ADB 客户端接口执行runCommand/open默认连接127.0.0.1:5037——这与文档中 默认 host127.0.0.1、port5037 的说明完全对应。二、快速上手一个完整的 Android 自动化脚本文档给出的示例脚本同时演示了 WebView 与 Chrome 两条主线建议直接作为入门模板const { _android: android } require(playwright); (async () { // Connect to the device. const [device] await android.devices(); console.log(Model: ${device.model()}); console.log(Serial: ${device.serial()}); // Take screenshot of the whole device. await device.screenshot({ path: device.png }); { // --------------------- WebView ----------------------- // Launch an application with WebView. await device.shell(am force-stop org.chromium.webview_shell); await device.shell(am start org.chromium.webview_shell/.WebViewBrowserActivity); // Get the WebView. const webview await device.webView({ pkg: org.chromium.webview_shell }); // Fill the input box. await device.fill({ res: org.chromium.webview_shell:id/url_field, }, github.com/microsoft/playwright); await device.press({ res: org.chromium.webview_shell:id/url_field, }, Enter); // Work with WebViews page as usual. const page await webview.page(); await page.waitForNavigation({ url: /.*microsoft\/playwright.*/ }); console.log(await page.title()); } { // --------------------- Browser ----------------------- // Launch Chrome browser. await device.shell(am force-stop com.android.chrome); const context await device.launchBrowser(); // Use BrowserContext as usual. const page await context.newPage(); await page.goto(https://webkit.org/); console.log(await page.evaluate(() window.location.href)); await page.screenshot({ path: page.png }); await context.close(); } // Close the device. await device.close(); })();脚本要点入口是playwright包解构出的_android属性带下划线正是文档标注的实验性体现。从源码 playwright.ts 可以看到_android是Playwright对象上的只读属性this._android Android.from(initializer.android)WebView 部分先用device.shell(am ...)强制启动webview_shell应用再用device.fill/device.press操作 Android 原生控件最后webview.page()无缝切到标准页面 APIChrome 部分launchBrowser()返回的是持久化BrowserContextnewPage()/goto/evaluate/screenshot与桌面浏览器用法一致。三、API 逐项详解3.1Android.devices—— 枚举已连接设备since: v1.9返回AndroidDevice[]。这是最直接的入口Playwright 通过 ADB 枚举所有已连接设备。选项类型默认值说明hostsince v1.22string127.0.0.1建立 ADB server 连接的 hostportsince v1.20int5037建立 ADB server 连接的端口omitDriverInstallsince v1.21booleanfalse跳过连接时的自动 Playwright driver 安装假定 driver 已安装omitDriverInstall对 CI 场景很有价值driver 应用packages/playwright-core/src/server/android/driver下的 instrumented app只安装一次即可后续连接无需重复推送。从源码 android.ts 可以看到服务端正是依据this._options.omitDriverInstall决定是否执行安装逻辑。3.2Android.connect—— 连接远端 Android Serversince: v1.28返回单个AndroidDevice。它与launchServer配对使用服务端在目标机器上启动 Android Server 并打印wsEndpoint客户端可以是另一台机器、另一个容器、或 CI 节点通过 WebSocket 端点连接。参数说明参数类型默认值说明endpointstring必填要连接的 WebSocket 端点ws://host:port/wsPathheadersObjectstring, string无随 WebSocket 连接请求发送的附加 HTTP 头slowMofloat0人为放慢 Playwright 操作的毫秒数便于观察timeoutfloat3000030 秒建立连接的最长等待时间传0禁用超时从源码 client/android.ts 的connect实现可以确认几处文档未细说的行为连接请求会自动附带x-playwright-browser: android头再叠加用户传入的headers握手完成后客户端会校验对端返回的preConnectedAndroidDevice如果缺失会直接抛出Malformed. Did you use Android.launchServer method?并断开连接——即该端点必须是launchServer生成的不能拿chromium.launchServer的端点来连若超过timeout未完成握手会抛出Timeout xxxms exceeded且测试 launch-server.spec.ts 中专门验证了这条错误信息android.connect: Timeout 2000ms exceeded。3.3Android.launchServer—— 启动可被连接的 Android Serversince: v1.28返回BrowserServer。用于把设备托管起来供远端connect。仓库文档给出的 Server/Client 双侧示例如下Server 侧const { _android } require(playwright); (async () { const browserServer await _android.launchServer({ // If you have multiple devices connected and want to use a specific one. // deviceSerialNumber: deviceSerialNumber, }); const wsEndpoint browserServer.wsEndpoint(); console.log(wsEndpoint); })();Client 侧const { _android } require(playwright); (async () { const device await _android.connect(wsEndpoint); console.log(device.model()); console.log(device.serial()); await device.shell(am force-stop com.android.chrome); const context await device.launchBrowser(); const page await context.newPage(); await page.goto(https://webkit.org/); console.log(await page.evaluate(() window.location.href)); await page.screenshot({ path: page-chrome-1.png }); await context.close(); })();选项一览选项类型默认值说明adbHostsince v1.28string127.0.0.1ADB server 的 hostadbPortsince v1.28int5037ADB server 的端口omitDriverInstallsince v1.28booleanfalse跳过自动 driver 安装deviceSerialNumbersince v1.28string无指定要启动服务的设备序列号不指定且连接了多台设备时会直接抛错hostsince v1.45stringlocalhostWebSocket 监听地址。默认只接受回环接口连接显式传0.0.0.0可接受网络请求——但要注意这等价于把设备 RPC 暴露给任何能访问该端口的方portsince v1.28int0随机可用端口WebSocket 监听端口wsPathsince v1.28string随机不可猜测字符串服务挂载的路径。文档明确警告任何知道wsPath的进程或网页都能接管该 OS 用户因此自定义该值时必须使用不可猜测的 tokenlaunchServer的底层流程可以从 androidServerImpl.ts 得到印证共三步预选设备先调用playwright.android.devices()透传adbHost/adbPort/omitDriverInstall设备数为 0 抛No devices found若指定了deviceSerialNumber则过滤过滤后仍无设备抛No device with serial number ...设备数大于 1 且未指定序列号时抛More than one device found. Please specify deviceSerialNumber。这些错误路径在 launch-server.spec.ts 中均有断言如No device with serial number does-not-exist启动 WebSocket 服务wsPath未指定时取/${createGuid()}即文档所说的不可猜测字符串然后new PlaywrightServer({ mode: launchServer, path, maxConnections: 1, preLaunchedAndroidDevice: device })并listen(port, host)。注意maxConnections: 1——同一时刻只允许一个客户端连接测试用例 should not allow multiple connections 验证了第二个connect会超时失败返回BrowserServer接口其close()/kill()都会关闭设备连接设备close事件又会触发服务端关闭并发出close事件测试 should handle close event correctly 对事件顺序device先于browserServer做了精确断言。host: 0.0.0.0的新选项since v1.45也有对应测试android.launchServer should work with host断言wsEndpoint()中包含0.0.0.0。3.4Android.setDefaultTimeoutsince: v1.9。把接受timeout选项的所有方法的全局默认超时改为timeout毫秒。在 client/android.ts 中它操作的是TimeoutSettings实例AndroidDevice构造时会new TimeoutSettings((parent as Android)._timeoutSettings)即设备级超时设置继承Android 级别的默认值因此Android.setDefaultTimeout对设备上的fill、wait、webView等带超时参数的方法全局生效。四、AndroidDevice常用能力速览connect/devices返回的AndroidDevice是设备操作的主体完整文档见 class-androiddevice.md。与本文主线最相关的几个方法shell(command)/open(command)在设备上执行 shell 命令并返回输出 Buffer / 返回一个可双向通信的AndroidSocket文档示例中am force-stop、am start都走shelllaunchBrowser({ pkg, ...contextOptions })启动 Chrome可用pkg换成其他浏览器包名返回持久化BrowserContext支持proxy、args等标准 context 参数proxy 自 v1.29 起可用。客户端实现见 android.ts 的launchBrowser它会prepareBrowserContextParams(options)后经 channel 下发并把返回的BrowserContext注册进 selectors 上下文集合webView({ pkg?, socketName? })/webViews()按包名或 socket 名等待/枚举 WebView内部逻辑是先查本地缓存_webViews未命中则waitForEvent(webview, predicate)控件操作族tap/longTap/fill/press/swipe/scroll/fling/drag/pinchOpen/pinchCloseselector 为AndroidSelector支持res、text、pkg、desc、hasChild、hasDescendant等字段文件与截图push(file, path, { mode })推文件、installApk(file, { args })装 APKargs默认-r -t -S、screenshot({ path })拍整机截图事件close连接关闭、webView检测到新 WebView 实例配合waitForEvent使用。五、仓库内的测试基础设施仓库自带完整的 Android 测试工程tests/android/可作为接入参考androidTest.ts 定义androidDevice/android等 fixtureplaywright.config.ts 声明了android-native与android-page两个 project其中loopback: 10.0.2.2是 AVD 访问宿主机环回地址的专用 IP10.0.2.2是模拟器访问宿主机localhost的惯例地址全局超时设为 2 小时、单测试 120 秒launch-server.spec.ts 覆盖了launchServerconnect的关键行为基本连通性shell(echo 123)返回123\n、host选项、设备/服务端close事件顺序、断线后重连、指定不存在序列号时报错、单连接限制、close()/kill()的断开语义甚至通过一个中转 WebSocket 代理验证了设备断开时服务端会主动终止 WS 连接。六、接入建议与注意事项版本能力devices/setDefaultTimeout自 v1.9 可用portv1.20、omitDriverInstallv1.21、hostv1.22依次加入整套launchServer/connect模型自 v1.28 起可用launchServer的host选项自 v1.45 起可用。低版本 Playwright 上请勿使用后续版本才有的参数。安全面launchServer的wsPath是控制凭证默认随机生成如需固定路径供多客户端脚本使用务必自行生成不可猜测的 token并避免随意把host设为0.0.0.0。多设备launchServer不指定deviceSerialNumber时会因多台设备直接失败CI 中挂多块设备时应始终显式指定。定位手段原生控件定位靠AndroidSelectorres资源 ID、text文本等拿到Page之后则回到 Playwright 标准的 role/text/selector 体系两种定位方式不要混用层级。实验性声明所有结论以当前仓库的 class-android.md 与packages/playwright-core/src/client/android.ts、packages/playwright-core/src/androidServerImpl.ts、packages/playwright-core/src/server/android/backendAdb.ts为准真机上的行为差异截图黑屏、部分命令失败等属于文档已声明的已知限制范畴。【免费下载链接】playwrightPlaywright is a framework for Web Testing and Automation. It allows testing Chromium, Firefox and WebKit with a single API.项目地址: https://gitcode.com/GitHub_Trending/pl/playwright创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进