Documentation
¶
Overview ¶
Package testutil provides shared testing utilities for the koopa project.
This package contains reusable test infrastructure that can be used across multiple packages, following the pattern of Go standard library packages like net/http/httptest and testing/iotest.
Index ¶
- func DiscardLogger() *slog.Logger
- type GoogleAISetup
- type RAGSetup
- type SSEEvent
- type Terminal
- func (t *Terminal) Close() error
- func (t *Terminal) ExpectPrompt(timeout time.Duration) error
- func (t *Terminal) ExpectRegex(pattern string, timeout time.Duration) ([]string, error)
- func (t *Terminal) ExpectString(expected string, timeout time.Duration) error
- func (t *Terminal) Output() string
- func (t *Terminal) Send(input string) error
- func (t *Terminal) SendLine(input string) error
- func (t *Terminal) WaitExit(timeout time.Duration) error
- type TestDBContainer
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DiscardLogger ¶
DiscardLogger returns a slog.Logger that discards all output. This is the standard library pattern for test loggers.
Use this in tests to reduce noise. For components that use log.Logger (which is a type alias for *slog.Logger), use log.NewNop() directly.
Note: log.Logger is a type alias for *slog.Logger, so this function and log.NewNop() return the same type. Prefer log.NewNop() when working with the internal/log package.
Types ¶
type GoogleAISetup ¶
GoogleAISetup contains all resources needed for Google AI-based tests.
func SetupGoogleAI ¶
func SetupGoogleAI(tb testing.TB) *GoogleAISetup
SetupGoogleAI creates a Google AI embedder with logger for testing.
This is the preferred setup function for integration tests that need both embedder and logger with real Google AI API access.
Requirements:
- GEMINI_API_KEY environment variable must be set
- Skips test if API key is not available
Example:
func TestKnowledge(t *testing.T) {
setup := testutil.SetupGoogleAI(t)
store := knowledge.NewStore(pool, setup.Logger)
// Use setup.Embedder, setup.Genkit, setup.Logger
}
Note: Accepts testing.TB interface to support both *testing.T (tests) and *testing.B (benchmarks). This allows the same setup to be used in both contexts.
type RAGSetup ¶
type RAGSetup struct {
// Genkit instance with both GoogleAI and PostgreSQL plugins
Genkit *genkit.Genkit
// Embedder for creating vector embeddings
Embedder ai.Embedder
// DocStore for indexing documents (from Genkit PostgreSQL plugin)
DocStore *postgresql.DocStore
// Retriever for semantic search (from Genkit PostgreSQL plugin)
Retriever ai.Retriever
}
RAGSetup contains all resources needed for RAG-enabled integration tests. This uses the Genkit PostgreSQL plugin for DocStore and Retriever.
func SetupRAG ¶
SetupRAG creates a complete RAG test environment using Genkit PostgreSQL plugin.
This function sets up:
- Genkit with GoogleAI plugin (for embeddings)
- PostgreSQL plugin wrapping the provided connection pool
- DocStore for indexing documents
- Retriever for semantic search
Requirements:
- GEMINI_API_KEY environment variable must be set
- PostgreSQL pool must be initialized (from SetupTestDB)
- Migrations must be run (SetupTestDB does this automatically)
Example:
func TestRAGFeature(t *testing.T) {
db, dbCleanup := testutil.SetupTestDB(t)
defer dbCleanup()
rag := testutil.SetupRAG(t, db.Pool)
// Index documents
doc := ai.DocumentFromText("test content", map[string]any{
"source_type": "file",
})
rag.DocStore.Index(ctx, []*ai.Document{doc})
// Query using retriever
req := &ai.RetrieverRequest{Query: ai.DocumentFromText("query", nil)}
resp, _ := rag.Retriever.Retrieve(ctx, req)
}
type SSEEvent ¶
type SSEEvent struct {
Type string // event: value
Data string // data: value (multi-line joined with \n)
}
SSEEvent represents a parsed Server-Sent Event.
func FindAllEvents ¶
FindAllEvents finds all events of a given type.
func ParseSSEEvents ¶
ParseSSEEvents parses SSE event stream into structured events.
Handles W3C SSE spec correctly:
- Multiple "data:" lines are joined with newline
- Empty line terminates an event
- data: before event: is allowed (defaults to "message" event type per W3C spec)
- Comments starting with ":" are ignored
The parser is lenient by default - incomplete final events (missing trailing empty line) are accepted with a warning log. This improves test reliability for truncated or real-world streams that may omit the trailing empty line.
Example:
events := testutil.ParseSSEEvents(t, responseBody) require.Len(t, events, 3) assert.Equal(t, "chunk", events[0].Type)
Note: Accepts testing.TB interface to support both *testing.T (tests) and *testing.B (benchmarks). This allows the same parser to be used in both contexts.
type Terminal ¶
type Terminal struct {
// contains filtered or unexported fields
}
Terminal provides a test helper for CLI interactive testing. It captures stdout/stderr and provides expect-style synchronous waiting.
func NewTerminal ¶
func NewTerminal(stdin io.WriteCloser, stdout, stderr io.ReadCloser) (*Terminal, error)
NewTerminal creates a new terminal test helper. It starts goroutines to capture stdout and stderr.
func (*Terminal) ExpectPrompt ¶
ExpectPrompt waits for the CLI prompt ("> ").
func (*Terminal) ExpectRegex ¶
ExpectRegex waits for the output to match the given regex pattern.
func (*Terminal) ExpectString ¶
ExpectString waits for the output to contain the expected string.
type TestDBContainer ¶
type TestDBContainer struct {
Container *postgres.PostgresContainer
Pool *pgxpool.Pool
ConnStr string
}
TestDBContainer wraps a PostgreSQL test container with connection pool.
Provides:
- Isolated PostgreSQL instance with pgvector extension
- Connection pool for database operations
- Automatic cleanup via cleanup function
Usage:
db, cleanup := testutil.SetupTestDB(t) defer cleanup() // Use db.Pool for database operations
func SetupTestDB ¶
func SetupTestDB(tb testing.TB) (*TestDBContainer, func())
SetupTestDB creates a PostgreSQL container for testing with pgvector extension.
Creates a fully-configured PostgreSQL container with:
- pgvector extension (for vector similarity search)
- Test database schema (via migrations)
- Connection pool ready for use
Returns:
- TestDBContainer: Container with connection pool
- cleanup function: Must be called to terminate container
Example:
func TestMyFeature(t *testing.T) {
db, cleanup := testutil.SetupTestDB(t)
defer cleanup()
// Use db.Pool for queries
var count int
err := db.Pool.QueryRow(ctx, "SELECT COUNT(*) FROM documents").Scan(&count)
require.NoError(t, err)
}
Note: Accepts testing.TB interface to support both *testing.T (tests) and *testing.B (benchmarks). This allows the same setup to be used in both contexts.