實作 Dart 與 Flutter 測試覆蓋率
目錄
測試基礎
使用標準的 Dart 測試範例來建構您的測試套件。對於 Dart 專案,請使用 package:test;對於 Flutter 專案,請使用 flutter_test。
- 單元測試: 驗證個別函數、方法或類別。
- 元件/Widget 測試: 使用模擬物件 (
package:mockito) 驗證元件行為、佈局和互動。 - 整合測試: 在模擬或真實裝置上驗證整個應用程式流程。
覆蓋率指令
使用內聯註解將特定行、區塊或整個檔案排除在覆蓋率指標之外。在格式化時傳遞 --check-ignore 標誌以強制執行這些指令。
- 忽略單一行:
// coverage:ignore-line - 忽略程式碼區塊:
// coverage:ignore-start和// coverage:ignore-end - 忽略整個檔案:
// coverage:ignore-file
工作流程:配置與產生覆蓋率報告
請依序執行以下步驟,以新增 coverage 套件、執行測試並產生 LCOV 報告。
任務進度核對清單:
- 1. 將
coverage新增為dev_dependency。 - 2. 執行自動化覆蓋率指令碼。
- 3. 驗證 LCOV 輸出。
1. 新增依賴
將 coverage 套件新增為專案的 dev_dependency。請勿將其新增至標準依賴。
若為標準 Dart 專案:
dart pub add dev:coverage
若為 Flutter 專案:
flutter pub add dev:coverage
2. 收集覆蓋率並產生 LCOV
使用內建的 test_with_coverage 指令碼。此指令碼會自動執行所有測試、從 Dart VM 收集 JSON 格式的覆蓋率資料,並將其格式化為 LCOV 報告。
dart run coverage:test_with_coverage
注意:如果是在 Dart 工作區(monorepo)中運作,請明確指定測試目錄(例如 dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test)。
3. 回饋迴圈:驗證輸出
執行驗證器 -> 檢閱錯誤 -> 修正:
- 確認
coverage/目錄已在專案根目錄中建立。 - 確認
coverage/coverage.json(原始資料)和coverage/lcov.info(格式化報告)已存在。 - 如果特定檔案的覆蓋率遺失,請確認它們已由測試檔案匯入並執行,或者如果故意排除,請新增
// coverage:ignore-file。
工作流程:進階手動覆蓋率收集
如果您需要對 VM 服務、isolate 暫停或分支/函數層級覆蓋率進行精細控制,請使用手動收集工作流程。
任務進度核對清單:
- 1. 啟用 VM 服務執行測試。
- 2. 收集原始 JSON 覆蓋率。
- 3. 將 JSON 格式化為 LCOV。
1. 啟用 VM 服務執行測試
在退出時暫停 isolates 並在特定連接埠(例如 8181)上公開 VM 服務來執行測試。
dart run --pause-isolates-on-exit --disable-service-auth-codes --enable-vm-service=8181 test &
2. 收集原始覆蓋率
從執行中的 VM 服務提取覆蓋率資料,並輸出至 JSON 檔案。
dart run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:8181/ -o coverage/coverage.json --resume-isolates
可選:附加 --function-coverage 和 --branch-coverage 以收集更深入的指標(需要 Dart VM 2.17.0+)。
3. 格式化為 LCOV
將原始 JSON 資料轉換為標準的 LCOV 格式。
dart run coverage:format_coverage --packages=.dart_tool/package_config.json --lcov -i coverage/coverage.json -o coverage/lcov.info --check-ignore
範例
範例:pubspec.yaml 配置
確保您的 pubspec.yaml 將 coverage 套件嚴格置於 dev_dependencies 底下。
name: my_dart_app
environment:
sdk: ^3.0.0
dependencies:
path: ^1.8.0
dev_dependencies:
test: ^1.24.0
coverage: ^1.15.0
範例:套用忽略指令
使用忽略指令來防止產生的程式碼或無法測試的邊緣情況降低覆蓋率分數。
// coverage:ignore-file
import 'package:meta/meta.dart';
class SystemConfig {
final String env;
SystemConfig(this.env);
// coverage:ignore-start
void legacyInit() {
print('已廢棄的初始化');
}
// coverage:ignore-end
bool isProduction() {
if (env == 'prod') return true;
return false; // coverage:ignore-line
}
}