efftesting

package module
v0.241201.0 Latest Latest
Warning

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

Go to latest
Published: Dec 1, 2024 License: 0BSD Imports: 12 Imported by: 0

README

efftesting: effect testing

efftesting is a unit testing helper module that manages test expectations automatically. See https://pkg.go.dev/github.com/ypsu/efftesting for the documentation.

Note: this project uses https://ypsu.github.io/featver as its versioning scheme. The project will enter the more stable v1 version only when it has users already.

Documentation

Overview

Package efftesting checks expectations and optionally rewrites them if the EFFTESTING_UPDATE=1 envvar is set.

Its main feature is an Expect(effectName string, want any, got string) function. It stringifies want and compares that string to got and fails the test if they are not equal. The magic is this: if got is wrong, efftesting can automatically update the source code to the new value. It should make updating the tests for a code's effects a bit easier. effectName is just an arbitrary name to make the test log messages clearer.

See https://github.com/ypsu/efftesting/tree/main/example/example_test.go for a full example. See pkgtrim_test.go in https://github.com/ypsu/pkgtrim for a more realistic example.

Example:

func MyStringLength(s string) int {
	return len(s)
}

func TestLength(t *testing.T) {
	et := efftesting.New(t)
	et.Expect("string length of tükör", MyStringLength("tükör"), "7")
}

func TestMain(m *testing.M) {
	os.Exit(efftesting.Main(m))
}

Suppose you change the string to count utf8 characters instead of bytes:

func MyStringLength(s string) int {
	return utf8.RuneCountInString(s)
}

The expectation now fails with this:

$ go test example_test.go
--- FAIL: TestLength (0.00s)

    example_test.go:17: Non-empty diff for effect "string length of tükör", diff (-want, +got):
        -7
        +5

FAIL
Expectations need updating, use `EFFTESTING_UPDATE=1 go test ./...` for that.

Rerun the test with the EFFTESTING_UPDATE=1 envvar to update the test expectation to expect 5 if that was expected from the change.

There's also a Check(effectName string, want any, got string) variant that quits the test if the expectation doesn't match. So instead of this:

...
foo, err = foolib.New()
if err != nil {
	t.Failf("foolib.New() failed: %v.", err)
}
...

it's possible to write this:

foo, err = foolib.New()
et.Check("foolib.New() succeeded", err, "null")

You don't need to know beforehand that err's value will be stringified to null. Initially add only et.Check("foolib.New() succeeded", err, "") and then simply run update expectation command as described above. In fact you no longer need to know beforehand what any expression's result will be, you only need to tell if a result is correct or not. Ideal for code whose result is more a matter of taste rather than correctness (e.g. markdown rendering).

Most typical expectations can be rewritten to efftesting expectations. E.g. a EXPECT_LESS_THAN(3, 4) can be rewritten to Expect("comparison", 3 < 4, "true"). Or EXPECT_STRING_CONTAINS(str, "foo") can be rewritten to Expect("contains foo", strings.Contains(str, "foo"), "true"). Expect and Check can be a powerful building block to make managing tests simpler.

efftesting formats multiline strings with backticks. For convenience it formats structs and slices into a multiline json:

et.Expect("slice example", strings.Split("This is a sentence.", " "), `
	[
		"This",
		"is",
		"a",
		"sentence."
	]`)

Tip: include the string "TODO" in effectName for expectations that are still under development and are thus incorrect. This allows committing the expectations first. Once the correct implementation is in, the tests can be quickly updated with a single command. The only additional work then needed is removing the TODO markers while verifying the correctness of the expectations. Makes a test driven development much easier.

Index

Constants

This section is empty.

Variables

View Source
var Context = 2

Context is the number of lines to display before and after the diff starts and ends.

View Source
var Diff = dummydiff

Diff is the function to diff the expectation against the got value. Defaults to a very simple diff treats all lines changed from the first until the last change.

Functions

func Main

func Main(m *testing.M) int

Main is the TestMain for efftesting. If a _test.go file has efftesting expectations then call this explicitly:

func TestMain(m *testing.M) {
	os.Exit(efftesting.Main(m))
}

Types

type ET

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

ET (EffTesting) is an expectation tester.

func New

func New(t *testing.T) ET

New creates a new ET.

func (ET) Check

func (et ET) Check(desc string, got any, want expectationString)

Check checks that want is got. If they are unequal, the test is aborted. want must be a string literal otherwise the update feature won't work.

func (ET) Expect

func (et ET) Expect(desc string, got any, want expectationString)

Expect checks that want is got. want must be a string literal otherwise the update feature won't work.

Jump to

Keyboard shortcuts

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