testutil

package
v0.0.0-...-26e635b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 22, 2025 License: MIT Imports: 25 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func DiscardLogger

func DiscardLogger() *slog.Logger

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

type GoogleAISetup struct {
	Embedder ai.Embedder
	Genkit   *genkit.Genkit
	Logger   *slog.Logger
}

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

func SetupRAG(tb testing.TB, pool *pgxpool.Pool) *RAGSetup

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

func FindAllEvents(events []SSEEvent, eventType string) []SSEEvent

FindAllEvents finds all events of a given type.

func FindEvent

func FindEvent(events []SSEEvent, eventType string) *SSEEvent

FindEvent finds an event by type in the parsed events. Returns nil if not found.

func ParseSSEEvents

func ParseSSEEvents(tb testing.TB, body string) []SSEEvent

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) Close

func (t *Terminal) Close() error

Close closes the terminal and cleans up resources.

func (*Terminal) ExpectPrompt

func (t *Terminal) ExpectPrompt(timeout time.Duration) error

ExpectPrompt waits for the CLI prompt ("> ").

func (*Terminal) ExpectRegex

func (t *Terminal) ExpectRegex(pattern string, timeout time.Duration) ([]string, error)

ExpectRegex waits for the output to match the given regex pattern.

func (*Terminal) ExpectString

func (t *Terminal) ExpectString(expected string, timeout time.Duration) error

ExpectString waits for the output to contain the expected string.

func (*Terminal) Output

func (t *Terminal) Output() string

Output returns the current captured output.

func (*Terminal) Send

func (t *Terminal) Send(input string) error

Send sends input without newline.

func (*Terminal) SendLine

func (t *Terminal) SendLine(input string) error

SendLine sends a line of input (with newline).

func (*Terminal) WaitExit

func (t *Terminal) WaitExit(timeout time.Duration) error

WaitExit waits for the CLI to exit.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL