testing
running the test suite
# run all Go tests
go test ./...
# verbose output (what CI uses)
go test -v ./...
# run a single package
go test ./config/taskparser/...
# run a specific test by name
go test ./config/taskfsm/... -run TestTransitionEvents -v
Via just:
just test # go test ./...
CI test matrix
The build workflow runs on every push and pull request that touches Go files:
- unit tests —
go test -v ./...onubuntu-latest - cross-compilation —
go buildforlinux/amd64,linux/arm64,darwin/amd64,darwin/arm64
The lint workflow adds:
- golangci-lint — runs via
golangci/golangci-lint-action@v6(versionv1.64.6, fast mode, only new issues) - gofmt check — fails if
gofmt -l .produces any output
Always run gofmt -w <your-files> before pushing. The CI formatting check is strict.
test patterns
table-driven tests
Most packages follow Go's standard table-driven style with testify:
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSomeBehavior(t *testing.T) {
cases := []struct {
name string
input string
want string
wantErr bool
}{
{"happy path", "foo", "bar", false},
{"error case", "", "", true},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got, err := doSomething(tc.input)
if tc.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tc.want, got)
})
}
}
isolation helpers
Use the standard library helpers to keep tests hermetic:
| helper | use for |
|---|---|
t.TempDir() | temporary directories that are cleaned up automatically |
t.Setenv(k, v) | environment variables scoped to the test |
| fake/stub executors | replacing external processes like tmux, git, or network calls |
no real external processes
Do not invoke real tmux, git commands, or make network requests in unit tests. The test suite must pass in an isolated CI environment. Use fake executors or in-memory implementations. Examples:
session/tmux/tests use acmd.Executorinterface with a stub implementation.config/taskstore/tests use an in-memory SQLite database viat.TempDir().- Filesystem-based signal tests write to
t.TempDir()rather than the real.kasmos/directory.
testing the task FSM
The FSM in config/taskfsm/fsm.go is a pure state machine — test it without any store or real I/O:
fsm := taskfsm.New(taskfsm.StatusReady)
err := fsm.Transition(taskfsm.EventImplement)
require.NoError(t, err)
assert.Equal(t, taskfsm.StatusImplementing, fsm.Status())
web / frontend
The marketing site (web/) and docs site (web/docs/) do not currently have JavaScript unit tests. CI validates them through npm run build. If you add new MDX pages, verify the build passes:
cd web/docs && npm ci && npm run build
writing new tests
- Place test files adjacent to the package they test (
foo_test.gonext tofoo.go). - Name test functions
TestXxx(unit) orBenchmarkXxx(benchmarks). - Prefer
requirefor assertions that should abort the test on failure,assertfor non-fatal checks. - Add a
TestMainif the package needs global setup (e.g., logging initialization). Seeapp/app_test.gofor an example. - For new CLI subcommands, add tests in
cmd/that use a fake executor and capture command output.