Java.DBMigrationTools.How do you run migrations for test environments?

services:
  db: { image: postgres:16, environment: [POSTGRES_DB=app, POSTGRES_PASSWORD=pass] }
  migrate:
    image: liquibase/liquibase
    depends_on: [db]
    command: ["update", "--url=jdbc:postgresql://db:5432/app", "--changelog-file=/changelog.xml"]
  app:
    image: my-app
    depends_on: [migrate]

Testcontainers for integration tests (Java):

@Testcontainers
class RepoIT {
  @Container
  static PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:16");

  @DynamicPropertySource
  static void dbProps(DynamicPropertyRegistry r) {
    r.add("spring.datasource.url", pg::getJdbcUrl);
    r.add("spring.datasource.username", pg::getUsername);
    r.add("spring.datasource.password", pg::getPassword);
    r.add("spring.flyway.enabled", () -> true);      // Flyway runs against the container
    r.add("spring.jpa.hibernate.ddl-auto", () -> "none");
  }
}

2) CI: run migrations as a pipeline step

Typical PR check pipeline

  1. Start DB service (Compose service or CI “services”).
  2. Run migrations (Flyway/Liquibase CLI or Maven/Gradle plugin).
  3. Run tests (unit + integration).
  4. Optionally validate schema drift.

GitHub Actions sketch





services:
  postgres:
    image: postgres:16
    env: { POSTGRES_DB: app, POSTGRES_PASSWORD: pass }
    ports: ["5432:5432"]
steps:
  - uses: actions/checkout@v4
  - name: Wait for DB
    run: until pg_isready -h localhost -p 5432; do sleep 1; done
  - name: Run Flyway
    run: ./mvnw -q -Dflyway.url=jdbc:postgresql://localhost:5432/app \
                -Dflyway.user=postgres -Dflyway.password=pass flyway:migrate
  - name: Tests
    run: ./mvnw -q test

3) Integration & E2E environments: treat like prod, but disposable

  • Dedicated DB per environment (e.g., app_test, app_e2e).
  • One-off “migrate” job before deploying the test app.
  • Seed data via separate changelog folder (e.g., db/seed/) or fixtures loaded by the test harness. Keep seeds idempotent.

4) Reset strategies between test runs

  • Flyway/Liquibase clean + migrate for quick wipe.
  • Ephemeral DB: Testcontainers or throwaway schema name per run (e.g., schema_pr123_abcdef).
  • Snapshot/restore: initialize once, take a DB snapshot, restore per suite for speed (useful for heavy datasets).

5) Versioning and safety knobs

  • Expand/Contract in tests too:
    • Verify “expand” migrations allow old + new code to run.
    • Run backfills as separate jobs you can test independently.
  • Flyway
    • validateOnMigrate=true to catch drift.
    • Use repair only to fix checksums on test DBs (never as a habit).
  • Liquibase
    • liquibase updateSQL for dry-run SQL review in CI.
    • diff/diffChangeLog to detect drift vs desired schema.

6) Seeding test data (cleanly)

  • Prefer readable, isolated seeds:
    • minimal “happy-path” records for integration tests,
    • richer fixtures for E2E.
  • Keep seeds separate from schema migrations (different path or tag) so prod doesn’t get test data.

7) Parallelism & race conditions

  • If your tests run in parallel against one DB, you’ll fight locks and state leakage.
  • Prefer one DB per test worker (Testcontainers, unique schema per worker, or a matrix of ports/DB names).
  • Ensure only one migration runner acts on a given database at a time (lock via tool’s built-in table or by isolating per-worker DB).

8) Tooling quick refs

  • Flyway (Maven):
<plugin>
  <groupId>org.flywaydb</groupId><artifactId>flyway-maven-plugin</artifactId>
  <version>${flyway.version}</version>
  <configuration>
    <url>${flyway.url}</url>
    <user>${flyway.user}</user>
    <password>${flyway.password}</password>
    <validateOnMigrate>true</validateOnMigrate>
  </configuration>
</plugin>

Run: mvn -q flyway:clean flyway:migrate -Ptest

Liquibase (Gradle)

liquibase {
  activities.register("testMigrate") {
    this.arguments = mapOf(
      "changelogFile" to "db/changelog-master.yaml",
      "url" to System.getenv("TEST_DB_URL"),
      "username" to "postgres",
      "password" to "pass"
    )
  }
}
  • Run: ./gradlew update -PliquibaseActivity=testMigrate

9) Suggested setups by environment

  • Unit tests: no DB or use lightweight embedded (no migrations).
  • Integration tests: Testcontainers + Flyway auto-migrate.
  • Local manual testing: docker compose up db migrate app; rerun migrate or clean+migrate as needed.
  • CI per PR: spin DB service → migrate → run tests; optionally run a dry-run (Liquibase updateSQL) and schema-drift check.
  • Shared E2E env: pre-deploy “migrate” job; nightly refresh with snapshot.
This entry was posted in Без рубрики. Bookmark the permalink.