自定义小部件测试需要 Material 个小部件进行测试
Custom widget testing needs Material widget to test
我正在尝试在 Flutter 中执行基本的小部件测试。基本上我想要一个包含数据列表的列表,并在自定义小部件(BasicListItem)中显示每个项目,它也有一个其中包含 ListTile 小部件。
根小部件:
class MyApp extends StatelessWidget {
final List taskList = ['List-1', 'List-2', 'List-3'];
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: ListView.builder(
itemCount: taskList.length, itemBuilder: _itemBuilder),
),
);
}
Widget _itemBuilder(BuildContext context, int index) {
final String item = taskList[index];
return BasicListItem(key: Key(item), title: item);
}
}
列表项小部件 (BasicListItem) 采用标题,并在 ListTile 小部件中使用它。
class BasicListItem extends StatelessWidget {
final String title;
const BasicListItem({required Key key, required this.title})
: super(key: key);
@override
Widget build(BuildContext context) {
return ListTile(
leading: Icon(Icons.map),
title: Text(title),
);
}
}
这是对它的测试:
testWidgets('has title and Icons', (WidgetTester tester) async {
const testKey = Key('my-key-1');
const testTitle = 'Demo title';
await tester.pumpWidget(BasicListItem(key: testKey, title: testTitle));
expect(find.text(testTitle), findsOneWidget);
});
但是测试报错:
No Material widget found. ListTile widgets require a Material widget
ancestor.
...
...
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree Actual:
_TextFinder:<zero widgets with text "Demo title" (ignoring offstage widgets)>
但是,如果我在 BasicListItem 构建方法中将 ListTile 包裹在 MaterialApp 周围,测试会 pass。像这样:
@override
Widget build(BuildContext context) {
return MaterialApp(
title: title,
home: Scaffold(
body: ListTile(
leading: Icon(Icons.map),
title: Text(title),
),
)
);
}
但是这样做我不能在 ListView 小部件中使用它。而且我还想要 modular/separate 自定义小部件,这样我也可以在不同的地方使用它。我是新来的,也许我遗漏了一些东西。如何构建自定义小部件并对其进行测试?你能帮帮我吗
ListTile
组件来自 Flutter UI 组件的 Material
部分 & 不是一个独立的 widget,因此它需要一个 MaterialApp
作为父组件。
您可以在此处检查 ListTile
是否在 material 库下:https://api.flutter.dev/flutter/material/ListTile-class.html
此外,您可以创建尽可能多的自定义 Widgets
以在单独的模块中使用,
唯一的要求是在应用程序初始化的最开始使用 MaterialApp
。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// Only this needs to be a MaterialApp
return MaterialApp(
title: 'Welcome to Flutter',
/// this point to different screen widget also, like MainScreen()
/// Or you can start using Scaffold from here as well.
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Text('Hello World'),
),
),
);
}
}
没有必要在您构建的每个自定义小部件上使用 MaterialApp
作为父级。根也可以。
但是,如果您使用单个小部件进行简单测试,并且它需要一个 Material
祖先,您也可以简单地将小部件包装在 Material
小部件中。
起初我不明白 Darshan 的回答,因为我认为他提供的代码让我将 MaterialApp 和 Material 小部件实现为 BasicListItem 小部件 class 直接构建方法,而不是只在测试服上实现它。但这给了我实现它的线索。
所以,这是最终的测试用例。我确实用 BasicListItem 包装了 MaterialApp 和 Material 小部件,但不是在构建方法中,而是我将它们包装在测试用例上:
testWidgets('has title and Icons', (WidgetTester tester) async {
const testKey = Key('my-key-1');
const testTitle = 'Demo title';
await await tester.pumpWidget(MaterialApp(
home: Material(
child: BasicListItem(key: testKey, title: testTitle),
),
));;
expect(find.text(testTitle), findsOneWidget);
});
我希望这也能帮助像我一样的人。
好的,这在 Flutter Docs 中并没有特别提及,但在各处都有暗示。在 flutter 测试方面,我们抽取一个根小部件来渲染一个框架,作为我们用于测试小部件的调色板。
转换为您需要创建一个 Root App Widget 来包装被测小部件。 eBay 的 Golden Toolkit 提供了挂钩,可以通过 pumpWidgetBuilder 实现这一点,它是 Widget Tester 的扩展。
有关更多信息,请参阅我的博客,https://fredgrott.medium.com
我正在尝试在 Flutter 中执行基本的小部件测试。基本上我想要一个包含数据列表的列表,并在自定义小部件(BasicListItem)中显示每个项目,它也有一个其中包含 ListTile 小部件。
根小部件:
class MyApp extends StatelessWidget {
final List taskList = ['List-1', 'List-2', 'List-3'];
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: ListView.builder(
itemCount: taskList.length, itemBuilder: _itemBuilder),
),
);
}
Widget _itemBuilder(BuildContext context, int index) {
final String item = taskList[index];
return BasicListItem(key: Key(item), title: item);
}
}
列表项小部件 (BasicListItem) 采用标题,并在 ListTile 小部件中使用它。
class BasicListItem extends StatelessWidget {
final String title;
const BasicListItem({required Key key, required this.title})
: super(key: key);
@override
Widget build(BuildContext context) {
return ListTile(
leading: Icon(Icons.map),
title: Text(title),
);
}
}
这是对它的测试:
testWidgets('has title and Icons', (WidgetTester tester) async {
const testKey = Key('my-key-1');
const testTitle = 'Demo title';
await tester.pumpWidget(BasicListItem(key: testKey, title: testTitle));
expect(find.text(testTitle), findsOneWidget);
});
但是测试报错:
No Material widget found. ListTile widgets require a Material widget ancestor.
... ...
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree Actual: _TextFinder:<zero widgets with text "Demo title" (ignoring offstage widgets)>
但是,如果我在 BasicListItem 构建方法中将 ListTile 包裹在 MaterialApp 周围,测试会 pass。像这样:
@override
Widget build(BuildContext context) {
return MaterialApp(
title: title,
home: Scaffold(
body: ListTile(
leading: Icon(Icons.map),
title: Text(title),
),
)
);
}
但是这样做我不能在 ListView 小部件中使用它。而且我还想要 modular/separate 自定义小部件,这样我也可以在不同的地方使用它。我是新来的,也许我遗漏了一些东西。如何构建自定义小部件并对其进行测试?你能帮帮我吗
ListTile
组件来自 Flutter UI 组件的 Material
部分 & 不是一个独立的 widget,因此它需要一个 MaterialApp
作为父组件。
您可以在此处检查 ListTile
是否在 material 库下:https://api.flutter.dev/flutter/material/ListTile-class.html
此外,您可以创建尽可能多的自定义 Widgets
以在单独的模块中使用,
唯一的要求是在应用程序初始化的最开始使用 MaterialApp
。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// Only this needs to be a MaterialApp
return MaterialApp(
title: 'Welcome to Flutter',
/// this point to different screen widget also, like MainScreen()
/// Or you can start using Scaffold from here as well.
home: Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
child: Text('Hello World'),
),
),
);
}
}
没有必要在您构建的每个自定义小部件上使用 MaterialApp
作为父级。根也可以。
但是,如果您使用单个小部件进行简单测试,并且它需要一个 Material
祖先,您也可以简单地将小部件包装在 Material
小部件中。
起初我不明白 Darshan 的回答,因为我认为他提供的代码让我将 MaterialApp 和 Material 小部件实现为 BasicListItem 小部件 class 直接构建方法,而不是只在测试服上实现它。但这给了我实现它的线索。
所以,这是最终的测试用例。我确实用 BasicListItem 包装了 MaterialApp 和 Material 小部件,但不是在构建方法中,而是我将它们包装在测试用例上:
testWidgets('has title and Icons', (WidgetTester tester) async {
const testKey = Key('my-key-1');
const testTitle = 'Demo title';
await await tester.pumpWidget(MaterialApp(
home: Material(
child: BasicListItem(key: testKey, title: testTitle),
),
));;
expect(find.text(testTitle), findsOneWidget);
});
我希望这也能帮助像我一样的人。
好的,这在 Flutter Docs 中并没有特别提及,但在各处都有暗示。在 flutter 测试方面,我们抽取一个根小部件来渲染一个框架,作为我们用于测试小部件的调色板。
转换为您需要创建一个 Root App Widget 来包装被测小部件。 eBay 的 Golden Toolkit 提供了挂钩,可以通过 pumpWidgetBuilder 实现这一点,它是 Widget Tester 的扩展。
有关更多信息,请参阅我的博客,https://fredgrott.medium.com