stefanprodan / timoni

Timoni is a package manager for Kubernetes, powered by CUE and inspired by Helm.
https://timoni.sh
Apache License 2.0
1.52k stars 66 forks source link

Document testing practices #169

Open benbooth493 opened 1 year ago

benbooth493 commented 1 year ago

The podinfo example provided here has some test files. Documentation around this would be great!

b4nst commented 1 year ago

Maybe not the best solution but one pattern we currently use in our company:

We have a /test directory at root module level. This directory contains a bunch of <test-name>.cue and <test-name>.expected.yml. We generate .<test-name>.actual.yml by using <test-name>.cue as a value file. Then we compare it to <test-name>.expected.yml using homeport/dyff (k8s aware). It's not super fancy but it gets the job done.

Here's our Makefile stanza if that's of any help

# Copyright © Loft Orbital Solutions Inc.
project_name := project

timoni := timoni
cue := cue
go := go
dyff := dyff

# Define sources
GEN_DEPS := $(shell go list -f '{{ join .Imports " " }}')
GEN_DEPS_DIR := $(addsuffix /.generated,$(addprefix cue.mod/gen/,$(GEN_DEPS)))
SOURCES := $(wildcard *.cue) $(wildcard templates/*.cue)
TEST_FILES := $(wildcard test/*.cue)
TEST_TARGETS := $(patsubst test/%.cue,test/.%.run,$(TEST_FILES))

all: lint test fmt ## Run all checks and format code

go.sum: dependencies.go go.mod
    $(go) mod tidy

$(GEN_DEPS_DIR): go.sum
    $(cue) get go $(patsubst %/.generated,%,$(patsubst cue.mod/gen/%,%,$@))
    @touch $@

init: $(GEN_DEPS_DIR) ## Initialize module

lint: init ## Check module for syntax errors
    $(timoni) mod lint .
.PHONY: lint

test/.%.actual.yml: test/%.cue $(SOURCES) init
    $(timoni) build -n default -f $< $(project_name) . > $@

$(TEST_TARGETS): test/.%.run: test/%.expected.yml test/.%.actual.yml
    $(dyff) between -is $^
    @touch $@
test: $(TEST_TARGETS) ## Run tests

fmt: ## Format CUE files
    $(cue) fmt ./...
.PHONY: fmt

help: ## Show help
    @grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.PHONY: help

.DEFAULT_GOAL := help

Btw regarding the init target, we make use of a dependencies.go file to avoid versioning the content of cue.mod/gen. It gets automatically generated, and it's easier to maintain.

Here's an example of that dependencies.go file:

package main

// Placeholder for cue get go generation dependencies
import (
    _ "k8s.io/api/apps/v1"
    _ "k8s.io/api/core/v1"
    _ "k8s.io/api/autoscaling/v2"

    _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/sql/v1beta1"
    _ "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1"
)