我在TabbarView中有ListView小部件,允许用户滚动浏览每个选项卡的内容。我想测试一些屏幕外的小部件。我按照此操作滚动ListView以将相关小部件显示在屏幕上:
How to find off-screen ListView child in widget tests?
在我将ListView放在TabbarView中之前,这是正常的,然后它失败了。
我在TabbarView中重建了没有ListView的代码,测试通过。将ListView放置在TabbarView中会导致测试失败,原因如下:

'zero widgets with text "bbb" (ignoring offstage widgets)'

debugDumpApp()output显示这是因为没有滚动。
我的状态小部件:
class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
  TabController _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Scroll test'),
        ),
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return [
              SliverAppBar(
                expandedHeight: 100.0,
                bottom: TabBar(
                  controller: _tabController,
                  tabs: <Widget>[
                    Tab(
                      child: Text('Tab one'),
                    ),
                    Tab(
                      child: Text('Tab two'),
                    )
                  ],
                ),
              )
            ];
          },
          body: TabBarView(
            controller: _tabController,
            children: <Widget>[
              ListView(
                children: <Widget>[
                  Container(
                    height: 800.0,
                    child: Text('aaa'),
                  ),
                  Text('bbb')
                ],
              ),
              ListView(
                children: <Widget>[
                  Container(
                    height: 800.0,
                    child: Text('ccc'),
                  ),
                  Text('ddd')
                ],
              ),
            ],
          )
        )
    );
  }
}

我的测试:
void main() {
  Widget buildTestableWidget(Widget widget) {
    return new MediaQuery(
        data: new MediaQueryData(), child: new MaterialApp(home: widget));
  }

  Home home = Home();

  testWidgets('scroll test', (WidgetTester tester) async {
    await tester.pumpWidget(buildTestableWidget(home));

    expect(find.text('aaa'), findsOneWidget);
    expect(find.text('bbb'), findsNothing);

    final Offset point = tester.getCenter(find.text("aaa"));
    final gesture = await tester.startGesture(point);
    await gesture.moveBy(const Offset(0.0, -400.0));

    await tester.pump();

    expect(find.text('bbb'), findsOneWidget);
  });

}

这是一个bug,还是需要做一些不同的事情来获取testGesture.moveby以在TabbarView中工作?非常感谢你的帮助。

最佳答案

我认为这个问题与拖动结束在可滚动区域之外的事实有关,WidgetTester有一个名为dragFrom的方法,它为您处理该场景。

testWidgets('scroll test', (WidgetTester tester) async {
    await tester.pumpWidget(buildTestableWidget(home));

    expect(find.text('aaa'), findsOneWidget);
    expect(find.text('bbb'), findsNothing);

    final Offset point = tester.getCenter(find.text("aaa"));
    await tester.dragFrom(point, Offset(0.0, -400.0));

    await tester.pump();

    expect(find.text('bbb'), findsOneWidget);
  });

10-05 18:49