Skip to content

Helpers

Project-Specific Helpers

Create reusable test helpers for your project by wrapping common overrides.

Creating Helpers

Create a separate file in your tests directory:

tests/my_helpers.go
package main

import "github.com/karlderkaefer/kcl-test/pkg/kcltest"

// Project-specific convenience functions
func WithTeamName(name string) kcltest.TestOption {
    return kcltest.WithStringOverride(
        []string{"oxr", "spec", "resourceConfig", "teamName"},
        name,
    )
}

func WithRegion(region string) kcltest.TestOption {
    return kcltest.WithStringOverride(
        []string{"oxr", "spec", "resourceConfig", "btpRegion"},
        region,
    )
}

func WithEnvironment(env string) kcltest.TestOption {
    return kcltest.WithStringOverride(
        []string{"oxr", "spec", "environment"},
        env,
    )
}

Using Helpers

assertion := kcltest.NewKCLAssertion(t, mainKCLPath).
    WithTestInput(
        WithTeamName("my-team"),
        WithRegion("eu10"),
        WithEnvironment("production"),
    )

Benefits

  • Readable tests: WithTeamName("my-team") is clearer than raw path arrays
  • Maintainable: Change paths in one place when schema changes
  • Type-safe: Compile-time checks for helper function signatures

Structured Errors

The framework provides structured error types for better debugging.

AssertionError

err := &kcltest.AssertionError{
    Type:     kcltest.AssertionTypeEqual,
    Kind:     "Subaccount",
    Path:     "spec.forProvider.region",
    Index:    -1,  // or item index for multi-item assertions
    Expected: "eu10",
    Actual:   "us-east-1",
    Message:  "Region should match expected value",
}

Output:

Subaccount: expected 'eu10' at 'spec.forProvider.region', got 'us-east-1' - Region should match expected value

Error Collection

errs := &kcltest.AssertionErrors{}
errs.Add(err1)
errs.Add(err2)

if errs.HasErrors() {
    fmt.Println(errs.Error())
}

Error Types

Type Description
AssertionTypeEqual Value equality check failed
AssertionTypeExists Expected item/path to exist
AssertionTypeNotExists Expected item/path to not exist
AssertionTypeCount Item count mismatch
AssertionTypeMatches Custom matcher function failed
AssertionTypeItemNotFound Resource kind not found
AssertionTypePathNotFound Path not found in resource

Environment Variables

Variable Description
UPDATE_SNAPS=true Update snapshots instead of comparing

Updating Snapshots

UPDATE_SNAPS=true go test ./...

Best Practices

Organize Test Files

tests/
├── helpers.go          # Project-specific helpers
├── composition_test.go # Main composition tests
├── input.yaml          # Default test input
└── snapshots/          # Snapshot files
    └── TestComposition.snap

Reusable Test Fixtures

tests/fixtures.go
package main

import "github.com/karlderkaefer/kcl-test/pkg/kcltest"

// Common test configurations
var (
    DefaultHooks = kcltest.ChainHooks(
        kcltest.NewDefaultsHook(map[string]any{
            "ctx": defaultContext,
        }),
        kcltest.NewFilterHook(excludeUsageResources),
    )
)

func excludeUsageResources(item map[string]any) bool {
    kind, _ := kcltest.GetByPath[string](item, "kind")
    return kind != "Usage"
}

var defaultContext = map[string]any{
    "apiextensions.crossplane.io/environment": map[string]any{
        "region": "eu10",
    },
}

Table-Driven Tests

func TestRegions(t *testing.T) {
    tests := []struct {
        name     string
        region   string
        expected string
    }{
        {"EU region", "eu10", "eu-central-1"},
        {"US region", "us10", "us-east-1"},
        {"AP region", "ap10", "ap-southeast-1"},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            assertion := kcltest.NewKCLAssertion(t, mainKCLPath).
                WithTestInput(
                    kcltest.WithInputFile("input.yaml"),
                    WithRegion(tt.region),
                )

            assertion.AssertPath(
                "Subaccount",
                "spec.forProvider.awsRegion",
                tt.expected,
            )
        })
    }
}