Skip to content

test: expand BigQuery export coverage from 29.89% to 100% - #1223

Merged
groupthinking merged 1 commit into
mainfrom
groupthinking-bigquery-export-coverage
Aug 29, 2026
Merged

test: expand BigQuery export coverage from 29.89% to 100%#1223
groupthinking merged 1 commit into
mainfrom
groupthinking-bigquery-export-coverage

Conversation

@groupthinking

Copy link
Copy Markdown
Owner

Canonical issue

Closes #909

src/uvai/ml/bigquery_export.py had a single test covering 29.89% of the module. Both transports (BigQuery client and REST fallback), all four export_* entry points, and every failure path were unverified.

Outcome

Replaced the 1-test file with 42 tests. Statement coverage of src/uvai/ml/bigquery_export.py goes 29.89% -> 100% (61 previously-missed statements now covered, 0 missed).

Class Tests Covers
TestGetBqClient 3 ImportError -> None; construction raises -> None; success passes project=PROJECT_ID
TestInsertRows 6 no client -> False; success -> True; fully-qualified table_ref; backend row errors -> False; exception -> False; empty-list behaviour
TestInsertViaRest 8 missing/empty token -> False; success -> True; insertErrors -> False; network error -> False; metadata-server URL and header; bearer auth + insertAll URL; unique insertId per row
TestExportTranscriptOutcome 6 skips REST on success; falls back on failure; both fail -> False; field serialization; absent metadata -> None; falsy 0.0/False preserved
TestExportActionFeedback 2 field serialization; REST fallback
TestExportModelCheckpoint 2 nested dicts JSON-encoded; documented defaults
TestExportPipelineRun 3 stage list -> JSON; omitted list -> []; failure details recorded
TestExporterContract 12 3 shared invariants x 4 exporters, parametrized

The suite also fixes a pre-existing order-dependent failure. The old test poisoned sys.modules["google.cloud.bigquery"], but from google.cloud import bigquery resolves via getattr on an already-imported parent package, so a mocked google.cloud left behind by another test bypassed the poison entirely. It passed in isolation (vacuously - google is not installed) and failed in a full-suite run. The replacement denies the import at __import__ level, which is order-independent.

No production code is modified. All public signatures are unchanged, as the issue requires.

Risk

  • Risk level: low
  • Test-only change; src/uvai/ml/bigquery_export.py is untouched (git status clean for that path after every mutation run).
  • Every Google Cloud, network, and metadata-server boundary is mocked, so the suite never reaches an external service and runs offline in 0.06s.
  • The one behavioural claim about existing code - that the old test was already failing in full-suite runs - is demonstrated below rather than asserted.

Verification

Run on branch groupthinking-bigquery-export-coverage, branched from origin/main at b664e9227 per the issue's "start from current main" criterion.

$ .venv/bin/python -m pytest tests/unit/test_bigquery_export.py
42 passed in 0.06s

$ .venv/bin/python -m pytest tests/unit/test_bigquery_export.py --cov=uvai.ml.bigquery_export
src/uvai/ml/bigquery_export.py      87      0  100.0000%

$ .venv/bin/python -m ruff check tests/unit/test_bigquery_export.py
All checks passed!

$ .venv/bin/python -m black --check tests/unit/test_bigquery_export.py
1 file would be left unchanged.

Coverage baseline captured by stashing the new file and re-running:

before:  87 stmts   61 missed   29.8851%
after:   87 stmts    0 missed  100.0000%

Full tests/unit run, mine vs. baseline (same command, same machine):

with change:  133 failed, 6062 passed, 41 errors
baseline:     134 failed, 6020 passed, 41 errors

Passed count rises by exactly 42 (my tests) and failures drop by exactly 1 - the pre-existing test_get_bq_client_import_error. All other counts are identical, confirming nothing else is affected. The remaining 133 failures and 41 errors are pre-existing and unrelated (collection errors reproduce identically at 36 with and without this change).

Production evidence

1. The tests detect regressions. Passing tests are not the same as detecting tests, so each assertion was verified by mutating the source and confirming a failure. 10/10 mutations caught, source verified restored after each:

# Mutation Caught
1 Drop the bearer prefix from the auth header yes
2 Wrong metadata-server header key yes
3 Remove the REST fallback from export_pipeline_run yes
4 Constant insertId instead of per-row unique yes
5 Ignore insertErrors in the REST response yes
6 Wrong metadata-flavor header value yes
7 Wrong export_model_checkpoint default yes
8 Naive (non-UTC) exported_at timestamp yes
9 Write outcomes to the wrong table yes
10 Rebuild the row on fallback instead of reusing it yes

2. The order-dependence fix is demonstrated, not asserted. A temporary harness reproduced the exact pollution condition (a mocked google.cloud in sys.modules), then was removed:

old approach + pollution:  1 failed
new approach + pollution:  43 passed

And on unmodified origin/main, the pre-existing test is confirmed already failing in a full-suite run:

$ git stash push tests/unit/test_bigquery_export.py
$ .venv/bin/python -m pytest tests/unit/ --continue-on-collection-errors
FAILED tests/unit/test_bigquery_export.py::test_get_bq_client_import_error

3. The replacement test is not vacuous. Because google is not installed in this environment, an import-denial test can pass without exercising anything. Mutating the ImportError branch to return a truthy sentinel fails the test, proving the branch is genuinely reached:

mutated: ImportError branch returns truthy sentinel
FAILED tests/unit/test_bigquery_export.py::TestGetBqClient::test_returns_none_when_bigquery_not_installed

A behaviour-preserving mutation (except ImportError -> except ZeroDivisionError) is correctly not flagged, since the generic except Exception handler still returns None - the tests assert on contract, not on incidental structure.

`tests/unit/test_bigquery_export.py` held a single test that covered
29.89% of `src/uvai/ml/bigquery_export.py`, leaving both transports, all
four exporters, and every failure path unverified.

Replace it with 42 tests covering `_get_bq_client`, `_insert_rows`,
`_insert_via_rest`, and the four `export_*` entry points, including the
REST fallback contract shared by all exporters. Statement coverage of the
module goes from 29.89% to 100% (61 previously-missed statements).

The pre-existing test was also order-dependent and already failing in a
full-suite run: it poisoned `sys.modules["google.cloud.bigquery"]`, but
`from google.cloud import bigquery` resolves via `getattr` on an
already-imported parent package, so a mocked `google.cloud` left behind by
another test bypassed the poison. Denying the import at `__import__` level
makes it deterministic. Full `tests/unit` failures drop 134 -> 133 as a
result.

No production code is modified; all public signatures are unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 2, 2026 13:16
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v0-uvai Ready Ready Preview, v0 Aug 2, 2026 1:17pm

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🔍 PR Validation

⚠️ Large PR detected (552 lines changed)

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • [‘architecture-gap’, ‘bug’, ‘ci-cd’, ‘ci/cd’, ‘copilot-rabbit’, ‘documentation’, ‘duplicate’, ‘enhancement’, ‘frontend’, ‘github_actions’, ‘good first issue’, ‘help wanted’, ‘high-priority’, ‘invalid’, ‘javascript’, ‘ml-model’, ‘needs-triage’, ‘pipeline-critical’, ‘placeholder-code’, ‘priority:high’, ‘python’, ‘python:uv’, ‘question’, ‘styling’, ‘tests’, ‘v0’]

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a56ce6ed-7008-4157-acfa-103222b3e556

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the python label Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 738cee3.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Agent Completion Truth Gate: BLOCKED

Reasons: invalid_payload

Machine-readable verdict
{
  "details": {
    "collection_errors": [
      "incomplete_linked_issue_contract",
      "missing_intent_snapshot",
      "missing_agent_run_id",
      "missing_agent_login"
    ],
    "invalid_fields": [
      "policy.agent_login",
      "policy.run_id"
    ]
  },
  "reasons": [
    "invalid_payload"
  ],
  "verdict": "blocked"
}

Workflow evidence

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Expands deterministic, offline unit coverage for BigQuery exports, closing #909 without production changes.

Changes:

  • Adds 42 tests covering both transports and four exporters.
  • Covers serialization, fallback behavior, failures, and import-order isolation.
  • Uses the approved test video ID and mocks external boundaries.

@groupthinking groupthinking left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review-requested triage — blocked on one non-code gate

Functional CI is fully green. test, build, lint-python, lint-frontend, trivy, bandit, CodeQL, both security scans, dependency-review, and Generate and Upload Coverage all pass. Copilot's review is a positive overview with no change requests; CodeRabbit auto-review was skipped by label config (not a failure).

The sole red is agent-completion/truth-gate, and it is a provenance gate rather than a code check. Its machine-readable verdict is:

{"verdict":"blocked","reasons":["invalid_payload"],
 "details":{"invalid_fields":["policy.agent_login","policy.run_id"]}}

i.e. the completion payload reached the gate with empty/invalid agent_login and run_id. This is unrelated to the diff — the change is test-only and src/uvai/ml/bigquery_export.py is untouched.

Why this isn't auto-resolved here. The missing fields are the originating run's agent identity and run id. A downstream reviewer cannot legitimately populate them — supplying fabricated provenance is exactly what this "truth gate" exists to prevent — so I will not push a payload to force it green. The gate's applicability/payload wiring is the subject of in-flight PRs #1123 (explicit noop terminal state) and #1154 (scope gate applicability to real dispatch evidence).

Unblock path (needs the maintainer / originating automation):

  1. Re-run the agent-completion workflow so it emits a payload with populated policy.agent_login and policy.run_id; or
  2. Given all functional checks are green and the change is test-only, a maintainer merges past the provenance gate.

Terminal state: HALTED(truth_gate_invalid_payload). Not merging — main is protected and merge approval is a human decision.


Generated by Claude Code

@groupthinking
groupthinking marked this pull request as draft August 2, 2026 13:22

Copy link
Copy Markdown
Owner Author

Returned to draft during delivery control. The test-only change is linked to #909, but no current execution receipt or independent exact-head completion evidence has been reconciled. Preserve the branch and checks; do not advance until that evidence is bound.

@groupthinking

Copy link
Copy Markdown
Owner Author

Note on the red agent-completion/truth-gate check

This failure is not caused by anything in this PR's diff. It is the pre-existing defect tracked in #1130.

The linked issue carries a label that agentTaskApplicable() treats as an agent-contract marker, which arms the completion gate transitively through the issue. The issue declares no Agent run id / Agent login headings, so the gate resolves policy.agent_login and policy.run_id to null and returns invalid_payload. No change on the PR side can satisfy it.

Evidence, including a label model that predicts the gate outcome for 6/6 issues and a survey showing 10 of 30 open PRs affected across three authors, is in #1130 (comment).

I deliberately did not work around it: doing so would mean self-issuing a dispatch record for a dispatch that never happened, which trusted-publishers.json explicitly says should block rather than downgrade.

Every other check on this PR passes.

@groupthinking groupthinking self-assigned this Aug 13, 2026
@groupthinking
groupthinking marked this pull request as ready for review August 29, 2026 06:00
@groupthinking
groupthinking merged commit a130ead into main Aug 29, 2026
43 of 46 checks passed
@groupthinking
groupthinking deleted the groupthinking-bigquery-export-coverage branch August 29, 2026 06:31
@linear-code

linear-code Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

GRV-440

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Backlog: add focused BigQuery export coverage on current main

2 participants