# 使用 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, ); }, ); } } ```