使用 coverage 套件收集測試涵蓋率並產生 LCOV 報告
實作 Dart 與 Flutter 測試涵蓋率
目錄
測試基本概念
使用標準的 Dart 測試典範來建構您的測試套件。Dart 專案請使用 package:test,Flutter 專案則使用 flutter_test。
- 單元測試(Unit Tests): 驗證獨立的函式、方法或類別。
- 元件/Widget 測試(Component/Widget Tests): 使用 Mock 物件(
package:mockito)驗證元件行為、版面配置與互動。 - 整合測試(Integration Tests): 在模擬器或實體裝置上驗證完整的應用程式流程。
涵蓋率指示標籤
使用單行註解在涵蓋率統計中排除特定程式碼行、區塊或整個檔案。在格式化過程中傳入 --check-ignore 旗標即可套用這些指示標籤。
- 忽略單一行:
// coverage:ignore-line - 忽略程式碼區塊:
// coverage:ignore-start與// coverage:ignore-end - 忽略整個檔案:
// coverage:ignore-file
工作流程:設定與產生涵蓋率報告
請依照以下步驟新增 coverage 套件、執行測試並產生 LCOV 報告。
任務進度檢查清單:
- [ ] 1. 將
coverage新增至dev_dependencies。 - [ ] 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,或需要分支(Branch)/函式(Function)層級的涵蓋率,請使用手動收集工作流程。
任務進度檢查清單:
- [ ] 1. 在啟用 VM 服務的情況下執行測試。
- [ ] 2. 收集原始 JSON 涵蓋率資料。
- [ ] 3. 將 JSON 格式化為 LCOV。
1. 在啟用 VM 服務的情況下執行測試
執行測試時在結束時暫停 Isolate,並將 VM 服務暴露於特定通訊埠(例如:8181)。
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
範例:套用忽略指示標籤
使用忽略指示標籤,避免自動產生的程式碼或無法測試的邊角情況(Edge Cases)拉低涵蓋率分數。
// coverage:ignore-file
import 'package:meta/meta.dart';
class SystemConfig {
final String env;
SystemConfig(this.env);
// coverage:ignore-start
void legacyInit() {
print('Deprecated initialization');
}
// coverage:ignore-end
bool isProduction() {
if (env == 'prod') return true;
return false; // coverage:ignore-line
}
}






