ci: measure test coverage and upload as artifact#323
Merged
Conversation
flutter test now runs with --coverage. The generated coverage/lcov.info is filtered to remove generated code (lib/generated/**) and the main entrypoint, then uploaded as an artifact so coverage can be inspected without re-running the suite locally. No threshold enforcement yet — see the README 'Coverage infrastructure roadmap'. This step only produces a baseline measurement; the gate that fails the build below 100% lands in a follow-up.
4 tasks
TaprootFreak
added a commit
that referenced
this pull request
May 15, 2026
) ## Summary Adds 38 unit tests across six previously-untested files in `lib/packages/utils/` and `lib/packages/wallet/`. Each spec lives in the mirror path under `test/` per the project convention. | File under test | Test file | Cases | | --- | --- | --- | | `lib/packages/utils/fast_hash.dart` | `test/packages/utils/fast_hash_test.dart` | 5 | | `lib/packages/utils/jwt_decoder.dart` | `test/packages/utils/jwt_decoder_test.dart` | 7 | | `lib/packages/wallet/payment_uri.dart` | `test/packages/wallet/payment_uri_test.dart` | 4 | | `lib/packages/wallet/wallet_account.dart` | `test/packages/wallet/wallet_account_test.dart` | 7 | | `lib/packages/wallet/wallet.dart` | `test/packages/wallet/wallet_test.dart` | 11 | | `lib/packages/wallet/eip7702_signer.dart` | `test/packages/wallet/eip7702_signer_test.dart` | 4 | ## What each file covers - **fast_hash:** FNV-1a determinism, distinct inputs differ, ordering matters, unicode safety, empty-string offset basis. - **jwt_decoder:** well-formed payload parsing, segment-count errors, non-map payload rejection, all three valid base64url padding lengths, illegal length-mod-4 rejection. - **payment_uri:** empty-amount short form, dotted and comma-locale amounts, preservation of decimal precision. - **wallet_account:** BIP-44 derivation path format, deterministic Hardhat account #0 address from the standard test mnemonic, distinct indices, signMessage shape + determinism + sensitivity to addressIndex. - **wallet:** `SoftwareWallet` walletType + primary/current account identity + `selectAccount` semantics + id/name mutability; `DebugWallet` sign refusal. - **eip7702_signer:** hardware-credential refusal (BitBox cannot sign EIP-7702), software-credential signing, signature determinism, nonce-sensitivity. ## Why Stage 2 of the coverage push tracked in the README features matrix ([#322](#322)). These six files are pure-Dart with no platform dependencies, so they were the cheapest meaningful coverage win available — no service mocks, no widget rendering, no merge-conflict risk with the three in-flight test PRs ([#319](#319), [#320](#320), [#321](#321)). ## Test plan - [x] `flutter analyze` clean on all six new test files (locally on Flutter 3.38.5) - [x] `flutter test test/packages/utils/ test/packages/wallet/` — 38 / 38 passing - [ ] CI green on this branch - [ ] Spot-check: coverage artifact from #323 (once that lands) shows non-zero coverage on the six files above
TaprootFreak
added a commit
that referenced
this pull request
May 23, 2026
- fake_async example: add bitbox_flutter.dart import and inline the pairedServiceSync idiom so the snippet is copy-paste compilable - platform-coupled section: real-plugin counterpart is Tier 2/3, not Tier 1/2 (Tier 1 is FakeBitboxCredentials by definition); add the CONTRIBUTING.md footnote-165 caveat that the annotation is the documenting form today - README: PRs #319/#320/#321/#322/#323 are all merged since 2026-05-15; replace "in flight"/"landing in"/"extended in" with "added via" / "have closed" / "partially covered after"
1 task
TaprootFreak
added a commit
that referenced
this pull request
May 25, 2026
## Summary Audited every claim in `docs/testing.md` against the current repo state. Two stale entries fixed; everything else verified accurate and left untouched. ## Findings & fixes ### Tier-table (L5-11) - **Status:** accurate. 5 tiers, Tier 0/1 CI both shown as green (`flutter test --coverage`) — matches `.github/workflows/pull-request.yaml` reality. ### Tier 3 coverage-artifact claim (L369) - **Before:** "Coverage is uploaded as an artifact (see #323)" under the `tier3-handbook.yaml` sentence. - **Finding:** `tier3-handbook.yaml` only uploads the `handbook-captures` artifact (per-flow diagnostic recordings). The coverage artifacts (`coverage-lcov`, `coverage-summary`) come from the `Analyze & Test` job in `pull-request.yaml`, not from Tier 3. PR [#323](#323) was about Tier 0/1 coverage upload. - **Fix:** Reworded the paragraph to correctly attribute artifact provenance and surface the floor protocol (`.coverage-floor-lines = 100`, `.coverage-floor-functions = 50`). ### Surface-needs-infra table (L375-378 in new layout) **Drift wrappers row (was L377)** — removed. - **Before:** "wrapper specs are not written yet" - **Finding:** All 5 Drift-backed repos (asset, balance, cache, transaction, wallet) have tests under `test/packages/repository/` that already use `AppDatabase.forTesting(NativeDatabase.memory())` — exactly the pattern the row prescribed. Even the 3 non-Drift repos (settings, supported_fiat, supported_language) have specs. - **Path correction:** doc said `database.dart`, actual path is `lib/packages/storage/database.dart`. - **Fix:** Row deleted; replaced with a short resolution note + correct path + test-file pointer. **Page-widgets `getIt<X>()` row (was L378)** — kept as-is. - **Finding:** Still valid. `lib/screens/dashboard/dashboard_page.dart`, `lib/screens/receive/receive_page.dart`, `lib/screens/settings/settings_page.dart` still call `getIt<X>()` directly in `build` / `BlocProvider.create`. Many sub-pages do as well. **`chain_asset_icon` / `image_picker_sheet` row (was L379)** — kept as-is. - **Finding:** Both files still exist under `lib/widgets/`. No tests for either. The recent `precacheImages` fix in [#575](#575) only affects golden tests (visual regression), not unit tests for these widgets. ### Sumsub paragraph (L381 / L382 in new layout) - **Status:** accurate. `lib/screens/kyc/steps/ident/cubits/kyc_ident/sumsub_ident_port.dart` (interface), `lib/screens/kyc/steps/ident/sumsub_ident_sdk_adapter.dart` (adapter, outside cubit folder), `@no-integration-test` annotation present, test file at the claimed path. ### DocumentsDirectoryPort paragraph (L383 / L384 in new layout) - **Status:** accurate. `lib/packages/io/documents_directory_port.dart` + `lib/packages/io/path_provider_adapter.dart` exist with the documented `coverage:ignore` + `@no-integration-test` annotations. `AppDatabase.getDatabasePath()` accepts a `DocumentsDirectoryPort` arg as claimed. ### Adding tests for BitBox-related code (L388-) - **Status:** accurate. All five referenced classes resolve in `lib/`. `enum FakeBitboxBehavior` exists in `test/helper/fake_bitbox_credentials.dart` with the documented variants. ### README coverage sections - **Status:** accurate. The 100% rule is correctly framed as the target, the floor protocol matches `.coverage-floor-lines = 100` / `.coverage-floor-functions = 50` reality. ## Verification - `flutter analyze test/` — 110 pre-existing issues (same as baseline before the edits; all `generated/i18n.dart` related). No regression introduced by docs edits. - Every referenced file/symbol verified with `grep` / `find` against the current `develop` HEAD. ## Test plan - [ ] Reviewer spot-checks the two changed paragraphs against the workflow files / test directory.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
flutter test --coverageto the existing PR workflow and uploads the (filtered)lcov.infoas a CI artifact.flutter test --coveragereplaces the plainflutter testinvocationcoverage/lcov.infois filtered withlcov --removeto drop generated files (lib/generated/**) andlib/main.dartso the artifact reflects only the activated surfacecoverage-lcovon every run (if: always())lcov --summaryprints to the CI log so contributors can eyeball the line/function/branch numbers without downloading the artifactWhy
Step 1 of the coverage infrastructure roadmap documented in PR #322. Without measurement, the 100% rule is unverifiable; with measurement but no threshold, this PR is safe to merge today and lays the foundation for the threshold gate in a follow-up.
What this PR is not
test/.Test plan
coverage-lcovartifact is present on the PR's checks pagelcov --summaryline of the CI log shows non-zero coverage onlib/packages/**lib/generated/**