【Flutter test】Flutterのテスト、チートシート

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, isNotNaN

  • int/double
    1, equals(1), isZero, isNonZero, isNotNaN, 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 Exception("message"); 	
   fail("Exception was not thrown");
} on Exception catch(e){ expect(e.message, "message");
} catch(e){ fail('Not-expect object was thrown');}

Widget Test, Integration Test用

  • Finder (Wigetを見つける)
    text(‘1’), textContaining(‘1’), byKey(Key(‘1’)), byWidget(Text(‘1’)), widgetWithText(‘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 (画面操作を行う)
    drag, dragFrom, dragUntilVisible, fling, flingFrom
    longPress, longPressAt, press, tap, tapAt
    enterText, pageBack, showKeyboard

  • Matcher(ユニットテスト以外で条件のWidget数を確認する)
    findsOneWidget, findsNothing, findsWidget, findsNWidgets(5)

出典:「FlutterでのはじめてのTDD! 」(https://flutter.salon/tdd)

まとめ

講座の方でも取り扱っていないFinderやActionがあります。引き続き講座とこのチートシート自体の改善・加筆を行っていこうと思います。