Die Ăśbersetzung des Materials wurde im Rahmen des Online-Kurses " Flutter Mobile Developer " vorbereitet .
Wir laden außerdem alle zu einem kostenlosen zweitägigen Intensivkurs „Erstellen einer Flutter-App für Web, iOS und Android“ ein . Während des Intensivkurses erfahren wir genau, wie Sie mit Flutter Anwendungen für die Webplattform erstellen können und warum die Funktionalität jetzt stabil ist. wie die Webassembly funktioniert. Schreiben wir eine Anwendung mit Netzwerk. Details und Anmeldung hier .
Dies ist eine Fortsetzung des ersten Teils des Artikels zum Testen von Widgets in Flutter .
Lassen Sie uns den Widget-Testprozess weiter untersuchen.
, testWidgets()
. , , , — . , , , .
:
.
test.
testWidgets()
, .
.
?
:
.
.
, . :
.
- (, ).
(, ), .
, .
, , . test:
void main() {
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
},
);
}
, WidgetTester
, . .
, pumpWidget()
:
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
),
),
);
},
);
( await
, .)
.
WidgetTester
, .
-
, «» , .
, , , — , . .
, ? -, Finder
. ( , .)
, - — , , . .
:
find.byType()
Text:
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Text('Hi there!'),
),
),
),
);
var finder = find.byType(Text);
},
);
- CommonFinders
find
. byType()
. , , . , Text
, , :
find.text()
Text, find.text()
:
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Text('Hi there!'),
),
),
),
);
var finder = find.text('Hi there!');
},
);
EditableText
, TextField
.
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
var controller = TextEditingController.fromValue(TextEditingValue(text: 'Hi there!'));
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: TextField(controller: controller,),
),
),
),
);
var finder = find.text('Hi there!');
},
);
find.byKey()
— :
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Icon(
Icons.add,
key: Key('demoKey'),
),
),
),
),
);
var finder = find.byKey(Key('demoKey'));
},
);
find.descendant() find.ancestor()
, , ( -).
, , Center, . :
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
key: Key('demoKey'),
child: Icon(Icons.add),
),
),
),
);
var finder = find.descendant(
of: find.byKey(Key('demoKey')),
matching: find.byType(Icon),
);
},
);
, Center ( of
) , -.
find.ancestor()
, , , , of
.
Center, :
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
key: Key('demoKey'),
child: Icon(Icons.add),
),
),
),
);
var finder = find.ancestor(
of: find.byType(Icon),
matching: find.byKey(Key('demoKey')),
);
},
);
-
find.xxxx()
Finder
. ?
, , -, , . BadlyWrittenWidgetFinder
.
MatchFinder
.
class BadlyWrittenWidgetFinder extends MatchFinder {
@override
// TODO: implement description
String get description => throw UnimplementedError();
@override
bool matches(Element candidate) {
// TODO: implement matches
throw UnimplementedError();
}
}
2. matches()
, . , null
:
class BadlyWrittenWidgetFinder extends MatchFinder {
BadlyWrittenWidgetFinder({bool skipOffstage = true})
: super(skipOffstage: skipOffstage);
@override
String get description => 'Finds icons with no key';
@override
bool matches(Element candidate) {
final Widget widget = candidate.widget;
return widget is Icon && widget.key == null;
}
}
3. , - CommonFinders
( find
):
extension BadlyWrittenWidget on CommonFinders {
Finder byBadlyWrittenWidget({bool skipOffstage = true }) => BadlyWrittenWidgetFinder(skipOffstage: skipOffstage);
}
4. - , :
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
key: Key('demoKey'),
child: Icon(Icons.add),
),
),
),
);
var finder = find.byBadlyWrittenWidget();
},
);
, -, WidgetTester
.
, WidgetTester
, , .
WidgetTester
. , , . :
setState()
, .
setState()
, , . ? pump
.
pump
:
pump()
( ),pumpWidget()
,pumpAndSettle()
pump()
, ( ).
pumpWidget()
, pumpWidget()
. runApp()
, , pump()
. .
pump()
pump()
, . , :
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
var count = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Text('$count'),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
count++;
});
},
),
),
);
}
}
FloatingActionButton
, -.
: , , 1:
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(CounterWidget());
var finder = find.byIcon(Icons.add);
await tester.tap(finder);
// Ignore this line for now
// It just verifies that the value is what we expect it to be
expect(find.text('1'), findsOneWidget);
},
);
:
, Text
, , setState()
, . pump()
:
testWidgets(
'Test description',
(WidgetTester tester) async {
// Write your test here
await tester.pumpWidget(CounterWidget());
var finder = find.byIcon(Icons.add);
await tester.tap(finder);
await tester.pump();
// Ignore this line for now
// It just verifies that the value is what we expect it to be
expect(find.text('1'), findsOneWidget);
},
);
:
, pump()
— :
await tester.pump(Duration(seconds: 1));
, , .
pump
: . EnginePhase
:
enum EnginePhase {
/// The build phase in the widgets library. See [BuildOwner.buildScope].
build,
/// The layout phase in the rendering library. See [PipelineOwner.flushLayout].
layout,
/// The compositing bits update phase in the rendering library. See
/// [PipelineOwner.flushCompositingBits].
compositingBits,
/// The paint phase in the rendering library. See [PipelineOwner.flushPaint].
paint,
/// The compositing phase in the rendering library. See
/// [RenderView.compositeFrame]. This is the phase in which data is sent to
/// the GPU. If semantics are not enabled, then this is the last phase.
composite,
/// The semantics building phase in the rendering library. See
/// [PipelineOwner.flushSemantics].
flushSemantics,
/// The final phase in the rendering library, wherein semantics information is
/// sent to the embedder. See [SemanticsOwner.sendSemanticsUpdate].
sendSemanticsUpdate,
}
await tester.pump(Duration.zero, EnginePhase.paint);
. , . .
pumpAndSettle()
pumpAndSettle()
— , , pump, , . .
( ), — -, .
await tester.pumpAndSettle(
Duration(milliseconds: 10),
EnginePhase.paint,
Duration(minutes: 1),
);
WidgetTester
« + ». :
tester.drag()
, - . , X Y:
var finder = find.byIcon(Icons.add);
var moveBy = Offset(100, 100);
var slopeX = 1.0;
var slopeY = 1.0;
await tester.drag(finder, moveBy, touchSlopX: slopeX, touchSlopY: slopeY);
, tester.timedDrag()
:
var finder = find.byIcon(Icons.add);
var moveBy = Offset(100, 100);
var dragDuration = Duration(seconds: 1);
await tester.timedDrag(finder, moveBy, dragDuration);
, -, tester.dragFrom()
, .
var dragFrom = Offset(250, 300);
var moveBy = Offset(100, 100);
var slopeX = 1.0;
var slopeY = 1.0;
await tester.dragFrom(dragFrom, moveBy, touchSlopX: slopeX, touchSlopY: slopeY);
— tester.timedDragFrom()
.
var dragFrom = Offset(250, 300);
var moveBy = Offset(100, 100);
var duration = Duration(seconds: 1);
await tester.timedDragFrom(dragFrom, moveBy, duration);
. ,
tester.fling()
tester.drag()
.
: «» .
:
var dragFrom = Offset(250, 300);
var gesture = await tester.startGesture(dragFrom);
, .
:
var dragFrom = Offset(250, 300);
var gesture = await tester.startGesture(dragFrom);
await gesture.moveBy(Offset(50.0, 0));
await gesture.moveBy(Offset(0.0, -50.0));
await gesture.moveBy(Offset(-50.0, 0));
await gesture.moveBy(Offset(0.0, 50.0));
await gesture.up();
, , . , , , , , ( , — , - , ).
Finder
WidgetTester
. — .
« Flutter Web, iOS Android».