유닛 테스트 보다 더 복잡한 방법의 테스트이긴 하지만, flutter_test
패키지 덕분에 유닛 테스트와 비슷한 방법으로 테스를 수행할 수 있다.
예를 들어, 다음과 같이 ListTile
위젯이 4개가 있는 계산기 앱이 있다고 하면,
import 'package:flutter/material.dart';
void main() {
runApp(const CalculatorPage());
}
class CalculatorPage extends StatelessWidget {
const CalculatorPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("Calculator"),
),
body: Column(
children: const [
ListTile(
title: Text("Addition"),
leading: Icon(Icons.add),
),
ListTile(
title: Text("Subtraction"),
leading: Icon(Icons.minimize),
),
ListTile(
title: Text("Multiplication"),
leading: Icon(Icons.cancel_outlined),
),
ListTile(
title: Text("Division"),
leading: Icon(Icons.architecture),
),
],
),
),
);
}
}
유닛테스트에서 test
함수를 사용할 때 처럼 다음과 같이 testWidgets
함수를 사용하면 된다.
void main() {
group('CalculatorApp', () {
testWidgets('Render 4 widgets of Type ListTile',
(WidgetTester tester) async {
await tester.pumpWidget(const CalculatorPage());
expect(find.byType(ListTile), findsNWidgets(4)); // Expecting 4 ListTile widget on Screen.
});
});
}
WidgetTest
객체를 넘겨준다.WidgetTester
클래스에는 pumpWidget
함수가 있는데, 넘겨진 위젯을 최상위 트리부터 구성해서 렌더링 하는 함수이다. 이 함수에 테스트하고자 하는 위젯을 넘겨줌으로써 마치 UI 렌더링 된 상황처럼 테스트를 진행할 수 있다.테스트 단계에서는 터치 이벤트나 입력 폼을 채우는 동작 또는 스크롤 동작 등을 실행하기가 어렵다.
이 때를 테스트하기 위해, 다음과 같이 숫자 2개를 입력받아 더하는 위젯이 있다고 하자.
Column(
children: [
ListTile(
leading: Icon(Icons.add),
title: Text("Addition"),
),
TextField(
key: ValueKey('addFirst'),
decoration: InputDecoration(hintText: '1st number'),
onChanged: (value) => addFirst = int.tryParse(value),
keyboardType: TextInputType.number,
),
TextField(
key: ValueKey('addSecond'),
decoration: InputDecoration(hintText: '2st number'),
keyboardType: TextInputType.number,
onChanged: (value) {
addSecond = int.tryParse(value);
addResult = (addFirst ?? 0) + (addSecond ?? 0);
},
),
if (addResult == null) ...[
Text('Result '),
] else ...[
Text('Result $addResult'),
],
],
)
위의 입력 기능을 테스트하기 위해선 다음과 같이 정의하면 된다.
group(
'add',
() {
testWidgets('show result when two inputs are given',
(WidgetTester widgetTester) async {
await widgetTester.pumpWidget(const CalculatorPage());
await widgetTester.enterText(find.byKey(Key('addFirst')), '3');
await widgetTester.enterText(find.byKey(Key('addSecond')), '4');
await widgetTester.pump();
expect(find.text('Result 7'), findsOneWidget);
});
},
)
위 코드는 enterText
함수를 통해 위젯에 텍스트를 입력하는 기능이며, 첫번째 인자로 valueKey를 찾아서 그 키에 해당하는 위젯을 넣어주고 두번째 인자로 입력할 텍스트를 넣어준다.
expect
함수는 pumpWidget
함수를 실행했을 때의 UI를 기준으로 ‘Result 7’ 이라는 글자가 존재하는지 찾아보기 때문이다.pump
함수를 사용해 새 프레임을 그리도록 해준다.pump
함수는 이런 경우에 1프레임을 새롭게 그리기 위해 사용하는 함수이며, 따라서 애니메이션 작동 여부 같이 여러 프레임을 확인해야 하는 테스트에는 적합하지 않다.