[译]Flutter自动测试工具appium-flutter-driver

1,777 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情


本文翻译自:github.com/appium-user…


Appium Flutter Driver

NPM version Downloads

Appium Flutter Driver 是用于跨平台/操作系统的 Flutter 应用的自动测试工具。
Appium Flutter Driver 是由社区维护的移动端自动测试工具 Appium 的一部分。

欢迎创建PR以修改问题或改进些驱动。

非常欢迎所有形式的贡献,包括非代码! 查看下面的 TODO 。

Flutter Driver vs Appium Flutter Driver

尽管 Flutter 已经自带了优秀的集成测试支持 Flutter Driver,但是并不适合一些特定的使用场景,如:

  • 使用其它语言而不是 Dart 编写测试代码
  • 为嵌入的 WebView 或原生 View 、或者嵌入Flutter View 的原生应用运行 Flutter 应用的集成测试
  • 同时在多个设备上运行测试
  • 在设备工场上运行集成测试,如 Sauce Labs、HeadSpin、 AWS、 Firebase

Appium Flutter Driver 底层使用带 ext.flutter.driver 扩展的 Dart 虚拟机服务协议,和 Flutter Driver 类似,可以控制 Flutter app-under-test (AUT)。

Appium Flutter Driver 或 Appium UiAutomator2/XCUITest 驱动

  • Appium Flutter Driver 管理被测试应用和使用 Appium UiAutomator2/XCUITest 驱动的测试设备。

    • FLUTTER 上下文直接通过观察 URL 向 Dart 虚拟机发送命令

      • 较新的 Flutter 版本向系统的辅助功能公开了其辅助标签。这意味着可以查找到一些 Flutter 元素并使用 Appium UiAutomator2/XCUITest 驱动的 accessibility_id 等进行交互
    • NATIVE_APP 上下文和常规的 Appium UiAutomator2/XCUITest 驱动是一样的

    • WEBVIEW 上下文通过 Appium UiAutomator2/XCUITest 驱动管理 WebView 内容

  • 如果被测试的应用带有 semanticLabel 属性,Appium UiAutomator2/XCUITest 驱动足以实现自动化。然后,各种操作系统的辅助机制通过系统的辅助功能公开了用于 Appium 的元素。

    • 例如 Key 在 Appium UiAutomator2/XCUITest 驱动中不起作用,但是能在 Appium Flutter Driver 正常使用。

安装

  • 为了使用 appium-flutter-driver ,我们需要使用 appium 版本 1.16.0 或更高。

  • Appium Flutter Driver 版本 1.0 或更高需要 Appium 2.0.0

    • 1.8.0+ 需要使用 Appium 2.0.0-beta.46

使用 Appium 2 (appium@next):

appium driver install --source=npm appium-flutter-driver

注意,对于 Flutter v3 请使用最新的带 appium 2 的 Flutter 驱动

使用 Appium 1:

npm i -g appium-flutter-driver

用法

如果对运行 Appinum 测试不熟悉,可以先从 Appium Getting Starting 开始。

Flutter app-under-test (AUT) 必须在 debug 或 profile 模式下编译,因为 Flutter Driver 不支持在发布模式下运行
然后,确保 Flutter AUT 在 runApp 之前运行了 enableFlutterDriverExtension()
然后,确保应用也导入了 flutter_driver 包作为开发依赖(devDependencies)。
example目录中的该代码片段,是使用 webdriverio 编写,用作 Appium 客户端,并假定已在相同的主机运行了 appium 服务器 (即已安装 appium-flutter-driver),并使用了默认端口(4723)。
更多信息,查看示例的 README.md

注意事项

  • Flutter 上下文不支持 页面来源

    • 请使用 getRenderTree 命令代替
  • 可以在 NATIVE_APP 上下文发送 appium-xcuitest-driver/appium-uiautomator2-driver 命令

  • scrollUntilVisible 命令 : 预期是检查已知在组件树中的元素可见。使用 waitFor 等待元素

  • scrollUntilTapable 命令 : 预期是检查元素可见并允许点击。使用 waitTapable 等待元素

  • driver.activateApp(appId) 启动被测试的应用并绑定到FLUTTER 上下文中的观察 URL。如果没有找到观察 URL ,该方法会抛出异常。典型的情况是 appId 已经在运行。然后,驱动查找观察 URL 会失败。

  • getClipboard 和 setClipboard 依赖每个 NATIVE_APP 的上下文行为

仅 Flutter 驱动的所需功能

功能描述示例值
appium:retryBackoffTime获取 Flutter Session 时连接 Socket 的重试等待时间 (默认为 3000毫秒)500
appium:maxRetryCount获取 Flutter Session 时连接 Socket 的重试次数 (默认为 30)20
appium:observatoryWsUri绑定 Dart 虚拟机的 URL 。 Appium flutter 驱动默认从设备日志中查找 WebSocket URL。可以指定该项略过查找 URL 的进程。然后,该驱动会尝试为给定的 WebSocket URL 建立 WebSocket 连接。注意,该功能会假定在 Appinum Session 之外 URL 已准备就绪。该 Flutter 驱动使用此项不会进行端口转发。你也可能需要配合端口转发。'ws://127.0.0.1:60992/aaaaaaaaaaa=/ws'
appium:skipPortForward从本地设备转向使用 observatoryWsUri 功能的测试设备时是否忽略端口转发。 它帮忙你管理 AUT 、观察 URL 和 端口转发配置。默认是 truetrue, false

上下文

Appium Flutter Driver 可以在 FLUTTER 上下文中向 Dart 虚拟机发送 flutter_driver 命令,但是它不支持原生的 Android/iOS 自动测试。取而代之的是,NATIVE_APP 上下文为 Android 和 iOS 分别提供了 UIA2 驱动 和 XCUITest 用于自动测试。WEBVIEW_XXXX 可辅助 WebView 测试。

因此,可以通过切换 FLUTTER 、 NATIVE_APP 和 WEBVIEW_XXXX 来自动化合适的测试应用目标。

示例

const wdio = require('webdriverio');
const assert = require('assert');
const { byValueKey } = require('appium-flutter-finder');

const osSpecificOps = process.env.APPIUM_OS === 'android' ? {
  'platformName': 'Android',
  'appium:deviceName': 'Pixel 2',
  // @todo support non-unix style path
  app: __dirname +  '/../apps/app-free-debug.apk',
}: process.env.APPIUM_OS === 'ios' ? {
  'platformName': 'iOS',
  'appium:platformVersion': '12.2',
  'appium:deviceName': 'iPhone X',
  'appium:noReset': true,
  'appium:app': __dirname +  '/../apps/Runner.zip',

} : {};

const opts = {
  port: 4723,
  capabilities: {
    ...osSpecificOps,
    'appium:automationName': 'Flutter',
    'appium:retryBackoffTime': 500
  }
};

(async () => {
  const counterTextFinder = byValueKey('counter');
  const buttonFinder = byValueKey('increment');

  const driver = await wdio.remote(opts);

  if (process.env.APPIUM_OS === 'android') {
    await driver.switchContext('NATIVE_APP');
    await (await driver.$('~fab')).click();
    await driver.switchContext('FLUTTER');
  } else {
    console.log('Switching context to `NATIVE_APP` is currently only applicable to Android demo app.')
  }

  assert.strictEqual(await driver.getElementText(counterTextFinder), '0');

  await driver.elementClick(buttonFinder);
  await driver.touchAction({
    action: 'tap',
    element: { elementId: buttonFinder }
  });

  assert.strictEqual(await driver.getElementText(counterTextFinder), '2');

  driver.deleteSession();
})();

修改日志


开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情