定位到目標 widget

在測試環境下,為了定位 widgets,我們需要用到 Finder 類。我們可以編寫自己的 finder 類,不過通常使用 flutter_test package 提供的工具來定位 widgets 更加方便。

執行 widget 測試,在執行 flutter run 的時候,你還可以與螢幕進行互動點選, Flutter 工具會輸出建議的 Finder

下面,我們來看看 flutter_test package 提供的 find 常數並示範如何使用其所提供的 Finders。如需檢視完整的 finders 的清單,請參閱 CommonFinders 文件

如果你還不熟悉 Widget 測試和 Finder 類使用方法,請參閱 Widget 測試介紹

本教程包含以下步驟:

  1. 查詢 Text Widget

  2. 使用具體 Key 查詢 Widget

  3. 查詢具體的 Widget 實例

一. 查詢 Text widget

在測試中,我們經常需要查詢含有特定文字的 widget。這正是 find.text() 的用途。它會建立一個 Finder 來尋找顯示特定文字 String 的 widget。

testWidgets('finds a Text widget', (tester) async {
  // Build an App with a Text widget that displays the letter 'H'.
  await tester.pumpWidget(const MaterialApp(
    home: Scaffold(
      body: Text('H'),
    ),
  ));

  // Find a widget that displays the letter 'H'.
  expect(find.text('H'), findsOneWidget);
});

二. 使用具體 Key 查詢 widget

有時,我們可能想要透過已經提供給 widget 的 Key 來查詢 widget。這樣在顯示多個相同 widget 實體時會很方便。比如,我們有一個 ListView 清單,它顯示了數個含有相同文字的 Text widgets。

在這種情況下,我們可以為清單中的每一個 widget 賦予一個 Key。這樣我們就可以唯一識別特定的 widget,在測試環境中更容易查詢 widget。

testWidgets('finds a widget using a Key', (tester) async {
  // Define the test key.
  const testKey = Key('K');

  // Build a MaterialApp with the testKey.
  await tester.pumpWidget(MaterialApp(key: testKey, home: Container()));

  // Find the MaterialApp widget using the testKey.
  expect(find.byKey(testKey), findsOneWidget);
});

三. 查詢具體的 Widget 實例

最後,我們有時會需要查詢 widget 的具體實例。比如,當建立含有 child 屬性的 widget 並需要確保渲染 child widget。

testWidgets('finds a specific instance', (tester) async {
  const childWidget = Padding(padding: EdgeInsets.zero);

  // Provide the childWidget to the Container.
  await tester.pumpWidget(Container(child: childWidget));

  // Search for the childWidget in the tree and verify it exists.
  expect(find.byWidget(childWidget), findsOneWidget);
});

總結

在測試環境下,flutter_test 套件提供的 find 常數給了我們多種查詢 widget 的方法。本篇列舉了三種方法,另外還有一些其他用途的方法。

如果上述範例不適用於一些特殊情況,請到 CommonFinders 文件 中檢視更多用法。

完整範例

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

void main() {
  testWidgets('finds a Text widget', (tester) async {
    // Build an App with a Text widget that displays the letter 'H'.
    await tester.pumpWidget(const MaterialApp(
      home: Scaffold(
        body: Text('H'),
      ),
    ));

    // Find a widget that displays the letter 'H'.
    expect(find.text('H'), findsOneWidget);
  });

  testWidgets('finds a widget using a Key', (tester) async {
    // Define the test key.
    const testKey = Key('K');

    // Build a MaterialApp with the testKey.
    await tester.pumpWidget(MaterialApp(key: testKey, home: Container()));

    // Find the MaterialApp widget using the testKey.
    expect(find.byKey(testKey), findsOneWidget);
  });

  testWidgets('finds a specific instance', (tester) async {
    const childWidget = Padding(padding: EdgeInsets.zero);

    // Provide the childWidget to the Container.
    await tester.pumpWidget(Container(child: childWidget));

    // Search for the childWidget in the tree and verify it exists.
    expect(find.byWidget(childWidget), findsOneWidget);
  });
}