Skip to content

1.0.1-alpha

Choose a tag to compare

@snowfluke snowfluke released this 31 Aug 04:11
· 294 commits to main since this release
v1.0.1-alpha
ac1c3ca

Released 2026-08-31. Testate is a self-hosted tool for QA teams. It takes data-only snapshots of the databases behind a system under test, restores them on demand, diffs them, imports fixtures, and lets an AI agent read them. One container, one volume, on your own network. Overview at https://pt-perkasa-pilar-utama.github.io/testate/, full record in the changelog.

This is the first usable release. 1.0.0-alpha was published and cannot boot: docker-slim removed /data from the image, so the first run against an empty volume refused with TESTATE_DATA_DIR is not writable. Use this version instead.

Install

docker run -d --name testate -p 3000:3000 -v testate-data:/data \
  -e TESTATE_SECRETS_ACTIVE_KEY="$(openssl rand -base64 32)" \
  -e TESTATE_ADMIN_PASSWORD=change-me-now-1234 \
  ghcr.io/pt-perkasa-pilar-utama/testate:1.0.1-alpha

For a deployment you keep, use Compose and an .env file: How to install. To run from source instead, copy apps/api/.env.example to apps/api/.env and use bun run dev.

Quick start

Open http://localhost:3000 and sign in as admin with the password you set. Testate makes you change it on the first login.

The API answers as soon as the container is up:

$ curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/v1/health/live
204

$ curl -s -X POST http://localhost:3000/api/v1/auth/login \
    -H 'content-type: application/json' -H 'X-Testate-Request: 1' \
    -d '{"username":"admin","password":"change-me-now-1234"}'
{"data":{"user":{"id":"01a05603-8398-7668-975f-69b40b380d6a","username":"admin","display_name":"admin","role":"admin"},"must_change_password":true}}

Then add a database under Adapters, snapshot it under States, break something, and put it back under Checkouts. Where to point the adapter's host is the one thing that catches people out, so read Connecting to a database first.

What it does

  • Snapshots that hold data, not schema: one state covers every database in a project, and a checkout restores them and reports what happened per database.
  • Diffs you can read: compare two states, or a state against the live database. The dialog leads with the totals and hides the tables that did not move, so a change in one table out of two hundred is the first thing you see.
  • A grid that behaves like a database client: filter, sort, page by keyset, follow a foreign key into the next table. Write mode stashes the table before the first write.
  • Fixtures with a dry run: upload a CSV or XLSX, map the columns, dry-run it, then import. Rejected rows come back as a file you can fix and re-import.
  • Read-only agent access over MCP: point Claude or any MCP client at /api/v1/mcp with an agent token. It gets list_tables, describe_table, page_rows, run_readonly_query, extract_fixture and more, capped at 1000 rows and 15 seconds a query. There is no write tool, and column policies mask values before the agent sees them.
  • An agent that arrives knowing how to use it: the first tool in tools/list is help and the first resource is testate://guide, both serving the same document: how the pieces relate, the order to call things in, and the limits that refuse a call. Every tool carries its own description, so an agent reading the list knows what each one answers.
  • A REST API under every screen: POST /projects/{slug}/checkouts resets a database before a test run. The contract is served at /api/v1/openapi.json by a running instance.

Engines

Tier Engines What you get
Tabular PostgreSQL, MySQL, MariaDB view, snapshot, checkout, diff, extract, edit, import
Document MongoDB view, snapshot, checkout, diff, extract
Files S3, SFTP, FTP view, download
REST any HTTP API saved requests, hooks around checkouts

Every engine in that table is real. None is a stand-in, and each has a contract suite that runs against the actual server rather than a mock.

Known limits

Read What it does not do before you install this. The three that bite hardest:

  • Databases go one at a time: even inside one project, Testate snapshots and restores them in sequence. Each is correct alone, the set is not guaranteed to line up. Keep the app idle while it runs.
  • It only resets what you add: an untracked database survives a reset and Testate cannot warn you, because it has never heard of it.
  • Microservices are untested: every limit above compounds. Stay inside one service, and add the rest as read-only adapters.

It also ships a one-line patch to @solidjs/signals, because a stale transaction stamp made the scheduler spin forever on the data grid. The evidence is in patches/ and the same fix is upstream as solidjs/solid#3143. It goes away when a Solid release carries it.

Credits

Built on Bun, Hono (MIT), SolidJS (MIT), valibot (MIT), Cloudflare Kumo (MIT), ssh2 (MIT), basic-ftp (MIT), and the MongoDB Node driver (Apache-2.0). The interface follows GitHub's design language and uses Mona Sans (OFL-1.1). Images are slimmed with SlimToolkit.

Testate is MIT licensed.