“这没有用!我无法使用 Flutter 的集成测试来运行端到端测试”,大约 9 个月前,我们的一位客户惊呼道。我问问题是什么,他们解释说他们正在使用 Google 身份验证进行登录并使用 包,但无法使用 Flutter 的集成测试与登录屏幕进行交互。我仍然不太明白问题是什么,然后它点击了:这个插件使用集成测试无法使用的 。 google_sign_in 本机 UI 组件 我很失望,当时我无法提供解决方案,只能就此放弃。然而,快进到今天,一个很棒的新解决方案出现了,称为 。我将告诉您所有相关内容,但在深入讨论之前,让我们回顾一下为什么运行测试很重要,到目前为止您可以使用哪些工具,然后讨论如何开始使用 Patrol。 “Patrol” 精益代码 为什么还要测试 Flutter 应用程序? 开发团队使用 (CI) 服务的主要原因之一,例如 是获得有关他们提交到其存储库的代码的即时反馈。测试可以作为管道的一部分自动运行,以确保一定程度的质量和稳定性,因为可以及早发现错误或问题并立即纠正。我们总是鼓励客户在设置工作流程时实施测试,但听到“我们没有时间编写测试”的情况并不少见。希望您没有陷入困境,并使用测试作为应用程序开发周期的一部分来交付高质量且无错误的应用程序! 持续集成 代码魔法 测试 Flutter 应用程序的主要自动化方法有哪些? 有四种主要的测试方法可以作为 CI 工作流程的一部分进行自动化。测试本身就是一个主题,因此我将保持简短,但结合使用这些测试方法将帮助您提高应用程序的质量并尽早发现问题。 首先, 通常用于单独测试您的函数和方法,以确保它们按预期工作。还可以编写单元测试来确保您的业务逻辑在不同的场景中工作,而不会出现任何意外的结果。 “单元测试” 接下来,我们有 Flutter ,它允许您测试 UI 组件并确保它们正确渲染并按您的预期工作。 “Widget 测试” 然后是 ,您可以在其中测试应用程序的单元和组件是否按预期协同工作。 “集成测试” 最后,还有 您可以像真实用户使用应用程序一样测试应用程序。在 CI 工作流程中,这通常是使用模拟器或模拟器来自动测试应用程序中的不同路径,以确保在更改代码后不会出现任何问题。 “端到端 UI 测试”, 这就是我一开始谈到的客户陷入困境的地方,因为他们无法运行端到端 UI 测试,因为无法登录应用程序。当时他们测试了绕过登录部分的“开发”版本。 然而,现在 可用了,这就不再需要了! “巡逻” 进入,舞台左侧,巡逻! 首先,什么是巡逻?好吧,我认为文档说得最好: Patrol 是由 LeanCode 开发的全新开源 Flutter UI 测试框架。它建立在 Flutter 现有测试工具之上,让您可以完成以前不可能完成的事情。 Patrol 可让您访问 Flutter 应用程序运行所在平台的本机功能。 这里最重要的部分是它允许您访问 应用程序运行平台的 。 Flutter 本机功能 这意味着您现在可以执行以下操作: 与权限请求对话框交互以驳回或接受请求。 与 WebView 交互。 最小化和最大化您的应用程序。 与 Google 或 Apple 身份验证等身份验证流程交互。 与其他本机功能交互,例如打开通知托盘、按主页按钮、打开或关闭 Wi-Fi 连接或将设备更改为暗模式等。 好吧,这听起来不错,但是有什么问题呢? 嗯,没有一个!更重要的是,它不仅是 ,而且 ! 免费的 开源 此外,Patrol 还引入了 ,它为您提供了更简洁的语法来编写测试。您可以阅读有关他们的更多信息 。 “自定义查找器” 这里 安装和设置 Patrol 要开始使用 Patrol,您需要安装 CLI、将 添加到 中,并在 iOS 和 Android 项目中设置一些配置。 Patrol 依赖项 pubspec.yaml 创建了一些很棒的文档 它会引导您完成每个平台的流程,您可以在此处找到。他们的分步指南将引导您完成 和 的设置。 LeanCode 这里 iOS Android 如果您遇到任何问题,获得帮助的最佳位置是您可以加入的 服务器 。 Patrol Community Discord 这里 如果您发现任何错误,则可以提出问题 。 这里 安装和设置 Patrol 要开始使用 Patrol,您需要安装 CLI、将 添加到 中,并在 iOS 和 Android 项目中设置一些配置。 Patrol 依赖项 pubspec.yaml 创建了一些很棒的文档 它会引导您完成每个平台的流程,您可以在此处找到。他们的分步指南将引导您完成 和 的设置。 LeanCode 这里 iOS Android 如果您遇到任何问题,获得帮助的最佳位置是您可以加入的 服务器 。 Patrol Community Discord 这里 如果您发现任何错误,则可以提出问题 。 这里 使用 Patrol 编写本机功能测试 现在您已完成所有设置,让我们开始测试一些本机功能。为了亲自尝试,我设置了一个简单的 Flutter 应用程序,其中包含一个提升按钮,单击该按钮会打开一个 警报对话框。 本机 单击“确定”或“取消”即可关闭该对话框。 再次,我建议使用 Patrol 自己的文档,您可以找到它 添加您的第一个测试文件。 这里 因此,对于我的测试,我想单击带有文本“Click me!”的提升按钮。它是一个标准的 Flutter 小部件,因此可以使用以下 Patrol finder 来点击它: await $('Click me!').tap(); 然后应该显示本机对话框,因此我们现在可以开始与本机 UI 组件进行交互。因此,让我们添加本机查找器,以便我们点击“确定”按钮: await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); 那很简单!我还想测试“取消”按钮,所以让我们点击“点击我!”再次单击按钮,然后通过添加更多行来点击本机对话框的“取消”按钮,如下所示: await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel')); 您完成的测试文件应如下所示: import 'package:cmpatrol/main.dart'; import 'package:patrol/patrol.dart'; void main() { patrolTest( 'Native tests', nativeAutomation: true, ($) async { await $.pumpWidgetAndSettle(const MyApp()); await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'NO')); }, ); } 您现在应该能够使用启动测试的命令在模拟器或真实设备上运行该测试。我的集成测试文件名为 ,因此我从终端开始测试,如下所示: “button_test” patrol test -t integration_test/button_test.dart 您将直接在终端中查看测试是否通过或失败。如果测试失败,您将获得完整测试报告的链接。或者,如果您像我一样在 Android 上运行测试,那么您应该可以通过单击以下目录中的 来访问报告: index.html ./build/app/reports/androidTest/connected 您可以进一步尝试其他本机功能,例如打开通知托盘、禁用 wifi、启用深色模式、最小化和最大化应用程序: // minimize app await $.native.pressHome(); await $.native.openNotifications(); await $.native.disableWifi(); await $.native.enableDarkMode(); // maximize app await $.native.openApp(); ⚠️ 请注意,不可能完全关闭您的应用程序然后重新打开它,因为这样做会结束整个测试,从而导致测试失败。 咨询巡逻队 了解更多示例。 文档 在 Codemagic 工作流程中使用 Patrol 要将 Patrol 合并到您的工作流程中,您首先必须在构建计算机上安装 。这只需几秒钟,完成后,您就可以运行测试脚本。下面是如何将这些步骤添加到 配置文件的“脚本”部分的示例。我建议运行脚本来安装 Patrol CLI 作为第一个脚本步骤之一,然后您可以在此之后立即运行 Patrol 测试,或者在您可能还想预先运行的任何其他测试之后运行 Patrol 测试。 Patrol CLI codemagic.yaml 在运行 Patrol 测试之前,您需要启动模拟器,因此我们将添加一个脚本来启动模拟器并等待其完全启动。请注意,由于 Apple 虚拟化框架不支持嵌套虚拟化,因此 Android 模拟器在使用 Apple Silicon M1 或 M2 机器的机器上不可用。因此,我建议在测试 Android 应用程序时使用 实例。 Linux 的脚本部分应如下所示: codemagic.yaml scripts: ... - name: Install Patrol CLI script: dart pub global activate patrol_cli - name: Launch Android emulator script: | cd $ANDROID_HOME/tools emulator -avd emulator & adb wait-for-device - name: Run tests with Patrol script: patrol test -t integration_test/your_test.dart ignore_failure: true ... 在 Codemagic 构建日志中显示 Patrol 测试结果 Patrol 测试结果也以 格式提供,这意味着它们可以显示在 Codemagic 构建概述屏幕上的构建日志中。您只需将 属性添加到生成的 JUnit XML 文件的路径中。您可以使用带有布尔值的 属性来控制是否希望工作流的其余部分继续运行。如果您想将结果上传到测试管理系统(如下一节所述),则应将其设置为 。 JUnit XML test_report ignore_failure true 以下是您的脚本应如下所示的示例: scripts: ... - name: Run tests with Patrol script: | patrol test -t integration_test/your_test.dart test_report: build/app/outputs/androidTest-results/connected/*.xml ignore_failure: true ... 失败的测试可能如下所示: 收集 Patrol 测试报告作为构建工件 您可能想要做的另一件事是将测试报告输出收集为构建工件,以便在发生任何错误时可以查看完整报告。执行此操作后,报告可以在构建概述屏幕左侧的“工件”部分中以 zip 文件的形式下载。最简单的方法是将报告文件所在的目录复制到 Codemagic 用于导出工件的目录中。有一个名为 的内置环境变量引用此目录,您可以在脚本中使用该目录。 $CM_EXPORT_DIR 执行此操作的脚本应该如下所示: scripts: ... - name: Export Patrol test report script: | cp -r build/app/reports/androidTests/connected $CM_EXPORT_DIR/report ... 结论 终于克服了运行涉及本机功能的 UI 和集成测试的问题。现在可以测试本机功能并与身份验证流程、本机对话框进行交互,甚至可以切换 wifi、蜂窝网络、暗模式等本机功能,甚至可以最小化和最大化您的应用程序。此外,它是 且 ,并为 Flutter 推出以来一直存在的实际问题提供了解决方案。此外,在您的 Codemagic 工作流程中添加和使用它非常简单。如果您想支持 LeanCode 所做的伟大工作,请在 pub.dev 上给 Patrol 点赞 并给 Patrol GitHub 存储库一颗星 。 Patrol 免费 开源的 这里 这里 本文由解决方案工程主管 Kevin Suhajda 撰写 。你可以找到凯文 , , 和 。 代码魔法 X GitHub 领英 也发布 。 在这里