zoobzio January 18, 2026 Edit this page

Testing Guide

This guide covers how to test code that uses chisel, including test helpers, fixtures, and mocking strategies.

Test Helpers

Chisel provides test utilities in github.com/zoobz-io/chisel/testing:

import (
    "testing"

    "github.com/zoobz-io/chisel"
    chitesting "github.com/zoobz-io/chisel/testing"
)

func TestChunking(t *testing.T) {
    chunks := getChunks() // your code

    // Assert chunk count
    chitesting.AssertChunkCount(t, chunks, 3)

    // Assert symbol exists
    chitesting.AssertHasSymbol(t, chunks, "UserService")

    // Assert kind exists
    chitesting.AssertHasKind(t, chunks, chisel.KindClass)
}

Available Helpers

FunctionDescription
AssertChunkCount(t, chunks, n)Fails if len(chunks) != n
AssertHasSymbol(t, chunks, sym)Fails if no chunk has symbol sym
AssertHasKind(t, chunks, kind)Fails if no chunk has kind kind
FindBySymbol(chunks, sym)Returns first chunk with symbol, or nil
FindByKind(chunks, kind)Returns first chunk with kind, or nil
CountByKind(chunks, kind)Returns count of chunks with kind

Testing Chunk Output

For detailed assertions, use FindBySymbol or FindByKind:

func TestAuthenticateFunction(t *testing.T) {
    source := []byte(`
func Authenticate(user, pass string) (*User, error) {
    // implementation
}
`)
    provider := golang.New()
    chunks, err := provider.Chunk(context.Background(), "auth.go", source)
    if err != nil {
        t.Fatal(err)
    }

    chunk := chitesting.FindBySymbol(chunks, "Authenticate")
    if chunk == nil {
        t.Fatal("Authenticate not found")
    }

    if chunk.Kind != chisel.KindFunction {
        t.Errorf("Kind = %v, want function", chunk.Kind)
    }

    if chunk.StartLine != 2 {
        t.Errorf("StartLine = %d, want 2", chunk.StartLine)
    }
}

Table-Driven Tests

For comprehensive coverage, use table-driven tests:

func TestProviderChunking(t *testing.T) {
    tests := []struct {
        name     string
        source   string
        wantSyms []string
        wantKind chisel.Kind
    }{
        {
            name:     "function",
            source:   "func Add(a, b int) int { return a + b }",
            wantSyms: []string{"Add"},
            wantKind: chisel.KindFunction,
        },
        {
            name:     "method",
            source:   "func (c *Calc) Add(n int) { c.v += n }",
            wantSyms: []string{"Calc.Add"},
            wantKind: chisel.KindMethod,
        },
    }

    provider := golang.New()
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            src := "package main\n" + tt.source
            chunks, err := provider.Chunk(context.Background(), "test.go", []byte(src))
            if err != nil {
                t.Fatal(err)
            }

            for _, sym := range tt.wantSyms {
                chitesting.AssertHasSymbol(t, chunks, sym)
            }
            chitesting.AssertHasKind(t, chunks, tt.wantKind)
        })
    }
}

Mocking Providers

For unit testing code that consumes chunks, mock the provider:

type mockProvider struct {
    chunks []chisel.Chunk
    err    error
}

func (m *mockProvider) Chunk(ctx context.Context, filename string, content []byte) ([]chisel.Chunk, error) {
    return m.chunks, m.err
}

func (m *mockProvider) Language() chisel.Language {
    return chisel.Go
}

func TestChunkProcessor(t *testing.T) {
    mock := &mockProvider{
        chunks: []chisel.Chunk{
            {Symbol: "Test", Kind: chisel.KindFunction, StartLine: 1, EndLine: 5},
        },
    }

    processor := NewProcessor(mock)
    result := processor.Process(context.Background(), "test.go", []byte("..."))

    // Assert on result
}

Testing Error Handling

Test that your code handles parsing errors gracefully:

func TestInvalidSource(t *testing.T) {
    provider := golang.New()

    // Invalid Go syntax
    source := []byte("func broken( {")
    _, err := provider.Chunk(context.Background(), "bad.go", source)

    if err == nil {
        t.Error("expected error for invalid syntax")
    }
}

Fixture Files

For complex test cases, use fixture files:

testdata/
├── simple.go
├── complex.go
└── expected/
    ├── simple.json
    └── complex.json
func TestFixtures(t *testing.T) {
    files, _ := filepath.Glob("testdata/*.go")
    for _, file := range files {
        t.Run(filepath.Base(file), func(t *testing.T) {
            source, _ := os.ReadFile(file)
            chunks, err := provider.Chunk(ctx, file, source)
            if err != nil {
                t.Fatal(err)
            }

            // Compare against expected output
            expected := loadExpected(t, file)
            assertChunksEqual(t, chunks, expected)
        })
    }
}

Benchmarking

Chisel includes benchmarks in testing/benchmarks/. Run them with:

go test -bench=. github.com/zoobz-io/chisel/testing/benchmarks -benchmem

To add benchmarks for your own code:

func BenchmarkMyProcessor(b *testing.B) {
    provider := golang.New()
    source := loadLargeFile()

    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        chunks, _ := provider.Chunk(context.Background(), "large.go", source)
        processChunks(chunks)
    }
}

Next Steps