在鸿蒙上使用 espresso Flutter 包
espresso是一个为Flutter应用提供Espresso测试绑定的插件,支持在Android原生测试中驱动Flutter组件。主要特点包括跨框架测试、丰富的匹配器(withText、withTooltip等)、完整操作集(点击、输入)和断言功能。使用方式:1)通过git引入dev_dependencies;2)配置Android项目的Manifest和build.gradle;3)创建测试文
插件介绍
espresso 是一个为 Flutter 应用提供 Espresso 测试绑定的包,它允许开发者从原生 Espresso 测试中驱动 Flutter 小部件。这个包主要用于 Android 平台的端到端测试,提供了一种无缝集成原生 Android 测试框架 Espresso 和 Flutter 应用的方式。
主要特点:
- 跨框架测试:允许在原生 Espresso 测试中与 Flutter 小部件进行交互
- 丰富的匹配器:提供了多种匹配器来定位 Flutter 小部件,如
withText、withTooltip、withValueKey等 - 完整的操作集:支持对 Flutter 小部件执行点击、输入等操作
- 断言功能:可以验证 Flutter 小部件的状态和属性
在鸿蒙平台上使用 espresso 包,可以结合鸿蒙的测试框架和 Espresso 测试框架,为 Flutter 应用提供更全面的端到端测试能力。
如何使用插件
包的引入
由于这是一个为鸿蒙平台定制修改的版本,需要以 git 形式引入。在项目的 pubspec.yaml 文件中添加以下依赖配置:
dev_dependencies:
espresso:
git:
url: "https://gitcode.com/openharmony-tpc/flutter_packages.git"
path: "packages/espresso"
注意:espresso 包通常作为开发依赖(dev_dependency)引入,而不是运行时依赖。
添加依赖后,运行 flutter pub get 命令来获取包:
flutter pub get
配置 Android 项目
由于 espresso 包是基于 Android 的 Espresso 测试框架,需要在 Android 项目中进行一些配置:
- 在
android/app/src/main/AndroidManifest.xml文件中添加以下配置(建议在 debug 或 androidTest 目录下的 AndroidManifest.xml 中添加):
<application android:usesCleartextTraffic="true">
<!-- 其他配置 -->
</application>
- 在
android/app/build.gradle文件中添加以下依赖:
dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation "com.google.truth:truth:1.0"
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
api 'androidx.test:core:1.2.0'
}
创建测试文件
-
在 Android 项目中创建测试目录和文件:
创建
android/app/src/androidTest/java/com/example/目录(根据你的包名调整),并创建测试文件,例如MainActivityTest.java。 -
编写 Espresso 测试代码:
package com.example.espresso_example;
import static androidx.test.espresso.flutter.EspressoFlutter.onFlutterWidget;
import static androidx.test.espresso.flutter.action.FlutterActions.click;
import static androidx.test.espresso.flutter.assertion.FlutterAssertions.matches;
import static androidx.test.espresso.flutter.matcher.FlutterMatchers.withText;
import static androidx.test.espresso.flutter.matcher.FlutterMatchers.withTooltip;
import static androidx.test.espresso.flutter.matcher.FlutterMatchers.withValueKey;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
@Before
public void setUp() throws Exception {
ActivityScenario.launch(MainActivity.class);
}
@Test
public void performClick() {
// 点击具有 "Increment" 提示的 Flutter 按钮
onFlutterWidget(withTooltip("Increment")).perform(click());
// 验证具有 "CountText" key 的文本小部件内容是否符合预期
onFlutterWidget(withValueKey("CountText")).check(matches(withText("Button tapped 1 time.")));
}
}
-
创建测试驱动程序:
在项目的
test_driver/目录下创建测试驱动文件,例如integration_test.dart:
import 'package:flutter_driver/driver_extension.dart';
import 'package:<app_package_name>/main.dart' as app;
void main() {
enableFlutterDriverExtension();
app.main();
}
将 <app_package_name> 替换为你的应用包名。
运行测试
使用以下命令运行 Espresso 测试:
./gradlew app:connectedAndroidTest -Ptarget=`pwd`/../test_driver/integration_test.dart
API 的调用
espresso 包提供了一系列 API 用于在 Espresso 测试中与 Flutter 小部件进行交互:
定位 Flutter 小部件
withText(String text):根据文本内容查找小部件withTooltip(String tooltip):根据提示文本查找小部件withValueKey(String key):根据键值查找小部件withType(String type):根据小部件类型查找小部件isDescendantOf(FlutterMatcher ancestorMatcher):查找特定父小部件的子小部件
执行操作
click():执行点击操作syntheticClick():执行合成点击操作enterText(String text):输入文本scrollTo():滚动到小部件
验证断言
matches(FlutterMatcher matcher):验证小部件是否匹配指定条件
完整的 API 示例
// 定位并点击具有特定文本的按钮
onFlutterWidget(withText("Submit")).perform(click());
// 定位文本输入框并输入文本
onFlutterWidget(withValueKey("EmailInput")).perform(enterText("test@example.com"));
// 定位文本小部件并验证内容
onFlutterWidget(withValueKey("WelcomeText")).check(matches(withText("Welcome to the app!")));
// 定位列表项并滚动到它
onFlutterWidget(withText("Item 100")).perform(scrollTo());
// 组合匹配器:查找特定类型的子小部件
onFlutterWidget(isDescendantOf(withType("ListView"))).check(matches(withText("Item 5")));
完整示例
以下是一个完整的示例,展示了如何在鸿蒙应用中使用 espresso 包:
1. Flutter 应用代码(main.dart)
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: 'Espresso Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Espresso Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
key: const ValueKey('CountText'),
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
2. 测试驱动程序(test_driver/integration_test.dart)
import 'package:flutter_driver/driver_extension.dart';
import 'package:espresso_demo/main.dart' as app;
void main() {
enableFlutterDriverExtension();
app.main();
}
3. Espresso 测试(android/app/src/androidTest/java/com/example/espresso_demo/MainActivityTest.java)
package com.example.espresso_demo;
import static androidx.test.espresso.flutter.EspressoFlutter.onFlutterWidget;
import static androidx.test.espresso.flutter.action.FlutterActions.click;
import static androidx.test.espresso.flutter.assertion.FlutterAssertions.matches;
import static androidx.test.espresso.flutter.matcher.FlutterMatchers.withText;
import static androidx.test.espresso.flutter.matcher.FlutterMatchers.withTooltip;
import static androidx.test.espresso.flutter.matcher.FlutterMatchers.withValueKey;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {
@Before
public void setUp() throws Exception {
ActivityScenario.launch(MainActivity.class);
}
@Test
public void incrementCounter() {
// 初始状态验证
onFlutterWidget(withValueKey("CountText")).check(matches(withText("0")));
// 点击增加按钮
onFlutterWidget(withTooltip("Increment")).perform(click());
// 验证计数器是否增加到 1
onFlutterWidget(withValueKey("CountText")).check(matches(withText("1")));
// 再次点击增加按钮
onFlutterWidget(withTooltip("Increment")).perform(click());
// 验证计数器是否增加到 2
onFlutterWidget(withValueKey("CountText")).check(matches(withText("2")));
}
}
注意事项
-
平台限制:
espresso包主要针对 Android 平台设计,在鸿蒙平台上使用时需要确保兼容性。 -
依赖配置:需要正确配置 Android 项目的依赖和权限,特别是
android:usesCleartextTraffic="true"配置。 -
测试驱动程序:必须创建并使用测试驱动程序来启用 Flutter Driver 扩展。
-
小部件键值:为了便于测试,建议为需要测试的 Flutter 小部件添加唯一的
ValueKey。 -
测试环境:需要在连接的设备或模拟器上运行测试,确保设备已启用开发者选项和 USB 调试。
-
版本兼容性:确保使用与 Flutter SDK 版本兼容的
espresso包版本。 -
鸿蒙适配:由于是在鸿蒙平台上使用,可能需要根据鸿蒙的特殊要求进行额外的适配和测试。
总结
espresso 是一个功能强大的 Flutter 包,它允许开发者在原生 Espresso 测试中与 Flutter 小部件进行交互,为 Flutter 应用提供了更全面的端到端测试能力。
在鸿蒙平台上使用 espresso 包,可以:
- 结合鸿蒙的测试框架和 Espresso 测试框架,为 Flutter 应用提供更全面的测试覆盖
- 使用丰富的匹配器、操作和断言 API,实现对 Flutter 小部件的精确控制和验证
- 编写清晰、可维护的测试代码,提高应用的质量和稳定性
虽然 espresso 包主要针对 Android 平台设计,但通过适当的配置和适配,可以在鸿蒙平台上使用它来测试 Flutter 应用。对于需要在鸿蒙平台上开发高质量 Flutter 应用的开发者来说,espresso 包是一个非常有价值的测试工具。
需要注意的是,随着鸿蒙平台的不断发展和完善,可能需要对 espresso 包进行进一步的适配和优化,以充分利用鸿蒙平台的特性和优势。
更多推荐



所有评论(0)