使用 coverage 套件收集覆蓋率並產生 LCOV 報告
實作 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 workspace(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 服務、隔離區暫停或分支/函式層級覆蓋率進行細粒度控制,請使用手動收集工作流程。
任務進度檢查清單:
- [ ] 1. 啟用 VM 服務執行測試。
- [ ] 2. 收集原始 JSON 覆蓋率。
- [ ] 3. 將 JSON 格式化為 LCOV。
1. 啟用 VM 服務執行測試
在退出時暫停隔離區,並在特定埠(例如 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
}
}






