# 使用 Screenutil 時在自動化測試會出錯
基本的 testWidget 渲染測試的程式碼:
```dart=
Text longTextTestFieldWidget() {
return Text(
'A lengthy test to generate a specific amount of text to observe its appearance.',
style: TextStyle(
// 使用 Screenutil 來設定文字大小
fontSize: 30.sp,
),
);
}
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester
.pumpWidget(longTextTestFieldWidget);
expect(
find.text(
'A lengthy test to generate a specific amount of text to observe its appearance.'),
findsOneWidget);
});
}
```
當我們執行後會發會爆錯,主要是 16 行在比對元件時發生錯誤:
```log
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following LateError was thrown building Builder(dirty):
LateInitializationError: Field '_minTextAdapt@304084504' has not been initialized.
```
從錯誤來看,推測有可能是 Screenutil 並沒有初始化,所以嘗試使用ScreenUtilInit 來包住我們需要的 Widget
```dart!
await tester.pumpWidget(
// 新增 ScreenUtilInit 做初始化
ScreenUtilInit(
designSize: Size(360, 690),
useInheritedMediaQuery: true,
builder: (_, __) {
return longTextTestFieldWidget();
},
),
);
```
執行後我們會再次收到一個錯誤,告訴我們找不到可以比對的元件,主要是因為 `pumpWidget` 本身執行時,並不會等所有畫面都渲染完成,所以 `ScreenUtilInit` 並還沒有執行完成就嘗試要 `findsOneWidget` 就會有問題
```
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: exactly one matching candidate
Actual: _TextWidgetFinder:<Found 0 widgets with text "A very long test to create a certain amount
of text to see how it looks like.": []>
Which: means none were found but one was expected
```
解決方法也很簡單,我們只要在 pumpWidget 的下一行,再加上一行 `tester.pumpAndSettle()`
```dart!
await tester.pumpWidget(ScreenUtilInit(
designSize: Size(360, 690),
useInheritedMediaQuery: true,
builder: (_, __) {
return longTextTestFieldWidget();
},
));
// 重建畫布並等待所有元件渲染完成
await tester.pumpAndSettle();
```
接著我們會收到另一個錯誤...
```log!
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building Text("A very long test to create a certain amount of
text to see how it looks like.", inherit: true, size: 44.4, dependencies: [MediaQuery]):
No Directionality widget found.
RichText widgets require a Directionality widget ancestor.
```
從錯誤上來看我們可以新增 Directionality,就會發現可以正常執行
```dart!
await tester.pumpWidget(ScreenUtilInit(
designSize: Size(360, 690),
useInheritedMediaQuery: true,
builder: (_, __) {
return Directionality(
textDirection: TextDirection.ltr,
child: longTextTestFieldWidget(),
);
},
));
```
之後遇到不同 Widget 的話會需要經常修改程式碼,因此可以直接加上 MaterialApp 來解決這個問題
```dart!
await tester.pumpWidget(
// 新增 MaterialApp 在最外層
MaterialApp(
home: ScreenUtilInit(
designSize: Size(360, 690),
useInheritedMediaQuery: true,
builder: (_, __) {
return longTextTestFieldWidget();
},
),
),
);
```
最後就能正確執行,且驗證這個 Text Widget 是可以被正常渲染的!
```dart=
Widget longTextTestFieldWidget() {
return Text(
'A lengthy test to generate a specific amount of text to observe its appearance.',
style: TextStyle(fontSize: 20.sp),
);
}
void main() {
testWidgets('Long text test', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: ScreenUtilInit(
designSize: Size(360, 690),
useInheritedMediaQuery: true,
builder: (_, __) {
return longTextTestFieldWidget();
},
),
),
);
await tester.pumpAndSettle();
expect(
find.text(
'A lengthy test to generate a specific amount of text to observe its appearance.'),
findsOneWidget);
}
}
```
到這裡 Screenutil 自動化測試的錯誤都已經解決。
若每次都得在 pumpWidget 時,去增加這麼冗長的程式碼,這樣對鍵盤太傷 XD
可以參考下面這樣的寫法,將 `ScreenUtilInit` 及 `MaterialApp` 封裝起來,之後只要從外面將要測試的 Widget 傳入 `TestWrapper` 就行啦~
```dart=
class TestWrapper extends StatelessWidget {
const TestWrapper({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: Size(360, 690),
useInheritedMediaQuery: true,
builder: (_, __) {
return MaterialApp(
home: child,
);
},
);
}
}
```