Background
GoBlog currently has a strong, hermetic unit suite but no integration
tests — an acknowledged, planned gap. The testing audit identified several
behaviours that are inherently hard to cover at the unit level and are the
natural home for an integration layer. We intend to build this layer with
testcontainers, booting the CLI / Docker
image against a real environment as black-box tests.
Areas that would benefit from integration testing
Server.Run lifecycle — real port bind, graceful shutdown, signal handling
(currently 0% covered; only the ctx-cancel path is driven indirectly).
- Bind-error propagation (
listenErr) when the port is already in use.
- Graceful-shutdown timeout behaviour.
- End-to-end live reload — a real watcher firing into a real server, served
content updating after a file change (unit tests are too coarse to prove this
through the full stack).
- CLI flag → behaviour at the process level (
NewServeCommand /
NewGeneratorCommand, both 0% — the go install and Docker channels).
- A Docker image smoke test exercising the published artifact.
How these should be written
- Use
testcontainers-go to boot the built CLI / Docker image against a real
temp content directory.
- Keep the layer narrow and black-box: a handful of tests that boot the
tool, hit HTTP endpoints, mutate a file on disk, and assert the served output
changes — not a broad E2E matrix.
- Treat it as a confirmation layer on top of the unit suite. The unit-level
concurrency and watcher-clock work (see related issue) should land first, so
integration tests confirm rather than first-discover concurrency behaviour.
User Stories
As a maintainer
I want an integration test layer built on testcontainers
So that the serve lifecycle and live-reload behaviours unit tests cannot
reach are verified end-to-end before a release.
Acceptance Criteria
Given the goblog server is running against a real temp directory
When a markdown file is added or edited on disk
Then the served HTTP response reflects the change (end-to-end live reload
through a real watcher and real server).
Given the server is asked to bind to a port already in use
When Run starts
Then the bind error is surfaced rather than silently swallowed.
Given a running server
When it receives a shutdown signal (or its context is cancelled)
Then it shuts down gracefully within the configured timeout.
Given the built CLI / Docker image
When it is invoked with representative flags against a temp directory
Then it generates and/or serves the expected content (covering the CLI and
Docker distribution paths).
Given the integration suite
When CI runs
Then it executes the testcontainers tests in a dedicated, clearly-separated
job/stage (so unit-test feedback stays fast).
Background
GoBlog currently has a strong, hermetic unit suite but no integration
tests — an acknowledged, planned gap. The testing audit identified several
behaviours that are inherently hard to cover at the unit level and are the
natural home for an integration layer. We intend to build this layer with
testcontainers, booting the CLI / Docker
image against a real environment as black-box tests.
Areas that would benefit from integration testing
Server.Runlifecycle — real port bind, graceful shutdown, signal handling(currently 0% covered; only the ctx-cancel path is driven indirectly).
listenErr) when the port is already in use.content updating after a file change (unit tests are too coarse to prove this
through the full stack).
NewServeCommand/NewGeneratorCommand, both 0% — thego installand Docker channels).How these should be written
testcontainers-goto boot the built CLI / Docker image against a realtemp content directory.
tool, hit HTTP endpoints, mutate a file on disk, and assert the served output
changes — not a broad E2E matrix.
concurrency and watcher-clock work (see related issue) should land first, so
integration tests confirm rather than first-discover concurrency behaviour.
User Stories
As a maintainer
I want an integration test layer built on testcontainers
So that the serve lifecycle and live-reload behaviours unit tests cannot
reach are verified end-to-end before a release.
Acceptance Criteria
Given the goblog server is running against a real temp directory
When a markdown file is added or edited on disk
Then the served HTTP response reflects the change (end-to-end live reload
through a real watcher and real server).
Given the server is asked to bind to a port already in use
When
RunstartsThen the bind error is surfaced rather than silently swallowed.
Given a running server
When it receives a shutdown signal (or its context is cancelled)
Then it shuts down gracefully within the configured timeout.
Given the built CLI / Docker image
When it is invoked with representative flags against a temp directory
Then it generates and/or serves the expected content (covering the CLI and
Docker distribution paths).
Given the integration suite
When CI runs
Then it executes the testcontainers tests in a dedicated, clearly-separated
job/stage (so unit-test feedback stays fast).