如何在小部件测试中找到屏幕外的 ListView 子项?

Posted

技术标签:

【中文标题】如何在小部件测试中找到屏幕外的 ListView 子项?【英文标题】:How to find off-screen ListView child in widget tests? 【发布时间】:2019-07-06 04:56:26 【问题描述】:

在 ListView 中显示多个子项时,如果一个子项不在屏幕上,则小部件测试无法找到它。这是一个完整的例子:

main.dart

import 'package:flutter/material.dart';

void main() => runApp(App());

class App extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(home: Scaffold(body: Test()));
  


class Test extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ListView(
      children: <Widget>[
        Container(
          height: 600,
          color: Colors.red,
        ),
        Text("Find me!"),
      ],
    );
  

main_test.dart

import 'package:flutter_app/main.dart';
import 'package:flutter_test/flutter_test.dart';

void main() 
  testWidgets("Find text", (WidgetTester tester) async 
    final testableWidget = App();

    await tester.pumpWidget(testableWidget);

    expect(find.text("Find me!"), findsOneWidget);
  );

此测试失败,但是如果我将 main.dart 中 Container 的高度更改为 599 ,则它可以工作。

有人知道为什么会这样吗?它是一个错误吗?有办法解决吗?

【问题讨论】:

【参考方案1】:

测试的行为应该与您的应用一样,否则,您的测试将变得毫无用处(因为您没有测试真正的行为)。 因此,这不是错误。

您必须在测试中手动滚动 ListView 以使其加载更多小部件。

这可以使用tester

final gesture = await tester.startGesture(Offset.zero /* THe position of your listview */ );
// Manual scroll
await gesture.moveBy(const Offset(0, 100));

await tester.pump(); // flush the widget tree 

【讨论】:

啊,好吧,有道理。谢谢。 值得一提,您还可以拖动列表视图中的小部件:await tester.drag(find.byType(Container), Offset(0.0, -200)); await tester.pump();【参考方案2】:

在 Finder 中将 skipOffstate 设置为 false 是另一种方法。试试这个:

expect(find.text("Find me!", skipOffstage: false), findsOneWidget);

【讨论】:

建议编辑:我认为 skipOffstate 不再是 ensureVisible 方法的参数:api.flutter.dev/flutter/widgets/Scrollable/ensureVisible.html 已编辑@AdrienArcuri ?【参考方案3】:

我强烈建议您注意屏幕/拖动运动的“笛卡尔平面”。

让我解释一下:

    您应该使用: await tester.drag(keyCartItemProduct1, Offset(-500.0, 0.0)); 但是,您的“偏移”命令必须遵循与拖动相同的“笛卡尔方向”。

2.1)因此:(命令偏移使用笛卡尔“方向”)-让我们看看: a) 左拖动:偏移量(-500.0, 0.0) b) 向右拖动:Offset(+500.0, 0.0) c) 向上拖动:Offset(0.0, +500.0) d) 向下拖动:Offset(0.0, -500.0)

【讨论】:

以上是关于如何在小部件测试中找到屏幕外的 ListView 子项?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 如何在小部件测试中选择 DropdownButton 项

Flutter:在小部件测试中测试异常

解决不可接受的 ListView 小部件

如何在 Flutter 的同一屏幕上沿 ListView 显示小部件?

如何在小部件测试期间存根不属于类的函数?

如何在颤动中截取屏幕之外的小部件屏幕截图?