testifyRecursive

package module
v0.0.1-beta.2 Latest Latest
Warning

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

Go to latest
Published: Jan 18, 2021 License: MIT Imports: 3 Imported by: 0

README

goRecursiveAssert

Extending https://github.com/stretchr/testify.git with recursive capabilities.

Tested for go 1.15.

Build Status codecov PkgGoDev

Why

The problem

If you've been into testing, you surely wrote a lot of such code :

package main

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

type MyStruct struct {
	A string
	B string
}

func MyFunction() MyStruct {
	return MyStruct{A: "foo", B: "bar"}
}

func TestMyFunction(t *testing.T) {
    res := MyFunction()
    assert.Equal(t, "foo", res.A)
    assert.Equal(t, "bar", res.B)
}

While this is a perfectly working and useful test, here is one problem : if your struct MyStruct changes in a next release, you may forget to update your test TestMyFunction. This means you may : Not check the value of a new field.

Solution provided

Enters goRecursiveAssert :

package main

import (
	rec "github.com/MaximeWeyl/goTestifyRecursive"
	bh "github.com/MaximeWeyl/goTestifyRecursive/behaviours"
	"testing"
)

type MyStruct struct {
	A string
	B string
}

func MyFunction() MyStruct {
	return MyStruct{A: "foo", B: "bar"}
}

func TestMyFunction(t *testing.T) {
    res := MyFunction()
    rec.AssertRecursive(t, res, bh.ExpectedStruct{
    	"A": "foo",
    	"B": "bar",
    })
}

If, later, you add a new Field to your struct, the test will fail. This will alert you that you probably want to update your test too.

Error handling

When a field is missing in the expected or actual value, you will get a nice error that you should understand easily :

        	Error:      	Fields are missing
        	Test:       	TestMyFunction
        	Messages:   	Some fields are missing : {C}

But you said "recursive"

Yes and here is why. This new syntax allow you to write nested assertions, just like this :

package main

import (
	rec "github.com/MaximeWeyl/goTestifyRecursive"
	bh "github.com/MaximeWeyl/goTestifyRecursive/behaviours"
	"testing"
)

type MyStruct struct {
	A string
	B []MyStruct
}

func MyFunction() MyStruct {
	return MyStruct{
		A: "foo", 
		B: []MyStruct{{
                A: "bar1",
                B: nil,
		    },
			{
				A: "bar2",
				B: []MyStruct{},
			},
		},
	}
}

func TestMyFunction(t *testing.T) {
    res := MyFunction()
    rec.AssertRecursive(t, res, bh.ExpectedStruct{
    	"A": "foo",
    	"B": bh.ExpectedSlice{
    		bh.ExpectedStruct{"A":"bar1", "B": []MyStruct(nil)},
    		bh.ExpectedStruct{"A":"bar2", "B": bh.ExpectedSlice{}},
        },
    })
}

The errors will also try to show you were your error is :

        	Error:      	Field not found
        	Test:       	TestMyFunction
        	Messages:   	Expected field not found : {B[1].C}

This way of writing tests prevents you from forgetting to update tests that need to be.

But I do not want to check for this new field

No problem, the idea of this lib is to let you know that you may want to check for a new field. But, if you decided that this new field should not be tested in this test, you can tell the lib to ignore it, you're the one that know your code best after all. Just use the IgnoredField struct.

package main

import (
	rec "github.com/MaximeWeyl/goTestifyRecursive"
	bh "github.com/MaximeWeyl/goTestifyRecursive/behaviours"
	"testing"
)

type MyStruct struct {
	A string
	B string
	NewField int
}

func MyFunction() MyStruct {
	return MyStruct{A: "foo", B: "bar"}
}

func TestMyFunction(t *testing.T) {
    res := MyFunction()
    rec.AssertRecursive(t, res, bh.ExpectedStruct{
    	"A": "foo",
    	"B": "bar",
    	"NewField": bh.IgnoredField{},
    })
}

Behaviours

You have seen several behaviours. The first one is known as the default behaviour : It is what happen when you pass an argument that does not implement the special interface FieldBehaviour.

In this case, the assertion checks that the field actual value is Equal to the expected value, with the help of testify's Equal function.

If you use an expected value that implements the FieldBehaviour interface, you will get customized behaviours, like with ExpectedStruct or ExpectedSlice or IgnoredField. This lib let you use several other behaviours, in the package github.com/MaximeWeyl/goTestifyRecursive/behaviours.

Writing your own behaviours

Writing a new behaviour is as simple as implementing the FieldBehaviour interface.

type FieldBehaviour interface {
CheckField(t assert.TestingT, actualValueInterface interface{}, parentFieldName string) bool
}

For instance, here is the code to write a behaviour that asserts that the field is not empty, using the original testify lib (this example is officially in this lib's behaviours).

package behaviours

import (
	"github.com/stretchr/testify/assert"
)

type NotEmptyField struct {
}

func (n NotEmptyField) CheckField(t assert.TestingT, actualValueInterface interface{}, fieldName string) bool {
	return assert.NotEmptyf(t, actualValueInterface, "Field {%s} should not be empty, but was", fieldName)
}

Require instead of Assert

Like in testify, you can stop your test immediately if the assertion fails. Simply use the function RequireRecursive instead of AssertRecursive

Contributing

Contributions are welcome, especially for writing new behaviours.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssertRecursive

func AssertRecursive(t assert.TestingT, actual interface{}, expected behaviours.FieldBehaviour) bool

AssertRecursive Performs a recursive assertion between an expected behaviour, and an actual value

func RequireRecursive

func RequireRecursive(t require.TestingT, actual interface{}, expected behaviours.FieldBehaviour)

RequireRecursive Same as AssertRecursive, but stops the test if failed

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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