snapshot

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Feb 6, 2022 License: MIT Imports: 11 Imported by: 0

README

snapshot - Snapshot test utilities for go

snapshot provides a set of utility functions for creating and loading snapshot files for using snapshot tests.

Install

go get -u github.com/djrollins/snapshot

Output Snapshot Example

package example

import (
	"testing"

	"github.com/djrollins/snapshot"
)

func ScanSum(in []int) (out []int) {
	sum := 0
	for i := range in {
		sum += i
		out = append(out, sum)
	}
	return
}

func TestScanPlus(t *testing.T) {
	nums := make([]int, 1000)
	for i := range nums {
		nums[i] = i
	}
	scan := ScanSum(nums)
	asJSON, err := snapshot.AsJSON(scan)
	if err != nil {
		t.Fatalf("failed to encode scan result to JSON")
	}
	ok, msg := snapshot.Match(t, asJSON)
	if !ok {
		t.Fatalf("scan did not match snapshot: %v", msg)
	}
}

Input Snapshot Example

package example

import (
	"io"
	"math/rand"
	"strings"
	"testing"
	"time"

	"github.com/djrollins/snapshot"
)

var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// EAR == "ExpensiveAsyncronousRandom" opertion provided by an external system,
// which also exposes a version number for their library.
const EARVersion = "v0.2.0"

func ExpensiveAsyncronousRandomOperation() (out io.Reader, err error) {
	out, in := io.Pipe()
	go func() {
		for i := 1; i < 1000; i++ {
			n := rand.Intn(len(letters))
			c := letters[n]
			in.Write([]byte{c})
			time.Sleep(2 * time.Millisecond)
		}
		in.Close()
	}()
	return
}

func TestEAR(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	// First time this test runs, this will take ~2 seconds. However, the
	// the input data is persisted to disk and reused on subsequent runs. This
	// allows for fast, repeatable tests that require complex input data
	// without having to manually create it. This should be used with custom
	// snapshot names based on versions so that a new snapshot is created
	// and breaking changes can be detected between versions.
	input := snapshot.GetTestInput(t,
		snapshot.WithCreateSnapshot(ExpensiveAsyncronousRandomOperation),
		snapshot.WithSnapshotName("ear_"+EARVersion),
	)
	buf := new(strings.Builder)
	_, _ = io.Copy(buf, input)

	upper := strings.ToUpper(buf.String())

	// Match will pass on the first run, as there is no snapshot recorded,
	// however it will ensure that future runs result in the same data,
	// until the snapshot is deleted.
	ok, msg := snapshot.Match(t, strings.NewReader(upper))
	if !ok {
		t.Fatalf("unexpected output: %v", msg)
	}
}

Documentation

Overview

Package snapshot provides utility functions for creating and loading on-disk data for use in snapshot tests.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AsJSON

func AsJSON(i interface{}) (out io.Reader, err error)

AsJSON marshals i to the io.Reader. If i is a function (as determined via reflection), it is called and the result is then marshalled to the resulting io.Reader - this is useful in the case where the generating the input data is expensive to compute or comes from an external source.

func GetTestInput

func GetTestInput(t *testing.T, optFns ...GetTestInputOption) (out io.Reader)

GetTestInput gets loads the input snapshot for a particular test case. By default, this looks for the file at the location <test-directory>/__snapshots__/<test-name>/input.txt. The base directory cannot be changed, however the file name can be overridden using with the relevant GetTestInputOption arguments. If the input snapshot file does not exist, the test immediately fails, unless a SnapshotCreator is provided as an argument. In this case the resulting reader for the SnapshotCreator is used as the input data for the current test run and persisted to disk for use in subsequent test runs.

func Match

func Match(t *testing.T, actual io.Reader, optFns ...MatchOption) (ok bool, msg string)

Match loads the output snapshot for a particular test case. By default, this looks for the file at the location <test-directory>/__snapshots__/<test-name>/output.txt. The base directory cannot be changed, however the file name can be overridden using with the relevant MatchOption arguments. If the output snapshot file does not exist, the input actual is used in its place and the test is likely to succeed. In this case actual is also persisted to the disk for use in subsequent test runs.

func NopReaderNormaliser added in v0.2.0

func NopReaderNormaliser(r io.Reader) io.Reader

NopReaderNormaliser is the default ReaderNormaliser. It passes the input io.Reader through unmodified

func StringComparator

func StringComparator(expected, actual io.Reader) (ok bool, msg string)

StringComparator reads expected and actual into strings and performs an equality check.

func StringDiffComparator added in v0.2.0

func StringDiffComparator(expected, actual io.Reader) (ok bool, msg string)

StringDiffComparator reads expected and actual into strings compares them using cmp.Diff from the go-cmp library. On failure the diff string is returned.

Types

type Comparator

type Comparator func(expected, actual io.Reader) (ok bool, msg string)

A Comparator can be used to override the default snapshot comparison. This function should compare the expected and actual io.Readers and return ok as true if they are deemed equal. The return value msg should be a human readable reason for the failure in the case where the values are not equal.

type GetTestInputOption

type GetTestInputOption interface {
	ApplyInputOption(*GetTestInputOptions)
}

GetTestInputOption may be an argument to GetTestInput in order to change GetTestInputOptions

func WithCreateSnapshot

func WithCreateSnapshot(r func() (io.Reader, error)) GetTestInputOption

WithCreateSnapshot provides a SnapshotCreator function to specify the data for the test when no snapshot file exists. This data is also persisted to disk and used for subsequent test runs.

func WithCreateSnapshotAsJSON

func WithCreateSnapshotAsJSON(i interface{}) GetTestInputOption

WithCreateSnapshotAsJSON configures GetTestInput to use AsJSON as the CreateSnapshot and sets the file extension to ".json".

func WithCreateSnapshotFromReader added in v0.2.0

func WithCreateSnapshotFromReader(r io.Reader) GetTestInputOption

WithCreateSnapshotFromReader creates SnapshotCreator func from a reader.

type GetTestInputOptionFunc added in v0.2.0

type GetTestInputOptionFunc func(*GetTestInputOptions)

GetTestInputOptionFunc applies a func to the GetTestInputOptions defaults.

func (GetTestInputOptionFunc) ApplyInputOption added in v0.2.0

func (giof GetTestInputOptionFunc) ApplyInputOption(o *GetTestInputOptions)

type GetTestInputOptions

type GetTestInputOptions struct {
	// SnapshotName is the name of the snapshot to load, without the
	// extension. This defaults to the value "input".
	SnapshotName string
	// FileExtension is the file extension of the snapshot. This defaults
	// to ".txt".
	FileExtension string
	// CreateSnapshot will be called if the snapshot file does not exist
	// The resulting io.Reader provides the input data for the currently
	// running test, as well as being copied to disk for future tests.
	// This is useful in cases where input data may be volatile or random
	// and would therefore usually be unsuitable for snapshot tests.
	CreateSnapshot SnapshotCreator
}

GetTestInputOptions are the set of options to configure the behaviour of GetTestInput.

type MatchOption

type MatchOption interface {
	ApplyMatchOption(*MatchOptions)
}

MatchOption may be an argument to Match in order to change MatchOptions.

func WithComparator

func WithComparator(cmp Comparator) MatchOption

WithComparator overrides the default comparator with a custom function.

func WithReaderNormaliser added in v0.2.0

func WithReaderNormaliser(rn ReaderNormaliser) MatchOption

WithReaderNormaliser provides a ReaderNormaliser function to apply to the actual and expected io.Readers before comparison.

type MatchOptionFunc added in v0.2.0

type MatchOptionFunc func(*MatchOptions)

WithMatchOption applies f to the MatchOptions defaults.

func (MatchOptionFunc) ApplyMatchOption added in v0.2.0

func (mof MatchOptionFunc) ApplyMatchOption(o *MatchOptions)

type MatchOptions

type MatchOptions struct {
	// SnapshotName is the name of the snapshot to load, without the
	// extension. This defaults to the value "output".
	SnapshotName string
	// FileExtension is the file extension of the snapshot. This defaults
	// to ".txt".
	FileExtension string
	// Comparator is a function to compare the actual and expected
	// io.Readers.
	Comparator Comparator
	// ReaderNormaliser is applied to the actual and expected io.Readers before
	// being passed to the comparator. This can be used to perform some clean
	// or modifications (i.e. sorting) of the snapshot/actual data before
	// comparison.
	ReaderNormaliser ReaderNormaliser
}

MatchOptions are the set of options to configure the behaviour of Match.

type ReaderNormaliser added in v0.2.0

type ReaderNormaliser func(io.Reader) io.Reader

A ReaderNormaliser is a function that takes an io.Reader and returns a new io.Reader after some processing. This function is applied to the actual and expected io.Readers before they are passed to the Comparator

type SnapshotCreator

type SnapshotCreator func() (io.Reader, error)

A SnapshotCreator is a function that can be provided to GetTestInput which will be used used in the case where an input snapshot file does not exist.

type SnapshotOption added in v0.2.0

type SnapshotOption interface {
	GetTestInputOption
	MatchOption
}

func WithSnapshotFileExtension added in v0.2.0

func WithSnapshotFileExtension(name string) SnapshotOption

WithSnapshotFileExtension overrides the file extension for the resulting snapshot file. This is useful if the snapshots are read by external tools and make use of the extensions to determine the filetype.

func WithSnapshotFilename

func WithSnapshotFilename(name string) SnapshotOption

WithSnapshotFilename overrides snapshot name and file extension of the resulting snapshot file.

func WithSnapshotName added in v0.2.0

func WithSnapshotName(name string) SnapshotOption

WithSnapshotName overrides the snapshot name. This is useful in cases where there may be multiple input/output snapshots for a test. This option does not change the file extension.

Jump to

Keyboard shortcuts

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