Testing Introduction
Nimbus embraces Go's built-in testing package and adds a testing.TestClient for convenient HTTP testing. No extra test runner needed — just go test.
Test file conventions
Go discovers tests automatically. Place test files alongside the code they test, using the _test.go suffix.
app/controllers/users_test.go— tests for the users controllerapp/models/user_test.go— tests for the user modelmain_test.go— integration and HTTP tests
Setting up a test app
Create a helper that builds a Nimbus app configured for testing. Use an in-memory SQLite database to keep tests fast and isolated.
package main
import (
"github.com/CodeSyncr/nimbus"
"github.com/CodeSyncr/nimbus/database"
"github.com/CodeSyncr/nimbus/middleware"
)
func setupTestApp() *nimbus.App {
app := nimbus.New()
app.Router.Use(middleware.Recover())
db, _ := database.Connect("sqlite", ":memory:")
app.Container.Singleton("db", func() *gorm.DB {
return db
})
// Register routes
app.Router.Get("/health", healthHandler)
app.Router.Get("/users", listUsersHandler)
app.Router.Post("/users", createUserHandler)
return app
}
The TestClient
Nimbus provides testing.NewTestClient(router) which sends requests directly to the router without starting a real HTTP server. It returns *httptest.ResponseRecorder.
import nimbustest "github.com/CodeSyncr/nimbus/testing"
func TestHealthEndpoint(t *testing.T) {
app := setupTestApp()
client := nimbustest.NewTestClient(app.Router)
resp := client.Get("/health")
if resp.Code != 200 {
t.Errorf("expected 200, got %d", resp.Code)
}
}
Test database
For database tests, use :memory: with SQLite. Run migrations inside the test setup to get a clean schema each time.
func setupTestDB() *gorm.DB {
db, _ := database.Connect("sqlite", ":memory:")
db.AutoMigrate(&User{}, &Post{})
return db
}
Writing a basic test
Test functions must start with Test and accept *testing.T.
func TestCreateUser(t *testing.T) {
app := setupTestApp()
client := nimbustest.NewTestClient(app.Router)
body := []byte(`{"name":"Alice","email":"alice@example.com"}`)
resp := client.Post("/users", body)
if resp.Code != 201 {
t.Fatalf("expected 201, got %d", resp.Code)
}
}
Running tests
Use the standard Go test commands:
# Run all tests
go test ./...
# Run tests in a specific package
go test ./app/controllers/...
# Run with verbose output
go test -v ./...
# Run a specific test function
go test -run TestCreateUser ./...
Tips
- Use
t.Parallel()at the top of tests that can run concurrently. - Use table-driven tests for handler endpoints that need multiple input/output cases.
- Keep test setup DRY with helper functions like
setupTestApp(). - Use
t.Cleanup()to tear down resources when a test finishes.