Skip to content

Running the Tests

Petrus Pradella edited this page Jun 18, 2026 · 2 revisions

Running the Tests

What this page covers: how to run EveryDatabase's test suites — the embedded backends that need nothing, the SQL/Mongo integration suites that need real servers via Docker compose, the -PnoDocker / -PskipStress switches, the throwaway-database plumbing, and the :manager add-on tests.


The 60-second version

export JAVA_HOME=/path/to/jdk-25            # PowerShell: $env:JAVA_HOME = "C:\path\to\jdk-25"

./gradlew :core:test                        # everything (auto-starts the DB containers)

No Docker on the machine? The integration suites self-skip; the embedded ones still run:

./gradlew :core:test -PnoDocker -PskipStress    # embedded only (H2 / LocalFile / InMemory), fast

📌 Note — the build prerequisites (JDK 25 launcher, the JDK-17 production compile) are on Building from Source. This page is just the test mechanics.


The two tiers of suites

Tier Backends Needs a server?
Embedded H2, Local Files, In-Memory No — always run
Integration MySQL/MariaDB, PostgreSQL, MongoDB Yes — a real server (Docker)

The integration suites guard themselves with a JUnit assumeTrue in each @BeforeAll: when their server is unreachable they self-skip, so the build never fails just because a database is down.


Integration databases via Docker compose

The SQL/Mongo suites need real servers. docker-compose.yml starts all three on non-default high ports chosen to avoid clashing with any default-port databases already on your host — and these ports/credentials match the test defaults, so no configuration is needed.

Service Host port Credentials
MariaDB (MySQL-compatible) 39306 root / root
PostgreSQL 39307 root / root
MongoDB 39308 root / root
docker compose up -d            # start all three in the background
docker compose up -d mariadb    # or just one
docker compose ps               # status / healthcheck of each container
docker compose logs -f          # watch initialization
docker compose down             # stop (keeps volumes — data survives)
docker compose down -v          # stop + wipe volumes (destroys all data)

📌 Note — MariaDB is wire-compatible with MySQL: the mysql-connector-j driver connects to it normally, so the MariaDB container also covers real MySQL. There is no separate MySQL container.

:core:test brings the containers up for you

The Gradle com.avast.gradle.docker-compose plugin is wired so dockerCompose.isRequiredBy(test) — running :core:test starts the containers automatically and stops them when the build finishes. You don't have to docker compose up first. Useful properties:

./gradlew :core:test -Pdocker.stop        # stop + remove containers after the run
./gradlew :core:test -Pdocker.recreate    # force-recreate the containers
./gradlew :core:test -Pdocker.logs        # surface container logs

⚠️ Gotcha — to run embedded-only without Docker, use -PnoDocker. Do not reach for -x :core:composeUp: under Gradle 9 + docker-compose plugin 0.17.x the test task eagerly queries composeUp's providers, and excluding that task makes the build fail. -PnoDocker skips the wiring itself, which is the supported path.


The switches

./gradlew :core:test                                   # everything
./gradlew :core:test -PskipStress                      # skip the @Tag("stress") 10k-record suites
./gradlew :core:test -PnoDocker                        # no Docker — SQL/Mongo suites self-skip
./gradlew :core:test -PnoDocker -PskipStress           # fastest embedded-only run
./gradlew :core:test --tests "*MariaDbStorageTest"     # one class
./gradlew :core:test --tests "*MariaDbStorageTest.inTransaction_commit_savesAreVisible"   # one method
  • -PskipStress excludes the @Tag("stress") 10k-record suites (one concrete class per backend, e.g. H2StorageStressTest). They run by default; skipping them is much faster.
  • -PnoDocker skips the docker-compose wiring entirely — the SQL/Mongo suites self-skip, the embedded suites still run.

💡 Tip — set verbosity without touching code via the log-level system property: ./gradlew :core:test -Deverydatabase.log.level=info (or debug / trace). See Logging & Diagnostics.


Throwaway databases (and keeping them)

Each SQL/Mongo test method runs against its own freshly-created database, named enc_NNN_<backend>_<methodName>, then dropped in @AfterAll. So a failed run never leaves state that poisons the next one. All the probe/create/drop plumbing lives in one place — testutil/ThrowawayDatabaseSupport (factories mysql(...), postgres(...), mongo(...)); concrete suites declare a static DBS instance and delegate.

To keep the throwaway databases for inspection after a run:

TEST_KEEP_DATABASES=true ./gradlew :core:test --tests "*PostgreSqlStorageTest"
# PowerShell: $env:TEST_KEEP_DATABASES = "true"; .\gradlew :core:test --tests "*PostgreSqlStorageTest"

Overriding connection coordinates

Resolution order per setting is system property → env var → default (DotEnvTestUtil). Override any backend's host/port/credentials/URL without editing code:

./gradlew :core:test -DMARIADB_PORT=3306 -DMONGO_USER=admin
# or via env vars: MARIADB_HOST, MARIADB_PORT, MONGO_USER, POSTGRES_URL, ...

The :manager add-on tests

The refs/caching module (Caching & References) has its own suite:

./gradlew :manager:test

It runs on the embedded backends (InMemory / H2 / LocalFile), so it needs no Docker for the bulk of its coverage. The heterogeneous fan-out test MultiBackendRefExampleTest resolves one root across all six real backends when Docker is up and self-skips otherwise — an embedded-only variant always runs. Test entities live under the module's testdata (and testdata.multibackend) packages.


How the suites are organized (for when a test fails)

  • A small abstract hierarchy holds the backend-agnostic contract. AbstractStorageTest covers CRUD, codec round-trip, the index/query matrix, and a [base] log: block; AbstractTransactionalStorageTest adds the [tx] transactional/lifecycle/schema suite; AbstractVersionedStorageTest covers optimistic locking. Display names are prefixed [base] / [tx].
  • Each backend extends the right abstract suite, so a cross-backend behavior is exercised on every backend at once. Backend-specific quirks (H2's index-drop enforcement, Mongo's insert race) live in the concrete class.
  • Tests are @Ordered for readability but independent (clean storage per @BeforeEach).

💡 Tip--tests "*AbstractStorageTest*" won't match anything (it's abstract). Target the concrete subclass, e.g. --tests "*H2StorageTest", then narrow to a method with the Class.method form.


See also

Clone this wiki locally