Keep test helpers out of the shipped binary (closes #506)
check / check (push) Waiting to run

The four testing.go files in config, database, middleware and session
are gone. ClearEnvForTest moves to internal/config/configtest as
ClearEnv; the webhook database manager helpers move to
internal/database/databasetest as NewWebhookDBManager and
NewWebhookDBManagerWithLogger, and the middleware's NewForTest to
internal/middleware/middlewaretest as New, both now built through the
production constructors. Tests that wrapped an open main database use
database.Open. The session helpers move into the session package's
export_test.go; the middleware tests build their session through
session.New and age its timestamps instead of using a fake clock.

The session, middleware and webhook database manager now take the
*slog.Logger they log through, so tests in other packages can give
them their own.

Model: opus-5-5
This commit is contained in:
2026-10-06 10:02:49 +00:00
parent 3de345fe6f
commit 342ae4f04d
39 changed files with 342 additions and 330 deletions
+19 -40
View File
@@ -10,7 +10,6 @@ import (
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"sync/atomic"
"testing"
@@ -19,12 +18,11 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
_ "modernc.org/sqlite"
"sneak.berlin/go/webhooker/internal/database"
"sneak.berlin/go/webhooker/internal/database/databasetest"
"sneak.berlin/go/webhooker/internal/delivery"
"sneak.berlin/go/webhooker/internal/gormlog"
)
// iSetup holds common integration test dependencies.
@@ -45,12 +43,12 @@ func newISetup(t *testing.T) iSetup {
wDB := iSeedWebhookDB(t, dbMgr, wID)
return iSetup{
MainDB: mainDB,
MainDB: mainDB.DB(),
DBMgr: dbMgr,
WebhookID: wID,
WebhookDB: wDB,
Engine: delivery.NewTestEngineWithDB(
database.NewTestDatabase(mainDB),
mainDB,
dbMgr,
slog.New(slog.NewTextHandler(
os.Stderr,
@@ -64,35 +62,16 @@ func newISetup(t *testing.T) iSetup {
}
}
func iMainDB(t *testing.T) *gorm.DB {
// iMainDB opens a main database through database.Open, the way the
// service opens it, so these tests cannot pass against journal and
// locking settings production does not use.
func iMainDB(t *testing.T) *database.Database {
t.Helper()
dbPath := filepath.Join(
t.TempDir(), "main-test.db",
)
// Opened the way the service opens the main database, so these
// tests cannot pass against journal and locking settings
// production does not use.
sqlDB, err := database.OpenSQLite(
dbPath, database.SQLiteModeCreate,
)
db, err := database.Open(t.TempDir(), slog.New(slog.DiscardHandler))
require.NoError(t, err)
t.Cleanup(func() { _ = sqlDB.Close() })
db, err := gorm.Open(
sqlite.Dialector{Conn: sqlDB},
&gorm.Config{Logger: gormlog.New(slog.New(slog.DiscardHandler))},
)
require.NoError(t, err)
require.NoError(t, db.AutoMigrate(
&database.Webhook{},
&database.Target{},
&database.User{},
&database.Setting{},
))
t.Cleanup(func() { _ = db.Close() })
return db
}
@@ -102,7 +81,7 @@ func iDBManager(
) *database.WebhookDBManager {
t.Helper()
return database.NewTestWebhookDBManager(t.TempDir())
return databasetest.NewWebhookDBManager(t, t.TempDir())
}
func iSeedWebhookDB(
@@ -1154,17 +1133,17 @@ func TestRecoverInFlight_ReportsAMissingWebhookDatabase(t *testing.T) {
mainDB := iMainDB(t)
webhookID := uuid.New().String()
iCreateWebhook(t, mainDB, webhookID, "lost-database")
iCreateWebhook(t, mainDB.DB(), webhookID, "lost-database")
var logs bytes.Buffer
dbMgr := database.NewTestWebhookDBManagerWithLogger(
t.TempDir(), slog.New(slog.NewTextHandler(&logs, nil)),
dbMgr := databasetest.NewWebhookDBManagerWithLogger(
t, t.TempDir(), slog.New(slog.NewTextHandler(&logs, nil)),
)
t.Cleanup(func() { _ = dbMgr.CloseAll() })
engine := delivery.NewTestEngineWithDB(
database.NewTestDatabase(mainDB), dbMgr,
mainDB, dbMgr,
slog.New(slog.DiscardHandler),
&http.Client{Timeout: 5 * time.Second}, 1,
)
@@ -1188,14 +1167,14 @@ func TestRecoverInFlight_SkipsAWebhookDeletedAfterTheListIsRead(
mainDB := iMainDB(t)
webhookID := uuid.New().String()
iCreateWebhook(t, mainDB, webhookID, "deleted-during-recovery")
iCreateWebhook(t, mainDB.DB(), webhookID, "deleted-during-recovery")
// The first query to return is recovery's read of the list of
// webhooks. Deleting the webhook right after it puts the delete
// between that read and the opening of the webhook's database.
deleted := false
require.NoError(t, mainDB.Callback().Query().After("gorm:query").
require.NoError(t, mainDB.DB().Callback().Query().After("gorm:query").
Register("delete-after-list", func(*gorm.DB) {
if deleted {
return
@@ -1203,16 +1182,16 @@ func TestRecoverInFlight_SkipsAWebhookDeletedAfterTheListIsRead(
deleted = true
require.NoError(t, mainDB.Delete(
require.NoError(t, mainDB.DB().Delete(
&database.Webhook{}, "id = ?", webhookID,
).Error)
}))
dbMgr := database.NewTestWebhookDBManager(t.TempDir())
dbMgr := databasetest.NewWebhookDBManager(t, t.TempDir())
t.Cleanup(func() { _ = dbMgr.CloseAll() })
engine := delivery.NewTestEngineWithDB(
database.NewTestDatabase(mainDB), dbMgr,
mainDB, dbMgr,
slog.New(slog.DiscardHandler),
&http.Client{Timeout: 5 * time.Second}, 1,
)