Flutter测试辅助插件react_testing_library的使用
Flutter测试辅助插件react_testing_library的使用
介绍
react_testing_library
是一个用于 Dart 的测试库,它提供了与 JavaScript 中 dom-testing-library
和 react-testing-library
类似的功能。这个库帮助你以用户为中心的方式测试 Dart UI 组件,使你的测试更接近用户的真实使用场景,从而提高测试的信心。
工作原理
react_testing_library
不是直接操作 React 或 OverReact 的组件实例,而是通过实际的 DOM 节点进行查询和交互。你可以像用户一样通过标签文本、链接文本或按钮文本找到元素,也可以通过 HTML 的 data-test-id
属性来查找特定的元素。这种测试方式鼓励开发人员编写更符合用户行为的测试用例,从而使应用程序更加可访问。
入门指南
1. 添加必要的依赖项
在 pubspec.yaml
文件中添加以下依赖项:
dependencies:
# 假设你正在测试 OverReact UI 组件
over_react: ^4.0.0
dev_dependencies:
build_runner: ">=1.7.1 <3.0.0"
build_test: ">=0.10.9 <3.0.0"
build_web_compilers: ">=2.12.0 <4.0.0"
react_testing_library: ^1.1.13
test: ^1.14.4
# 使 HTML 部分的测试引导更加容易
test_html_builder: ^2.0.0
2. 配置 build.yaml
生成测试输出
在 build.yaml
文件中配置生成测试输出的设置:
targets:
$default:
builders:
build_web_compilers|entrypoint:
# 这些是你要编译的入口文件的通配符
generate_for:
- test/**.browser_test.dart
3. 配置 dart_test.yaml
运行测试
在项目的根目录下创建 dart_test.yaml
文件:
platforms:
- chrome
paths:
- test/unit/
4. 添加 HTML 模板加载必要的 React/react-testing-library JS 文件
推荐使用 test_html_builder
库来创建一个模板,该模板将用于加载每个 .dart.js
测试文件。
使用 test_html_builder
(推荐)
在 test/unit/rtl_unit_test_template.html
文件中创建以下内容:
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{testName}}</title>
<script src="packages/react/react.js"></script>
<script src="packages/react/react_dom.js"></script>
<script src="packages/react_testing_library/js/react-testing-library.js"></script>
{{testScript}}
<script src="packages/test/dart.js"></script>
</head>
</html>
手动添加/提交自己的 HTML 文件
如果你不想使用 test_html_builder
,可以为每个包含 react_testing_library
的 _test.dart
文件创建一个对应的 HTML 文件。例如,在 test/unit/some_unit_test.html
文件中:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Some Unit Test</title>
<script src="packages/react/react.js"></script>
<script src="packages/react/react_dom.js"></script>
<script src="packages/react_testing_library/js/react-testing-library.js"></script>
<link rel="x-dart-test" href="some_unit_test.dart">
<script src="packages/test/dart.js"></script>
</head>
</html>
5. 编写组件测试
使用 react_testing_library
提供的 render
函数生成 DOM,并使用查询函数获取要测试的元素。然后,你可以使用 matchers.dart
中的匹配器对 DOM 进行断言,并使用事件和用户事件入口点与 DOM 交互。
示例:Greeting 组件
首先,定义一个简单的 Greeting 组件:
import 'package:over_react/over_react.dart';
part 'greeting.over_react.g.dart';
mixin GreetingProps on UiProps {
String heading;
String subHeading;
String getStartedRoute;
}
UiFactory<GreetingProps> Greeting = uiFunction(
(props) {
return (Dom.header()..role = 'group')(
Dom.h1()(props.heading),
Dom.h2()(props.subHeading),
(Dom.a()..href = props.getStartedRoute)('Get started'),
);
},
_$GreetingConfig, // ignore: undefined_identifier
);
接下来,编写测试代码:
import 'dart:html';
import 'package:test/test.dart';
import 'package:react_testing_library/react_testing_library.dart' as rtl;
import 'package:react_testing_library/matchers.dart';
import 'package:your_package/src/components/greeting.dart';
main() {
group('Greeting', () {
rtl.RenderResult view;
tearDown(() {
view = null;
});
group('renders the expected elements:', () {
group('a <header>', () {
HtmlElement headerElement;
setUp(() {
view = rtl.render((Greeting()
..heading = 'Hello There!'
..subHeading = 'Welcome to the unit testing party.'
..getStartedRoute = '/start/partying'
)());
headerElement = view.getByRole('group');
});
test('with a child <h1> with a text value equal to props.heading', () {
final h1Element = rtl.within(headerElement).getByRole('heading', level: 1);
expect(h1Element, hasTextContent('Hello There!'));
});
test('with a child <h2> with a text value equal to props.subHeading', () {
final h2Element = rtl.within(headerElement).getByRole('heading', level: 2);
expect(h2Element, hasTextContent('Welcome to the unit testing party.'));
});
test('with a child <a> with an href equal to props.getStartedRoute', () {
final anchorElement = rtl.within(headerElement).getByRole('link');
expect(anchorElement, hasAttribute('href', '/start/partying'));
});
});
});
});
}
更多关于Flutter测试辅助插件react_testing_library的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter测试辅助插件react_testing_library的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter项目中,虽然react_testing_library
是一个专为React应用设计的测试库,并不直接适用于Flutter,但Flutter社区也有类似的测试辅助工具和库来帮助开发者进行组件和应用的测试。在Flutter中,我们通常使用flutter_test
包以及相关的测试框架来进行测试。
不过,为了模拟react_testing_library
的功能,即在Flutter中提供类似的高级API来进行组件渲染和断言,我们可以结合flutter_test
和integration_test
包来编写测试用例。下面是一个简单的Flutter测试示例,展示了如何使用这些工具进行组件测试。
1. 添加依赖
首先,确保你的pubspec.yaml
文件中包含了必要的测试依赖:
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
2. 创建一个示例Widget
假设我们有一个简单的Flutter组件MyButton
:
// my_button.dart
import 'package:flutter/material.dart';
class MyButton extends StatelessWidget {
final String label;
final VoidCallback onPressed;
MyButton({required this.label, required this.onPressed});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: Text(label),
);
}
}
3. 编写测试代码
接下来,我们编写一个测试来验证MyButton
的行为。我们将使用flutter_test
包中的功能来渲染组件并进行断言。
// test/widget_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:my_app/my_button.dart'; // 假设你的MyButton在my_app目录下
void main() {
testWidgets('MyButton taps emit the correct callback', (WidgetTester tester) async {
bool wasTapped = false;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Center(
child: MyButton(
label: 'Tap Me',
onPressed: () {
wasTapped = true;
},
),
),
),
));
await tester.tap(find.text('Tap Me'));
await tester.pumpAndSettle();
expect(wasTapped, true);
});
}
4. 运行测试
在命令行中,你可以通过运行以下命令来执行测试:
flutter test test/widget_test.dart
解释
- 依赖添加:我们在
pubspec.yaml
中添加了flutter_test
作为开发依赖,这是Flutter自带的测试框架。 - 组件创建:我们创建了一个简单的
MyButton
组件。 - 测试编写:在测试文件中,我们使用
WidgetTester
来渲染组件,并模拟用户交互(点击按钮)。 - 断言:我们使用
expect
函数来验证点击事件是否触发了预期的回调。
虽然Flutter没有直接等效于react_testing_library
的库,但flutter_test
提供了强大的功能来进行组件和应用的测试。通过结合使用这些工具,你可以编写出高效且可靠的测试用例。