Changelog
Changelog was reset.
Historical release notes were intentionally removed during documentation restructuring.
New entries should be created from this point forward.
2026
2026-10-09 v0.7.0
Engine.Seed names the table it inserts into from the type name, and that rule now pluralizes the
way table names are actually written, with an explicit name for the tables it cannot derive.
The derived table name changed for two shapes of type name:
- A name ending in
xis no longer suffixed:JobOutboxseedsjob_outbox, notjob_outboxs. - A consonant before the final
ytakesies:JobCategoryseedsjob_categories, notjob_categorys. A vowel before it still takess, soApiKeykeeps seedingapi_keys.
Every other name still takes a plain s.
- A seeded type with a
TableName() stringmethod inserts into the table it returns, so a table outside the plural rule (tenant_usage_monthly) can be seeded. A generated row gains the method through a defined type over it.
2026-08-29 v0.6.0
The test-database lifecycle is no longer MySQL-only. DBLifecycle became a public extension point
with MySQL, PostgreSQL and SQLite implementations in the box, and identifier quoting moved out of
fmt.Sprintf.
WithConnectionFactory lost its executeDbCreateStmt bool parameter. The flag selected between
MySQL DDL and doing nothing, which is what tied the library to one engine.
| |
DBLifecycleandDBLifecycleBuilderare exported, so a consumer can implement create/drop for an engine puppetest does not ship.WithDatabaseLifecycle(...)selects the lifecycle. Option order does not matter: it is built after every option has run, over the root connectionWithConnectionFactoryopened.MySQLLifecyclekeeps the previousCREATE/DROP DATABASE IF [NOT] EXISTSbehaviour with backtick quoting.PostgresLifecyclecheckspg_databaseinstead of theIF NOT EXISTSPostgreSQL does not have, treats SQLSTATE42P04as success, and terminates live backends before dropping so teardown does not fail intermittently. It works on servers older than 13, which lackDROP DATABASE ... WITH (FORCE).SQLiteLifecycle(pathFor)manages the database file and its-wal/-shmsidecars, since SQLite has noCREATE DATABASE.QuoteIdentifier(name, quote)escapes an identifier by doubling the quote rune, and rejects an empty name or one holding a null byte. Database names reach a lifecycle from the caller, so this replaces interpolating them straight into a statement.
Engine.Seed hardcoded ? bind markers, which are a syntax error on PostgreSQL. The style is now
pluggable and still defaults to ?.
WithPlaceholderStyle(...)on the engine factory, withQuestionPlaceholder(default) andOrdinalPlaceholder($1,$2) shipped.bancoche.NewMapQuery(...)takesbancoche.WithPlaceholderStyle(...), since it is built from a*sql.DBand never sees the engine.NewRawQueryis unchanged; that SQL belongs to the caller.- Markers are GENERATED, never rewritten, so no SQL is parsed and no string literal or comment can be corrupted by the substitution.
WithConnectionTimeout(d) replaces the hardcoded one-second budget, which covered dial, auth and
ping with no way to change it. The default is unchanged. The budget is shared by the
ConnectionPerformer and the ping, so it could not be extended from the call site.
NewDatabasedrops the database it just created when the follow-up connection fails, instead of stranding it on the server;ConnectionPerformer.Executecloses the connection when its ping fails; the engine factory’s lazy provider store no longer races under concurrent access.
puppetest still has no third-party dependencies. PostgresLifecycle reads the duplicate-database
SQLSTATE through an interface{ SQLState() string } rather than importing a driver.
That structural read is what makes concurrent creation of the same database name safe, so the
guarantee depends on the driver: pgx’s *pgconn.PgError satisfies it, lib/pq’s *pq.Error does
not. On lib/pq, two tests racing to create one database name are not protected and one fails.
Under go test -p N that is the main path rather than an edge case.
2026-03-02 v0.5.0
Baseline release snapshot for the current Testereiro library structure and docs reset.
- Engine + factory lifecycle for integration tests:
NewEngineFactory(...)EngineFactory.NewEngine(t)EngineFactory.Close()
- Hook lifecycle support:
- before/after engine create
- before engine seed
- before/after engine run
- before/after engine teardown
- before/after factory close
- Extension model:
WithConnectionFactory(...)WithExtensions(...)WithTestServer(...)WithTestServerFromEngine(...)WithMigrationRunner(...)
- Seeding support:
- SQL struct seeding via
Engine.Seed(...) - provider-driven seeding via
Engine.SeedWithProvider(...)
- SQL struct seeding via
- Provider storage API:
- engine providers via
SetProvider(...)/Provider(...) - factory providers via
RegisterFactoryProvider(...)/FactoryProvider(...)
- engine providers via
- Runner ecosystem:
- HTTP runner (
netoche) - SQL runner (
bancoche) - multi-runner composition (
atores.MultiRunner)
- HTTP runner (
providers/mongotestage- factory Mongo connection setup (
WithMongoConnection,WithMongoClient) - engine Mongo database binding and accessors (
DatabaseFromEngine,ClientFromFactory) - Mongo assertion runner (
pkg/mongochecker) - Mongo seeding provider (
pkg/mongoseeder)
- factory Mongo connection setup (
providers/siqeltestage- SQL object expectation validators for
bancoche - custom comparator and sanitizer support
- SQL object expectation validators for
examples/webapi: HTTP-only flow withnetocheexamples/sqlite: SQL + migrations + HTTP integration flowexamples/testcontainers_mysql: MySQL container + SQL assertions flowexamples/mongodb_assert: Mongo provider + seeder + checker flow