--- title: Testing plugins description: Test plugins with go test, run database tests against real PostgreSQL containers, replay API parity fixtures and keep documentation examples running. section: plugins order: 40 --- # Testing plugins SummerCMS uses the standard Go test tooling. There is no separate test runner and no PHPUnit bootstrap: a plugin's tests are `_test.go` files next to its code, and `go test` runs them. ## Running tests Run every test in the module from its root: ```sh go vet ./... go test ./... ``` Tests that need Docker, such as database tests, skip themselves in short mode. Use it for a fast loop: ```sh go test -short ./... ``` In an application with local plugins in a `go.work` workspace, run the tests of one plugin by its directory, for example `go test ./plugins/blog/...`. ## Unit tests without a database Most plugin code runs without a database. Build a container with `backpack.New`, call your plugin's Register and Boot, and assert on what it published. Drive HTTP handlers with `net/http/httptest`: `surf.Assemble` builds the same handler `serve` uses, so a test can send requests to your routes without listening on a port. Call console commands in-process with `bonfire.Call`. ## Database tests SummerCMS supports PostgreSQL only, so database tests run against real PostgreSQL rather than an SQLite stand-in. The framework's own tests start a `postgres:16-alpine` container through testcontainers-go and create the database with the ICU `pl-PL` locale that lagoon checks for when it connects. Follow the same pattern in plugin tests: - skip the test when `testing.Short` reports true; - create the database with `LOCALE_PROVIDER icu ICU_LOCALE 'pl-PL'`, or lagoon refuses the connection; - migrate a fresh database per test with `lagoon.Migrate`, so tests do not depend on each other. Docker must be running for these tests. ## API parity tests When you port an existing backend, its real responses are the acceptance test. [tide](../../modules/tide/README.md) records request and response fixtures from the reference backend and replays them against your port, reporting differences after masking IDs and timestamps. The `summer parity:record`, `summer parity:replay`, `summer parity:proxy` and `summer parity:broadcasts` commands wrap it. ## Examples in the documentation Every Go code block in these docs is a copy of an `Example` function or a marked region of a test that `go test ./...` runs. If you change a framework API and forget an example, `go test` fails. Write your plugin's examples the same way: an `Example` function with an `// Output:` comment is compiled, run and compared by `go test`, so it cannot go stale.