许多应用都包含内容列表,从电子邮件客户端到音乐应用等等。要使用组件测试来验证列表是否包含预期内容,您需要一种方法来滚动列表以搜索特定项目。

要通过集成测试滚动列表,请使用 WidgetTester 类提供的方法,该类包含在 flutter_test 包中。

在本教程中,您将学习如何滚动项目列表以验证特定组件是否正在显示,以及不同方法的优缺点。

本示例将采取以下步骤

  1. 创建一个包含列表项的应用。
  2. 编写一个滚动列表的测试。
  3. 运行测试。

1. 创建一个包含列表项的应用

#

本教程将构建一个显示长列表项的应用。为了使本教程专注于测试,请使用在处理长列表教程中创建的应用。如果您不确定如何处理长列表,请参阅该教程以获取介绍。

将 key 添加到您希望在集成测试中与之交互的组件。

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

void main() {
  runApp(MyApp(items: List<String>.generate(10000, (i) => 'Item $i')));
}

class MyApp extends StatelessWidget {
  final List<String> items;

  const MyApp({super.key, required this.items});

  @override
  Widget build(BuildContext context) {
    const title = 'Long List';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(title: const Text(title)),
        body: ListView.builder(
          // Add a key to the ListView. This makes it possible to
          // find the list and scroll through it in the tests.
          key: const Key('long_list'),
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(
                items[index],
                // Add a key to the Text widget for each item. This makes
                // it possible to look for a particular item in the list
                // and verify that the text is correct
                key: Key('item_${index}_text'),
              ),
            );
          },
        ),
      ),
    );
  }
}

2. 编写一个滚动列表的测试

#

现在,您可以编写一个测试。在此示例中,滚动项目列表并验证列表中是否存在特定项目。WidgetTester 类提供了 scrollUntilVisible() 方法,该方法会滚动列表,直到特定组件可见。这很有用,因为列表项的高度可能会因设备而异。

scrollUntilVisible() 方法不会假定您知道列表中所有项目的高度,也不会假定特定组件在所有设备上都已渲染,而是会重复滚动项目列表,直到找到所需内容。

以下代码演示了如何使用 scrollUntilVisible() 方法在列表中查找特定项目。此代码位于名为 test/widget_test.dart 的文件中。

dart

// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

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

import 'package:scrolling/main.dart';

void main() {
  testWidgets('finds a deep item in a long list', (tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(
      MyApp(items: List<String>.generate(10000, (i) => 'Item $i')),
    );

    final listFinder = find.byType(Scrollable);
    final itemFinder = find.byKey(const ValueKey('item_50_text'));

    // Scroll until the item to be found appears.
    await tester.scrollUntilVisible(itemFinder, 500.0, scrollable: listFinder);

    // Verify that the item contains the correct text.
    expect(itemFinder, findsOneWidget);
  });
}

3. 运行测试

#

从项目根目录使用以下命令运行测试

flutter test test/widget_test.dart