Flutter测试辅助插件react_testing_library的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter测试辅助插件react_testing_library的使用

介绍

react_testing_library 是一个用于 Dart 的测试库,它提供了与 JavaScript 中 dom-testing-libraryreact-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

1 回复

更多关于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_testintegration_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提供了强大的功能来进行组件和应用的测试。通过结合使用这些工具,你可以编写出高效且可靠的测试用例。

回到顶部