https://www.inflearn.com/course/flutter-테스트-기초/dashboard 의 기반으로 TDD 연습 하기
dependencies:
cupertino_icons: ^1.0.6
mockito: ^5.4.4
dio: ^5.5.0+1
freezed_annotation: ^2.4.3
json_annotation: ^4.9.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
build_runner: ^2.4.11
custom_lint: ^0.6.4
freezed: ^2.5.2
json_serializable: ^6.8.0
- 테스튼 예상이 필요한 변수 및 로직을 적고, 그 다음에 예측이 필요한 변수, 예측하는 값을 적는게 테스트의 기본이다.
- testWidgets() : 위젯 테스트 시, 시작
- pumpWidget() : runApp()에 해당
- pump(Duration?) : 지정된 시간 후에 setState() 효과 - 다시 그리기
- pumpAndSettle() : 에니메이션이 끝날 때 까지 pump()를 반복
- find : CommonFinder를 사용하는 top-level 함수
=> 이걸 사용하면 편리하게 위젯을 찾을 수 있음 - findsOneWidget : 1개의 위젯을 찾았는지
공식 문서 예시
testWidget('find a widget using a key', (tester)async{
const testKey = Key('k');
// build a MaterialApp with TestKey
await tester.pumpWidget(MaterialApp(key: testKey, home: Container()));
// find the MaterialApp widget using the testKey
expect(find.byKey(testKey), findsOneWidget);
});
특정 위젯의 인스턴스를 찾을 때 편리
testWidgets('find a specific instance',(tester) async {
const childWidget = Padding(padding : EdgeInsets.zero);
await tester.pumpWidget(Container(child: childWidget));
expect(find.byWidget(childWidget), findsOneWidget);
});
- scrollUntilVisible() : 대상이 보일 때까지 스크롤해서 찾기 때문에 편리함
void main() {
testWidgets('finds a deep item in a long list', (tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp(
items: List<String>.generate(10000, (i) => 'Item $i'),
));
final listFinder = find.byType(Scrollable);
final itemFinder = find.byKey(const ValueKey('item_50_text'));
// Scroll until the item to be found appears.ㅋ
await tester.scrollUntilVisible(
itemFinder,
500.0,
scrollable: listFinder,
);
// Verify that the item contains the correct text.
expect(itemFinder, findsOneWidget);
});
}
테스트 환경에서는 유저와의 인터렉션을 시뮬레이팅 해야함 테스트 환경에서는 상태가 변경되어도 자동으로 화면을 다시 그리지 않기 때문에 pump() : 그냥 나타는 것들 또는 pumpAndSettle() : 에니메이팅이 들어가면서 생겨나는 것들을 사용하여 다시 그리기를 시뮬레이팅을 해야함 (setState)
testWidgets('Add and remove a todo', (tester)async {
// wait build the widget
await tester.pumpWidget(const TodoList());
// Simulate Enter 'hi' into the TextField
await tester.enterText(find.byType(TextField), 'hi');
});
tap() 이후에는 pump() 혹은 pumpAndSettle() 을 실행해야 반영됨
testWidget('Add and remove a todo', (tester)async {
// Tap the add button
await tester.tap(find.byType(FloatingActionButton));
// Rebuilt the widget after State Changed
await tester.pump();
// Expect to find the item on screen
expect(find.text('hi'), findsOneWidget);
})
testWidget('Add and remove a todo', (tester)async {
// Tap the add button
await tester.drag(find.byType(Dismissible), const Offset(500, 0));
// Rebuilt the widget after State Changed
await tester.pumpAndSettle();
// Expect to find the item on screen
expect(find.text('hi'), findsOneWidget);
})
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
이 무조건 선행 되어야 한다.
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('end-to-end test', () {
testWidgets('Tap~', (tester) async {
await tester.pumpWidget(const MyApp());
});
});
}