「Flutter Advent Calendar 2022」に参加させて頂きます!最終日です。皆様、お疲れ様です
PDF版(2ページ目を印刷して使う、再配布可能)
はじめに
Udemyにて、Flutterのテストの講座「FlutterでのはじめてのTDD(テスト 駆動開発)!」を公開しております。講座受講者の方向けにFlutterのテストのためのチートシートを作成してましたが、せっかくなので一般公開します。
よく分かるシート、より、1枚印刷して手元で確認できる思い出し用のシートを目指してます(どんなメソッドか名前で想像つきますよね?)。講座の方でどうやって使うか説明してますので、使い方の知りたい方、気に入ったのでお布施していただける神の方はご受講頂けると嬉しいです。(やる気に繋がります!)
実行
flutter test
flutter test test/widget_test.dart –plain-name=’testName’ (テストの指定。ファイル名、テスト名、なくても大丈夫)
flutter drive –driver=test_driver/integration_test.dart –target=integration_test/app_test.dart (インテグレーションテスト)
雛形
Unit Test と Widget Test
- /project/test/targetClass_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
void main() {
setUpAll(() async {});
setUp(() async {});
tearDown(() async {});
tearDownAll(() async {});
group('groupName', () {
test('unit test',() async{
expect(statement, Macher);
fail('reason');
});
testWidgets('widget test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Text("0"),
),);
await tester.pump();
expect(find.Finder, Matcher);
await tester.Action(Finder);
await tester.pumpAndSettle();
});
});
}
インテグレーションテストの導入はこちら
Matcher(全てのテスト)
-
共通
isNull, isNotNull, same(a), isNot(a) -
bool
isTrue, isFalse, isNaN, isNotNaN -
int/double
1, equals(1), isZero, isNonZero, isPositive, isNegative, isNonNegative, isNonPositive,
greaterThan(0), greaterThanOrEqualTo(0), lessThan(2), lessThanOrEqualTo(2)
inClosedOpenRange(0,2), inOpenClosedRange(0,2), inInclusiveRange(0,2), inExclusiveRange(0,2)
closeTo(2, 1) -
String
‘abcd’, equals(‘abcd’), equalsIgnoringCase(‘abcd’), equalsIgnoringWhitespace(‘abcd’)
contains(‘a’), startsWith(‘a’), endsWith(‘d’), stringContainsInOrder([‘a’, ‘b’, ‘c’, ‘d’]) -
List/Set/Map
hasLength(3), contains(1), containsAll([1,3]), containsAllInOrder([1,5])
orderedEquals([1, 3, 5]), unorderedEquals([3, 1, 5]) -
例外
actualに例外が発生することを書いて、expectに想定された例外クラスが発生したことを確認するMatcherを書く。クラスの型だけでなく詳細を確認したい場合は、次の項目の方法で確認する。
expect(() => throw Exception(), throwsA(isA<Exception>()));
expect(() => throw Exception(), throwsA(isInstanceOf<Exception>()));(非推奨) -
例外の発生でfailを避けて、想定通りの例外か詳細まで確認できる
try {
throw FormatException("wrong_format");
fail("Exception was not thrown");
} on FormatException catch(e){ expect(e.message, "wrong_format");
} catch(e){ fail('Not-expect object was thrown');}
expect(
() => throw const FormatException('wrong_format'),
throwsA(isA<FormatException>()
.having((e) => e.message, 'check message', 'wrong_format')
.having((e) => e.toString(), 'check toString', 'FormatException: wrong_format')));
Widget Test, Integration Test用
-
Finder (Wigetを見つける) -> findからアクセス
text(‘1’), textContaining(‘1’), byKey(Key(‘1′)), byWidget(instance), widgetWithText(Column,’1’),
byWidgetPredicate((widget){return true;}), byType(Text), byIcon(Icons.add),
widgetWithIcon(FloatingActionButton, Icons.add), widgetWithImage, image(FileImage(File(filePath),
byTooltip(‘Increment’), bySemanticsLabel(‘semantics’),
ancestor(of: find.text(‘add’), matching: find.byType(Center)),
descendant(of: find.byType(Center), matching: find.text(‘add’)),
byElementType(SingleChildRenderObjectElement), bySubtype() -
Action (画面操作を行う) -> testerからアクセス
widget, widgetList, firstWidget
drag, dragFrom, dragUntilVisible, fling, flingFrom
longPress, longPressAt, press, tap, tapAt
enterText, pageBack, showKeyboard -
Matcher(ユニットテスト以外で条件のWidget数を確認する)
findsOneWidget, findsNothing, findsWidget, findsNWidgets(5)
まとめ
講座の方でも取り扱っていないFinderやActionがあります。引き続き講座とこのチートシート自体の改善・加筆を行っていこうと思います。