attest

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Apr 13, 2021 License: MPL-2.0 Imports: 7 Imported by: 0

README

attest

An ever-growing list of assertions that make Go tests more readable and concise.

Build and Test

Installation:

Install Go, from your operating system's package manager or from the Golang website.

Open a terminal/console window and run

go get github.com/dscottboggs/attest

done!

Usage:

  package main

import (
  "testing"

  "github.com/dscottboggs/attest"
)

func TestExample(t *testing.T) {
  test := attest.Test{t}
  test.Attest(fmt.Sprintf("%T", "that something is true") == "string", "or %s a message", "log")
  var val1, val2 int
  test.Equals(val1, val2)
  val2 = 1
  test.Greater(val2, val1)
}

The implicit tests I use to perform testing on this package also serves as a great set of examples of its use. Unfortunately due to limitations in the Go testing methods, it's not really possible to test for failure cases, as they would fail the test. Recommendations are welcome for additional testing methodologies.

Contributing

Have a clever function that makes testing easier in Go? Submit a pull request or open an issue and let's discuss it!

About

Attest is a very lightweight testing library aimed at improving the intuitiveness and aesthetics of the go standard testing library, as well as reducing the amount of keystrokes per test, hence improving developer efficiency by a marginal amount with very minimal overhead and risk. Any given testing.T function can create an attest.Test object, whose methods can then perform tests.

A brief example:

package main

import (
  "testing"

  "github.com/dscottboggs/attest"
)

func TestExample(t *testing.T) {
  test := attest.NewTest(t)
  test.Attest(fmt.Sprintf("%T", "that something is true") == "string", "or %s a message", "log")
  const unchanging = 0
  var variable int
  test.Equals(unchanging, variable)
  variable = 1
  test.Greater(variable, unchanging)
}

That same test function with the default testing library might be written like:

func TestExample(t *testing.T) {
  if fmt.Sprintf("%T", "something is true") != "string" {
    t.Errorf("or %s a message", "log")
  }
  const unchanging = 0
  var variable int
  if fmt.Sprintf("%T", unchanging) != fmt.Sprintf("%T", variable) {
    t.Errorf("Value 1 had a different type (%T) than value 2 (%T)", unchanging, variable)
  }
  if unchanging != variable {
    t.Errorf("Value 1 (%d) didn't equal value 2 (%d).")
  }
  variable = 1
  if fmt.Sprintf("%T", unchanging) != fmt.Sprintf("%T", variable) {
    t.Errorf("Value 1 had a different type (%T) than value 2 (%T)", unchanging, variable)
  }
  if variable <= unchanging {
    t.Errorf("Value 1 was less than or equal to value 2")
  }
}

As you can see, this provides minimal benefit besides a reduced number of keystrokes when writing, but when reading back, the attest way is much easier to understand. Of course, you can mix-and-match:

func TestExample(t *testing.T){
  test := attest.New(t)
  if fmt.Sprintf("%T", "something is true") != "string" {
    test.Errorf("or %s a message", "log")
  }
  const unchanging = 0
  var variable int
  test.Equals(unchanging, variable)
  variable = 1
  test.GreaterThan(unchanging, variable)
}
Logging a custom message

All tests allow for an optional (or in the case of the few strictly boolean tests, required) message string and formatters to be forwarded to fmt.Sprintf()

Available test functions

The following tests are available:

  • Attest and That: the first argument must equal the boolean value true.
  • AttestNot and Not: the first argument must equal the boolean value false.
  • AttestOrDo: takes a callback function and arguments to forward to the callback in case of a failure
  • Nil and NotNil: the first argument must be nil or not nil, respectively.
  • Equals and NotEqual: the second argument must equal (or not equal, respectively) the first argument. Both require that the arguments be the same type
  • Compares, SimilarTo, DoesNotCompare, and NotSimilarTo: like Equals and NotEquals but the types don't have to be the same.
  • GreaterThan and LessThan: like Equals, but checks for the second value to be greater or less than the first argument.
  • Positive and Negative: are shortcuts for test.LessThan(0, ...) and test.GreaterThan(0, ...)
  • TypeIs and TypeIsNot: check the type of a value
  • Matches and DoesNotMatch: Check if the value matches a given regular expression.

In addition there are the following ways of handling error types and panics:

  • Handle: Log and fail if the first argument is a non-nil error.
  • HandleMultiple: Log and fail if any of the arguments to this are non-nil errors. Does not accept a callback or message.
  • AttestPanics and AttestNoPanic: ensure the given function panics or doesn't.
  • StopIf: Log and fail a fatal non-nil error
  • EatError: Logs and fails an error message if the second argument is a non-nil error, and returns the first argument. For handling function calls that return a value and an error in a single line.
  • FailOnError: Like StopIf combined with EatError -- stops the test immediately if there is an error, otherwise returns the value.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Test

type Test struct {
	*testing.T
	// contains filtered or unexported fields
}

Test -- A structure for containing methods and data for asserting and testing assertion validity

func New

func New(t *testing.T) Test

New returns a new Test struct so that you don't get the linter complaining about unkeyed struct literals when the value has no key. This Test will fail lazily by default; that is, it will continue with the test if an assertion fails. This behavior can be toggled by calling .ImmediateFailure() on the returned Test.

func NewImmediate added in v1.3.1

func NewImmediate(t *testing.T) Test

NewImmediate returns a Test which will fail at the first error by default. This can be toggled by calling .LazyFailure() on the returned Test.

func NewTest

func NewTest(t *testing.T) Test

NewTest does the same thing as New

func (*Test) Attest

func (t *Test) Attest(that bool, message string, formatters ...interface{})

Attest that `that` is true, or log `message` and fail the test.

func (*Test) AttestNoPanic

func (t *Test) AttestNoPanic(fun func(...interface{}), args ...interface{})

AttestNoPanic -- the inverse of AttestPanics

func (*Test) AttestNot

func (t *Test) AttestNot(that bool, message string, formatters ...interface{})

AttestNot -- assert that `that` is false. It just calls t.Attest(!that...

func (*Test) AttestOrDo

func (t *Test) AttestOrDo(that bool,
	callback func(*Test, ...interface{}),
	cbArgs ...interface{},
)

AttestOrDo -- call `callback` with the Test as a parameter and fail the test should `that` be false.

func (*Test) AttestPanics

func (t *Test) AttestPanics(fun func(...interface{}), args ...interface{})

AttestPanics -- Attest that when fun is called with args, it causes a panic. e.g.

t.AttestPanics(func(){log.Printf("Panics, passes test."); panic()})
t.AttestPanics(func(){log.Printf("Doesn't panic, fails test.")})

func (*Test) Compares

func (t *Test) Compares(var1, var2 interface{}, msgAndFmt ...interface{})

Compares checks to see if var1 loosely equals var2. This allows for some minor type coersion before checking equality. For example, Test.Equals("5", 5) will fail, but Test.Compares("5", 5) will pass.

This works by converting all values to a string with fmt.Sprintf("%v", value) before checking equality.

func (*Test) DoesNotCompare

func (t *Test) DoesNotCompare(var1, var2 interface{}, msgAndFmt ...interface{})

DoesNotCompare does the opposite of Compares/SimilarTo, the same as NotSimilarTo

func (*Test) DoesNotMatch

func (t *Test) DoesNotMatch(pattern *regexp.Regexp, value string, msgAndFmt ...interface{})

DoesNotMatch inverts Matches

func (*Test) EatError

func (t *Test) EatError(value interface{}, err error) interface{}

EatError accepts two values, the latter of which is a nillable error. If the error is not nil, the test is failed. Regardless, the first value is returned through the function.

func (*Test) Equals

func (t *Test) Equals(
	var1, var2 interface{}, msgAndFormatters ...interface{},
)

Equals checks that var1 is deeply equal to var2. Optionally, you can pass an additional string and additional string formatters to be passed to Test.Attest. If no message is specified, a message will be logged simply stating that the two values weren't equal.

func (*Test) FailOnError

func (t *Test) FailOnError(value interface{}, err error, msgAndFormat ...interface{}) interface{}

FailOnError accepts two values, the latter of which is a nillable error. If the error is not nil, the test is failed immediately.

func (*Test) GreaterThan

func (t *Test) GreaterThan(
	expected,
	variable interface{},
	msgAndFmt ...interface{},
)

GreaterThan -- log a message and fail if the variable is less than the expected value

func (*Test) Handle

func (t *Test) Handle(err error, msgAndFmt ...interface{})

Handle -- handle an error with an optional custom message.

func (*Test) HandleMultiple

func (t *Test) HandleMultiple(e ...error)

Handle -- log and fail for an arbitrary number of errors.

func (*Test) ImmediateFailure added in v1.3.1

func (t *Test) ImmediateFailure()

func (*Test) LazyFailure added in v1.3.1

func (t *Test) LazyFailure()

func (*Test) LessThan

func (t *Test) LessThan(expected,
	variable interface{},
	msgAndFmt ...interface{},
)

LessThan -- log a message and fail if variable is negative.

func (*Test) Matches

func (t *Test) Matches(pattern *regexp.Regexp, value string, msgAndFmt ...interface{})

Matches determines if value matches the regex pattern

func (*Test) Negative

func (t *Test) Negative(variable interface{}, msgAndFmt ...interface{})

Negative -- log a message and fail if variable is positive or zero.

func (*Test) NewRecorder

func (t *Test) NewRecorder(params ...string) (*httptest.ResponseRecorder, *http.Request)

NewRecorder retreives an httptest.ResponseRecorder and http.Request pointer pair. This function is variadic. That is, it accepts a varying number of arguments. If no arguments are passed, it uses the method "GET" and the default URL, with an empty body. This works for testing the index path. The first-priority parameter is the URL. It can begin with an actual URL, or a literal "/" and the default URL will be used with the given path. If two paramters are passed, they should be in the order (method, URL). An empty body will be used. If three paramters are passed, they are forwarded to the httptest.NewRequest function, with the following modifications:

  • The default URL is prepended to a URL which starts with "/"
  • The body is converted from a string with bytes.NewBufferString.

func (*Test) Nil

func (t *Test) Nil(variable interface{}, msgAndFmt ...interface{})

Nil -- Log a message and fail if the variable is not nil

func (*Test) Not

func (t *Test) Not(that bool, message string, formatters ...interface{})

Not does exactly the same thing that AttestNot does.

func (*Test) NotEqual

func (t *Test) NotEqual(var1, var2 interface{}, msgAndFmt ...interface{})

NotEqual fails the test if var1 equals var2, with the given message and formatting.

func (*Test) NotNil

func (t *Test) NotNil(variable interface{}, msg string, formatters ...interface{})

NotNil -- Log a message and fail if the variable is nil. The explanatory message is not optional for this function. If the explanatory message were not provided, the default would be "nil was expected to not be nil" which isn't very descriptive.

func (*Test) NotSimilarTo

func (t *Test) NotSimilarTo(var1, var2 interface{}, msgAndFmt ...interface{})

NotSimilarTo does the opposite of Compares/SimilarTo, the same as DoesNotCompare

func (*Test) Positive

func (t *Test) Positive(variable interface{}, msgAndFmt ...interface{})

Positive -- log a message and fail if variable is negative or zero.

func (*Test) ResponseOK

func (t *Test) ResponseOK(response *http.Response, msgAndFmt ...interface{})

ResponseOK passes the test if the status code of the given response is less than 400

func (*Test) SimilarTo

func (t *Test) SimilarTo(var1, var2 interface{}, msgAndFmt ...interface{})

SimilarTo is a semantic mirror of "Compares".

func (*Test) StopIf

func (t *Test) StopIf(err error, msgAndFmt ...interface{})

StopIf -- Fail the test and stop running it if an error is present, with optional message.

func (*Test) That

func (t *Test) That(boolean bool, message string, formatters ...interface{})

That mirrors the functionality of Attest.

func (*Test) TypeIs

func (t *Test) TypeIs(typestring string, value interface{}, msgAndFmt ...interface{})

TypeIs fails the test if the type of the value does not match the typestring, as determined by fmt.Sprintf("%T"). For example, a "Test" struct from the "attest" package (this one), would have the type "attest.Test".

func (*Test) TypeIsNot

func (t *Test) TypeIsNot(typestring string, value interface{}, msgAndFmt ...interface{})

TypeIsNot is the inverse of TypeIs; it fails the test if the type of value matches the typestring.

Jump to

Keyboard shortcuts

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