Testing Flutter apps翻譯-Widget測試介紹

翻譯首頁bash

單元測試的介紹裏,咱們學習到了如何使用test包測試Dart類,爲了測試Widget類,咱們須要一些由flutter test包提供的額外工具,這些工具隨Flutter SDK發佈。app

這個flutter_test包提供瞭如下用於測試Widget的工具:less

  • WidgetTester:該工具容許咱們在測試環境裏build Widget並與之交互。
  • 使用testWidgets函數。這個函數將自動對每一個測試用例建立一個WidgetTester,並用於替代普通的test函數。
  • Finder classes:該工具容許咱們在測試環境裏查找Widget。
  • Widget Matcher:一些常量,幫助咱們驗證在測試環境裏是否找到一個或者多個Widget。

若是上面的內容聽不懂的話,不要緊,讓咱們經過一些例子來將上面的碎片信息串聯到一塊兒。async

步驟:ide

  1. 添加flutter_test依賴。
  2. 建立一個Widget用來測試。
  3. 建立一個testWidgets測試方法。
  4. 使用WidgetTesterbuild一個Widget
  5. 使用Finder搜索咱們的Widget。
  6. 使用Matcher驗證咱們的Widget是否工做正常。

1. 添加flutter_test依賴。

在咱們開始寫測試以前,咱們須要在pubspec.yaml文件的dev_dependencies行下面添加flutter_test包。若是你經過命令行或者編譯器建立的Flutter項目,那麼該依賴已經添加好了。函數

dev_dependencies:
  flutter_test:
    sdk: flutter
複製代碼

2. 建立一個Widget用來測試。

下一步,咱們須要建立一個能讓咱們測試的Widget。在這個例子裏,咱們建立了顯示一個標題和一條信息的Widget。工具

class MyWidget extends StatelessWidget {
  final String title;
  final String message;

  const MyWidget({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: Text(message),
        ),
      ),
    );
  }
}
複製代碼

3. 建立一個testWidgets測試方法

如今咱們有了一個能夠用來測試的Widget,咱們能夠編寫咱們第一個測試用例了!咱們將會使用flutter_test包提供的testWidgets函數完成一個測試用例。這個testWidgets函數將會容許咱們定義一個Widget測試用例並建立一個WidgetTester給咱們使用。post

咱們的測試將會驗證MyWidget類是否正常顯示給定的標題和信息。單元測試

void main() {
  // Define a test. The TestWidgets function will also provide a WidgetTester
  // for us to work with. The WidgetTester will allow us to build and interact
  // with Widgets in the test environment.
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
    // Test code will go here!
  });
}
複製代碼

4. 使用WidgetTesterbuild一個Widget

下一步,咱們將會在測試環境裏build咱們的MyWidget類。爲了這麼作,咱們將使用WidgetTester提供的pumpWidget方法。這個pumpWidget方法將會build和渲染咱們提供的Widget。學習

在這個示例裏,咱們將會建立一個顯示標題「T」和消息「M」的MyWidget實例。

void main() {
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
    // Create the Widget tell the tester to build it
    await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));
  });
}
複製代碼

備註: 第一次調用pumpWidget以後,WidgetTester提供了從新建立相同Widget的其餘方式。若是你使用StatefulWidget或者動畫,這將會很是有用。

例如,若是咱們點擊一個按鈕,而且這個按鈕調用了setState方法,Flutter不會在測試環境裏rebuild你的Widget。咱們須要使用下面的方法之一來告訴Flutter再一次build咱們的Widget。

  • tester.pump()

    在一個給定的時間之後rebuild你的Widget。

  • tester.pumpAndSettle()

    在給定的時間不斷重複調用pump方法直到再也不有任何繪製任務。通常用於等待全部動畫完成。

這些方法提供了比build生命週期更細粒度的控制,這在測試的時候特別有用。

5. 使用Finder搜索咱們的Widget。

如今咱們已經在測試環境構建了咱們的Widget,咱們想要經過使用Finder在Widget樹裏搜索咱們的titlemessageWidget。這將容許咱們驗證是否正確顯示了那些Widget!

在這個例子裏,咱們將會使用flutter_test包提供的頂級find方法去建立咱們的Finder類。由於咱們知道咱們在尋找Text widget,因此咱們可使用find.text方法。 有關Finder類的更多信息,請查看在Widget測試裏查找Widget

void main() {
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
    await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));

    // Create our Finders
    final titleFinder = find.text('T');
    final messageFinder = find.text('M');
  });
}
複製代碼

6. 使用Matcher驗證咱們的Widget是否工做正常。

最後,咱們可使用flutter_test包提供的Matcher常量來驗證title和message Text Widgets是否出如今屏幕。 Matcher類是test包的核心部分,而且提供了通用的方式去驗證給定的值是否符合咱們的指望。

在這個例子裏,咱們想要咱們的Widgets只在屏幕出現一次。所以,咱們可使用findsOneWidget這個Matcher

void main() {
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
    await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));
    final titleFinder = find.text('T');
    final messageFinder = find.text('M');

    // Use the `findsOneWidget` matcher provided by flutter_test to verify our
    // Text Widgets appear exactly once in the Widget tree
    expect(titleFinder, findsOneWidget);
    expect(messageFinder, findsOneWidget);
  });
}
複製代碼

額外的Matcher: 在findsOneWidget之外,flutter_test爲常見用例提供了額外的Matcher

  • findsNothing

    驗證沒有Widget被找到。

  • findsWidgets

    驗證一個或者多個Widget被找到。

  • findsNWidgets

    驗證指定數量的Widget被找到。

完整示例:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  // Define a test. The TestWidgets function will also provide a WidgetTester
  // for us to work with. The WidgetTester will allow us to build and interact
  // with Widgets in the test environment.
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
    // Create the Widget tell the tester to build it
    await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));

    // Create our Finders
    final titleFinder = find.text('T');
    final messageFinder = find.text('M');

    // Use the `findsOneWidget` matcher provided by flutter_test to verify our
    // Text Widgets appear exactly once in the Widget tree
    expect(titleFinder, findsOneWidget);
    expect(messageFinder, findsOneWidget);
  });
}

class MyWidget extends StatelessWidget {
  final String title;
  final String message;

  const MyWidget({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Center(
          child: Text(message),
        ),
      ),
    );
  }
}
複製代碼
相關文章
相關標籤/搜索