testutil

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2026 License: MIT Imports: 10 Imported by: 0

README

Package testutil

Package testutil provides utilities for testing code generation using golden files.

Overview

Golden file testing compares generated output against expected output stored in files. When code generation changes, you can review the differences and update the golden files if the changes are correct.

This package provides:

  • Simple assertion functions for common cases
  • A fluent API for advanced scenarios
  • Automatic formatting for Go code and JSON
  • Cross-platform line ending normalization
  • Batch operations for testing multiple files

Basic Usage

The simplest way to test generated code:

func TestCodeGen(t *testing.T) {
    // Generate your code
    code := generateSomeCode()
    
    // Compare with golden file
    testutil.AssertString(t, "testdata/golden/expected.golden", code)
}

Run tests normally:

go test

Update golden files when output changes:

go test -update

Common Patterns

Testing Multiple Files

When generating multiple related files:

func TestMultipleFiles(t *testing.T) {
    batch := testutil.NewBatch(t)
    
    batch.AddString("server.go.golden", generateServer()).
          AddString("client.go.golden", generateClient()).
          AddString("types.go.golden", generateTypes()).
          Compare()
}
Format-Specific Testing

The package automatically formats content based on file type:

func TestFormattedOutput(t *testing.T) {
    // Go code is automatically formatted
    goCode := generateGoCode() // even if unformatted
    testutil.AssertGo(t, "output.go.golden", goCode)
    
    // JSON is pretty-printed
    jsonData := generateJSON() // even if minified
    testutil.AssertJSON(t, "config.json.golden", jsonData)
}

Testing Multiple Generated Files

When testing code generators that produce multiple files, you can use batch operations to test them all at once. This ensures all generated files remain consistent with each other.

Advanced Usage

Fluent API

For more control over the comparison process:

func TestWithFluentAPI(t *testing.T) {
    gf := testutil.NewGoldenFile(t, "testdata/golden")
    
    code := generateCode()
    
    gf.StringContent(code).
       Path("service.go.golden").
       CompareContent()
}
Directory Comparison

Compare entire directory structures:

func TestGeneratedDirectory(t *testing.T) {
    // Generate files to a directory
    generateToDirectory("./generated")
    
    // Compare against golden directory
    snapshot := testutil.NewDirSnapshot(t, "./generated", "testdata/golden/expected")
    snapshot.Ignore("*.tmp", "*.log").Compare()
}

Command Line Flags

# Update golden files
go test -update    # or -u or -w

# Sequential updates (for debugging)
go test -update -golden.parallel=false

File Organization

Golden files are typically stored in testdata/golden/ directories. This is the default when using NewGoldenFile with an empty base path:

// Uses "testdata/golden" as base path
gf := testutil.NewGoldenFile(t, "")
gf.StringContent(code).Path("output.golden").CompareContent()
// Creates: testdata/golden/output.golden

// Uses custom base path
gf := testutil.NewGoldenFile(t, "testdata/custom")
gf.StringContent(code).Path("output.golden").CompareContent()
// Creates: testdata/custom/output.golden

// Assert functions use paths exactly as provided
testutil.AssertString(t, "testdata/golden/output.golden", code)
// Creates: testdata/golden/output.golden

Typical directory structure:

mypackage/
├── generator.go
├── generator_test.go
└── testdata/
    └── golden/
        ├── server.go.golden
        ├── client.go.golden
        └── types.go.golden

Content Type Detection

The package automatically detects and formats content based on file extensions:

  • .go or .go.golden: Formatted with go/format
  • .json or .json.golden: Pretty-printed with proper indentation
  • Other extensions: Treated as plain text
  • Other extensions: Treated as plain text

Notes

  • Golden files should be committed to version control
  • Always review diffs carefully before updating golden files
  • Line endings are automatically normalized for cross-platform compatibility
  • The package ensures thread-safe access to golden files

API Reference

See the package documentation for complete API details.

Documentation

Overview

Package testutil provides testing utilities for the Loom code generation framework.

Golden File Testing

The package provides utilities for golden file testing, a technique where expected outputs are stored in files and compared against actual outputs during tests. This is particularly useful for testing code generation where outputs can be large and complex.

Basic Usage:

func TestCodeGeneration(t *testing.T) {
	// Create a golden file manager
	gf := testutil.NewGoldenFile(t, "testdata/golden")

	// Generate code
	code := generateCode()

	// Compare with golden file
	gf.Compare(code, "mytest.golden")
}

Updating Golden Files:

To update golden files when the expected output changes, run tests with the -update flag:

go test ./... -update

Legacy Compatibility:

For backward compatibility with existing tests, use CompareOrUpdateGolden:

testutil.CompareOrUpdateGolden(t, actual, "path/to/file.golden")

This function uses the same -update flag but requires the full path to the golden file.

Advanced Usage:

The GoldenFile type provides additional methods for more complex scenarios:

// Compare multiple files at once
gf.CompareMultiple(map[string]string{
	"file1.golden": code1,
	"file2.golden": code2,
})

// Create golden file if it doesn't exist
gf.CompareOrCreate(code, "new.golden")

// Check if a golden file exists
if gf.Exists("optional.golden") {
	gf.Compare(code, "optional.golden")
}

Organization:

Golden files are typically organized under a testdata/golden directory within each package. This keeps test data close to the tests while maintaining a clean structure.

Package testutil provides world-class utilities for testing code generation with golden files. It offers a fluent API, intelligent diffing, batch operations, and format-aware comparisons.

Index

Constants

View Source
const DefaultBasePath = "testdata/golden"

DefaultBasePath is the default directory for golden files

Variables

This section is empty.

Functions

func Assert

func Assert(t testing.TB, goldenPath string, got []byte)

Assert provides a simple assertion API

func AssertGo

func AssertGo(t testing.TB, goldenPath string, got string)

AssertGo compares Go source code with proper formatting

func AssertJSON

func AssertJSON(t testing.TB, goldenPath string, got []byte)

AssertJSON compares JSON content with proper formatting

func AssertString

func AssertString(t testing.TB, goldenPath string, got string)

AssertString provides a simple assertion API for strings

func CompareOrUpdateGolden

func CompareOrUpdateGolden(t *testing.T, actual, golden string)

CompareOrUpdateGolden provides a drop-in replacement for the legacy function used throughout the codebase. New code should use GoldenFile instead. The golden parameter should be a full path to the golden file.

Types

type GoldenFile

type GoldenFile struct {
	// contains filtered or unexported fields
}

GoldenFile manages golden file testing operations with a fluent API

func NewGoldenFile

func NewGoldenFile(t testing.TB, basePath string) *GoldenFile

NewGoldenFile creates a new GoldenFile instance with default options

func (*GoldenFile) Compare deprecated

func (g *GoldenFile) Compare(actual string, golden string)

Compare compares the actual content with the golden file content (legacy API)

Deprecated: Use StringContent().Path().CompareContent() for the fluent API

func (*GoldenFile) CompareBytes

func (g *GoldenFile) CompareBytes(actual []byte, golden string)

CompareBytes is like Compare but works with byte slices (legacy API)

func (*GoldenFile) CompareContent

func (g *GoldenFile) CompareContent()

CompareContent performs the golden file comparison

func (*GoldenFile) Content

func (g *GoldenFile) Content(content []byte) *GoldenFile

Content sets the content to compare (fluent API)

func (*GoldenFile) Exists

func (g *GoldenFile) Exists(golden string) bool

Exists checks if a golden file exists

func (*GoldenFile) Path

func (g *GoldenFile) Path(path string) *GoldenFile

Path sets the golden file path (fluent API)

func (*GoldenFile) SetUpdateMode

func (g *GoldenFile) SetUpdateMode(update bool)

SetUpdateMode sets whether this GoldenFile should update golden files on compare.

func (*GoldenFile) StringContent

func (g *GoldenFile) StringContent(content string) *GoldenFile

StringContent sets string content to compare (fluent API)

Jump to

Keyboard shortcuts

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