Skip to content

E2E: Cover House Tables against a deployed MySQL - #698

Draft
ruolin59 wants to merge 1 commit into
rufan/views-hts-lifecyclefrom
rufan/hts-deployment-tests
Draft

E2E: Cover House Tables against a deployed MySQL#698
ruolin59 wants to merge 1 commit into
rufan/views-hts-lifecyclefrom
rufan/hts-deployment-tests

Conversation

@ruolin59

Copy link
Copy Markdown
Collaborator

Stacked on #697. Base is rufan/views-hts-lifecycle, so this diff is only the deployment-test work.

What this is

services/housetables tests the slice through MockMvc against H2. Three things only exist in a deployment and were therefore untested:

  • the JSON body a caller actually receives, not the ResponseEntity a handler returns
  • the exception advice, which has to survive Hibernate's persistence wrapping
  • entity_type as MySQL stores and compares it, not as H2's MySQL-compatibility mode does

23 tests, run over HTTP against a running service.

Two defects on #697 were found this way and are already fixed there: the unreachable CorruptEntityTypeException handler (fcf243ce) and the collation assumption in EntityType.fromName (a8aa8fd0). Neither was visible to the MockMvc suite — the first because the status was 500 by accident through the catch-all, so a status-only assertion passed while the handler was dead.

Please look hardest at these

1. CI switches recipe. .github/workflows/build-run-tests.yml moves from oh-only to oh-only-mysql. Every run now starts a MySQL container, and the existing integration_test.py runs against MySQL rather than H2. That is a change to an existing pipeline, not just an added step. oh-only itself is untouched, so the IN_MEMORY path keeps its coverage — but nothing in CI exercises it any more.

2. sleep 30 becomes a readiness poll. Justified — a MySQL start is slower and less predictable — but it changes the existing pipeline's timing behaviour and is not strictly required by the new tests.

3. The recipe mounts services/housetables/ddl as the MySQL init directory. Side effect: every run checks the recorded DDL is a working migration path, which nothing else does. But that directory came from BDP-108403, not this ticket, and its file convention is still under review there (it differs from scripts/housetables-migrations/ in li-openhouse). This couples CI to a layout that may yet change.

4. Scope. The original brief was a test script plus a CI step. It grew a compose recipe, a SETUP.md row and a dependency. Each is defensible on its own; the total is worth a deliberate yes or no.

Skips, not failures

Tests needing SQL — planting a legacy NULL discriminator, or a corrupt one, which no endpoint can write — skip when no database is reachable, and skips are reported separately from passes. Against the MySQL recipe: 23 passed, 0 skipped. With the database unreachable: 20 passed, 3 skipped.

The endpoint-agreement invariant

The most durable assertion here. For any key, /hts/entities and the matching typed read must agree on whether the row exists. It is collation-robust where per-row status assertions are not: under PAD SPACE a trailing-space discriminator compares equal to TABLE and both routes answer 200; under NO PAD they disagree and the assertion fails, naming the right bug.

It does not hold universally on this deployment, and the test does not pretend otherwise. A corrupt discriminator genuinely breaks it — the typed route's predicate misses the row while the neutral route has no predicate and hydrates it into the converter. That is asserted as an explicit known-bad disagreement, so a future fix fails loudly instead of leaving a stale assertion.

Not verified

The production collation for user_table_row.entity_type. Measurements here are against MySQL 8.4 utf8mb4_0900_ai_ci (NO PAD); ddl/0000__baseline.sql specifies none. Same open question as on #697.

That matters for anyone re-running this suite: several corrupt-value assertions are collation-dependent, and the 404-vs-500 split on a trailing-space discriminator inverts under PAD SPACE. Against a differently-collated MySQL those are environment failures, not regressions. The endpoint-agreement assertions hold either way.

@ruolin59 ruolin59 changed the title BDP-108627: Cover House Tables against a deployed MySQL E2E: Cover House Tables against a deployed MySQL Aug 27, 2026
The suite in services/housetables drives the slice through MockMvc on H2.
That leaves untested the parts which only exist in a deployment: the JSON
a caller actually receives, the exception advice that has to survive
persistence wrapping, and the discriminator column as MySQL stores it.

These tests drive the running service over HTTP. Where the REST API cannot
express the state under test they plant rows with SQL, since no endpoint
writes a legacy NULL discriminator or a corrupt one. Those tests skip when
no database is reachable rather than fail, so the suite still runs against
a deployment whose database is not exposed.

CI moves from the oh-only recipe to a MySQL-backed variant of it. That
costs one container per run and changes what the existing integration test
runs against. oh-only itself is untouched, so the IN_MEMORY path keeps its
coverage. The recipe mounts services/housetables/ddl as the database's
init directory, so every run also checks that the recorded DDL is a
working migration path, which nothing else does today.

The fixed sleep before the tests becomes a readiness poll, because MySQL
starts more slowly and less predictably than H2.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant