0. 목표
Text.data 의 값이 'H' 인 Widget을 찾아 Widget Tree에 존재하는지 확인한다.
void main(){
testWidgets('find a Text widget', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
body: Text('H'),
),
));
expect(find.text('H'), findsOneWidget);
});
}
expect(Finder, Matcher)
expect(find.text('H'), findsOneWidget);
1. Finder
Type | Argument | 설명 |
Finder | find.text('H') | Text나 EditableText의 data field 가 'H'인 Widget을 찾아 Finder 로 반환한다. |
finders.dart
Finder text(String text, { bool skipOffstage = true })
=> _TextFinder(text, skipOffstage: skipOffstage);
class _TextFinder extends MatchFinder {
_TextFinder(this.text, { bool skipOffstage = true }) : super(skipOffstage: skipOffstage);
final String text;
@override
String get description => 'text "$text"';
@override
bool matches(Element candidate) {
final Widget widget = candidate.widget;
if (widget is Text) {
if (widget.data != null)
return widget.data == text;
assert(widget.textSpan != null);
return widget.textSpan!.toPlainText() == text;
} else if (widget is EditableText) {
return widget.controller.text == text;
}
return false;
}
}
_TextFinder 는 MatchFinder 를 상속받는다. matches는 Widget의 String 값(Text 는 data, EditableText는 controller의 text) 을 비교후 true/false를 반환한다.
2. Matcher
Type | function | 설명 |
Matcher | _findsWidgetMatcher(min, max) | 모든 matcher의 base 클래스 - matches, describe 는 필수 구현 클래스 bool matches( covariant Finder finder, Map<dynamic, dynamic> matchState); |
class _FindsWidgetMatcher extends Matcher {
const _FindsWidgetMatcher(this.min, this.max);
final int? min;
final int? max;
@override
bool matches(covariant Finder finder, Map<dynamic, dynamic> matchState) {
assert(min != null || max != null);
assert(min == null || max == null || min! <= max!);
matchState[Finder] = finder;
int count = 0;
final Iterator<Element> iterator = finder.evaluate().iterator;
if (min != null) {
while (count < min! && iterator.moveNext())
count += 1;
if (count < min!)
return false;
}
if (max != null) {
while (count <= max! && iterator.moveNext())
count += 1;
if (count > max!)
return false;
}
return true;
}
...
}
입력받은 Finder 의 element의 개수를 확인한다. findsOneWidget(1, 1) 은 Finder에 Widget이 하나만 있을 때 true 를 반환한다.
3. expect()
목적 : Actual 이 Matcher.matches() 를 만족하는지 확인한다.
expect()는 widget_tester.dart에 구현되어있고, 이 expect() 는 test_package.expect()를 호출한다.
test_package.expert()
void expect(actual, matcher,
{String? reason,
skip,
@Deprecated('Will be removed in 0.13.0.') bool verbose = false,
@Deprecated('Will be removed in 0.13.0.') ErrorFormatter? formatter}) {
_expect(actual, matcher,
reason: reason, skip: skip, verbose: verbose, formatter: formatter);
}
Future _expect(actual, matcher,
{String? reason, skip, bool verbose = false, ErrorFormatter? formatter}) {
formatter ??= (actual, matcher, reason, matchState, verbose) {
... 생략
var matchState = {};
try {
if ((matcher as Matcher).matches(actual, matchState)) {
return Future.sync(() {});
}
} catch (e, trace) {
reason ??= '$e at $trace';
}
fail(formatter(actual, matcher as Matcher, reason, matchState, verbose));
}
_expect() 의 내부구현을 보면 matcher가 Matcher의 인스턴스인 경우 Matcher.matches(Finder, matchState) 를 호출한다.
- Finder : 문자 'H'를 포함하는 Widget (find.text('H'))
- Matcher : Finder에서 찾은 Widget의 개수를 확인한다. (Matcher findsOneWidget = _FindWidgetMatcher(1, 1);)
Matcher.matches() 로 확인해 원하는 결과가 나오는지 확인한다. Widget이 1개라면 true를 반환하고 테스트 케이스를 통과한다. 그렇지 않으면 false를 반환하게되고 테스트 결과가 실패로 나온다.
'Flutter' 카테고리의 다른 글
dart 유닛 테스트 (0) | 2021.07.12 |
---|---|
Flutter Widget Test (0) | 2021.07.04 |
Null Safety (0) | 2021.06.02 |