“这没有用!我无法使用 Flutter 的集成测试来运行端到端测试”,大约 9 个月前,我们的一位客户惊呼道。我问问题是什么,他们解释说他们正在使用 Google 身份验证进行登录并使用google_sign_in包,但无法使用 Flutter 的集成测试与登录屏幕进行交互。我仍然不太明白问题是什么,然后它点击了:这个插件使用集成测试无法使用的本机 UI 组件。
我很失望,当时我无法提供解决方案,只能就此放弃。然而,快进到今天,一个很棒的新解决方案出现了,称为“Patrol”
开发团队使用持续集成(CI) 服务的主要原因之一,例如
有四种主要的测试方法可以作为 CI 工作流程的一部分进行自动化。测试本身就是一个主题,因此我将保持简短,但结合使用这些测试方法将帮助您提高应用程序的质量并尽早发现问题。
首先, “单元测试”通常用于单独测试您的函数和方法,以确保它们按预期工作。还可以编写单元测试来确保您的业务逻辑在不同的场景中工作,而不会出现任何意外的结果。
接下来,我们有 Flutter “Widget 测试” ,它允许您测试 UI 组件并确保它们正确渲染并按您的预期工作。
然后是“集成测试” ,您可以在其中测试应用程序的单元和组件是否按预期协同工作。
最后,还有“端到端 UI 测试”,您可以像真实用户使用应用程序一样测试应用程序。在 CI 工作流程中,这通常是使用模拟器或模拟器来自动测试应用程序中的不同路径,以确保在更改代码后不会出现任何问题。
这就是我一开始谈到的客户陷入困境的地方,因为他们无法运行端到端 UI 测试,因为无法登录应用程序。当时他们测试了绕过登录部分的“开发”版本。
然而,现在“巡逻”可用了,这就不再需要了!
首先,什么是巡逻?好吧,我认为文档说得最好:
Patrol 是由 LeanCode 开发的全新开源 Flutter UI 测试框架。它建立在 Flutter 现有测试工具之上,让您可以完成以前不可能完成的事情。 Patrol 可让您访问 Flutter 应用程序运行所在平台的本机功能。
这里最重要的部分是它允许您访问Flutter应用程序运行平台的本机功能。
这意味着您现在可以执行以下操作:
好吧,这听起来不错,但是有什么问题呢?
嗯,没有一个!更重要的是,它不仅是免费的,而且
此外,Patrol 还引入了“自定义查找器” ,它为您提供了更简洁的语法来编写测试。您可以阅读有关他们的更多信息
要开始使用 Patrol,您需要安装 CLI、将Patrol 依赖项添加到pubspec.yaml中,并在 iOS 和 Android 项目中设置一些配置。
LeanCode创建了一些很棒的文档
如果您遇到任何问题,获得帮助的最佳位置是您可以加入的Patrol Community Discord服务器
如果您发现任何错误,则可以提出问题
要开始使用 Patrol,您需要安装 CLI、将Patrol 依赖项添加到pubspec.yaml中,并在 iOS 和 Android 项目中设置一些配置。
LeanCode创建了一些很棒的文档
如果您遇到任何问题,获得帮助的最佳位置是您可以加入的Patrol Community Discord服务器
如果您发现任何错误,则可以提出问题
现在您已完成所有设置,让我们开始测试一些本机功能。为了亲自尝试,我设置了一个简单的 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();
⚠️ 请注意,不可能完全关闭您的应用程序然后重新打开它,因为这样做会结束整个测试,从而导致测试失败。
咨询巡逻队
要将 Patrol 合并到您的工作流程中,您首先必须在构建计算机上安装Patrol CLI 。这只需几秒钟,完成后,您就可以运行测试脚本。下面是如何将这些步骤添加到codemagic.yaml配置文件的“脚本”部分的示例。我建议运行脚本来安装 Patrol CLI 作为第一个脚本步骤之一,然后您可以在此之后立即运行 Patrol 测试,或者在您可能还想预先运行的任何其他测试之后运行 Patrol 测试。
在运行 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 ...
Patrol 测试结果也以JUnit XML格式提供,这意味着它们可以显示在 Codemagic 构建概述屏幕上的构建日志中。您只需将test_report属性添加到生成的 JUnit XML 文件的路径中。您可以使用带有布尔值的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 ...
失败的测试可能如下所示:
您可能想要做的另一件事是将测试报告输出收集为构建工件,以便在发生任何错误时可以查看完整报告。执行此操作后,报告可以在构建概述屏幕左侧的“工件”部分中以 zip 文件的形式下载。最简单的方法是将报告文件所在的目录复制到 Codemagic 用于导出工件的目录中。有一个名为$CM_EXPORT_DIR的内置环境变量引用此目录,您可以在脚本中使用该目录。
执行此操作的脚本应该如下所示:
scripts: ... - name: Export Patrol test report script: | cp -r build/app/reports/androidTests/connected $CM_EXPORT_DIR/report ...
Patrol终于克服了运行涉及本机功能的 UI 和集成测试的问题。现在可以测试本机功能并与身份验证流程、本机对话框进行交互,甚至可以切换 wifi、蜂窝网络、暗模式等本机功能,甚至可以最小化和最大化您的应用程序。此外,它是免费且开源的,并为 Flutter 推出以来一直存在的实际问题提供了解决方案。此外,在您的 Codemagic 工作流程中添加和使用它非常简单。如果您想支持 LeanCode 所做的伟大工作,请在 pub.dev 上给 Patrol 点赞
本文由解决方案工程主管 Kevin Suhajda 撰写
也发布在这里。