昨天透過單元測試為App的各個獨立零件(Provider、Repository)建立了品質防線,確保了引擎可以發動、輪胎可以滾動。但如果把這些零件組裝起來,這台車真的能在路上順暢行駛嗎?這是今天要來確認的問題。
整合測試(Integration Test):是一種更高層次的測試,不再是測試單一的類別或函式,而是模擬真實使用者的操作,驗證從UI互動到後端邏輯、再到狀態更新的整個流程是否暢通無阻。目標是撰寫一個自動化腳本,來執行一個完整的核心使用者流程 。
一、整合測試 vs. 單元測試
動手前,先釐清整合測試與單元測試的關鍵區別:
如果說單元測試是保證每個零件都合格,那麼整合測試就是確保整條生產線能順利產出最終產品。
二、設定整合測試環境
Flutter官方提供了強大的integration_test套件來幫助我們完成這項任務。
Step1. 加入依賴:在pubspec.yaml的dev_dependencies中加入integration_test。
Step2. 建立測試檔案:在專案根目錄下建立一個integration_test資料夾,並在其中建立我們的測試檔案,例如app_flow_test.dart。
Stpe3. 初始化綁定:在測試檔案的main函式中,必須呼叫IntegrationTestWidgetsFlutterBinding.ensureInitialized(); 來設定好測試環境。
三、實戰:撰寫端到端使用者流程測試
目標是自動化執行以下這個最關鍵的使用者流程:
**啟動App → 滑動卡片 → 收藏卡片 → 錄製語音筆記 → 在收藏頁查看結果 **
我們將使用flutter_test提供的testWidgets和WidgetTester來達成。
測試腳本breakdown:
Step1. 啟動App並等待載入
testWidgets('Full user flow integration test', (WidgetTester tester) async {
// 啟動 App
await tester.pumpWidget(const MyApp());
// 等待所有動畫和非同步操作(如 API 請求)完成
await tester.pumpAndSettle();
});
Step2. 模擬滑動與收藏
// 找到第一張卡片
final firstCard = find.byType(InspirationCard).first;
expect(firstCard, findsOneWidget);
// 模擬向右滑動(保留)
await tester.drag(firstCard, const Offset(500.0, 0.0));
await tester.pumpAndSettle();
// 找到收藏按鈕並點擊
final favoriteButton = find.byIcon(Icons.favorite_border);
expect(favoriteButton, findsOneWidget);
await tester.tap(favoriteButton);
await tester.pumpAndSettle(); // 等待狀態更新
Step3. 模擬新增筆記
在這個環節,無法真的對著測試裝置說話,但可以模擬UI操作的流程。
// 點擊筆記圖示展開輸入區
await tester.tap(find.byIcon(Icons.notes));
await tester.pumpAndSettle();
// 找到文字輸入框,並輸入文字來模擬語音轉文字的結果
final noteTextField = find.byType(TextField);
expect(noteTextField, findsOneWidget);
await tester.enterText(noteTextField, '這是一則整合測試筆記');
// 點擊儲存按鈕
await tester.tap(find.text('儲存'));
await tester.pumpAndSettle();
Step4. 導航至收藏頁並驗證結果
這是最後,也是最關鍵的一步:驗證前面的所有操作是否都正確地反映在最終結果上。
// 點擊導航欄的「收藏」分頁
await tester.tap(find.byIcon(Icons.collections_bookmark));
await tester.pumpAndSettle(); // 等待頁面轉換
// 驗證收藏頁面中,是否出現了我們收藏的卡片
// 這裡可以透過卡片的標題或摘要來尋找
expect(find.text('...卡片的摘要...'), findsOneWidget);
// 驗證我們剛剛新增的筆記是否也顯示出來了
expect(find.text('這是一則整合測試筆記'), findsOneWidget);
今天,為App建立了一道自動化防線。整合測試就像一個不知疲倦的機器人,在每次我們修改程式碼後,都會為我們完整地跑一遍核心流程,確保App的主動脈暢通無阻。
有了單元測試和整合測試的雙重守護,終於可以放心地進行下一步了。明天準備為App設計一個專業的門面:App Icon與啟動畫面。
【哈囉你好:)感謝你的閱讀!其他我會常出沒的地方:Threads】