Help us shape the future of Go! Take the 2026 Go Developer Survey

expect

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2015 License: MIT Imports: 14 Imported by: 0

README

Expect

A library to help you write tests in Go.

What's wrong with Go's built-in testing package? Not much, except it tends to lead to verbose code. Expect runs within go test but provides a different syntax for specifying expectations.

Example

import (
  "testing"
  . "github.com/karlseguin/expect"
)

type CalculatorTests struct{}

func Test_Caculator(t *testing.T) {
  Expectify(new(CalculatorTests), t)
}

func (_ CalculatorTests) AddsTwoNumbers() {
  c := new(Calculator)
  Expect(c.Add(4, 8)).To.Equal(12)
  Expect(c.Add(10, 2)).Greater.Than(11)
  Expect(c.Add(10, 2)).LessOrEqual.To(12)
  Expect(c.Add(10, 2)).Not.Greater.Than(9000)
  Expect(c.Add(1, 1)).Not.To.Equal(3)

  //OR

  Expect(c.Add(4.8)).ToEqual(12)
  Expect(c.Add(10, 2)).GreaterThan(11)
  Expect(c.Add(10, 2)).LessOrEqualTo(12)
  Expect(c.Add(10, 2)).Not.GreaterThan(9000)
  Expect(c.Add(1, 1)).Not.ToEqual(3)
}

You can also use Skip(format, args...) and Fail(format, args...) to either skip a test or cause a test to fail.

Running

Run tests as you normally would via go test. However, to run specific tests, use the -m flag, which will do a case-insensitive regular expression match.

go test -m AddsTwo

Expectations

Two similar syntaxes of expectations are supported

  • To.Equal(x) or ToEqual(x)
  • Greater.Than(x) or GreaterThan(x)
  • GreaterOrEqual.To(x) or GreaterOrEqualTo(x)
  • Less.Than(x) or LessThan(x)
  • LessOrEqual.To(x) or LessOrEqualTo(x)

All expectations can be reversed by starting the chain with Not.:

  • Not.To.Equal(x) or Not.ToEqual(x)
  • Not.Greater.Than(x) or Not.GreaterThan(x)
  • Not.GreaterOrEqual.To(x) or Not.GreaterOrEqualTo(x)
  • Not.Less.Than(x) or Not.LessThan(x)
  • Not.LessOrEqual.To(x) or Not.LessOrEqualTo(x)
Eql

The Equal method is strict. This will fail:

  //fails
  Expect(uint32(449)).To.Equal(449)

Eql can be used to do implicit type conversion for common types (notably between the various integer types, as well as []byte <-> string).

  //passes
  Expect(uint32(449)).To.Eql(449)
  Expect([]byte{65, 66}).To.Eql("AB")
JSON

Expect exposes a JSON helper:

Expect(`{"spice":"must flow"}`).To.Equal(JSON(`
{
  "spice": "must flow"
}`))

The helper makes it possible to write a expectations which ignore white spaces and are thus easier to write, read and maintain. Internally, when the JSON helper is used, both values (actual and expected) are unmarshalled using the encoding/json library (essentially converted to an map[string]interface{}) and a then compared in this form.

Contains

To.Contain works with strings, arrays, slices and maps. For arrays and slices, only individual values are matched. For example:

Expect([]int{1,2,3}).To.Contain([]int{1,2})

will, sadly, not work.

The exception to this is for strings and []byte. These work with either a single value or an array (they use the stdlib's strings.Contains and bytes.Contains).

Additional Information

You can add extra information to an error by using the Message(format string, args ...interface{}) function on an expectation:

Expect(res.Code).To.Equal(404).Message("path: %s", path)

This can be useful when you're testing the same code against different inputs (probably in a for loop).

Multiple Values

Expect throws away all but the first value. This is convenient when a method returns an error which you don't care to test:

Expect(ioutil.ReadFile("blah")).To.Equal([]byte{1, 2, 3, 4})

However, using To.Equal multiple values can be provided:

Expect(1, true, "a").To.Equal(1, true, "a")

stdout

Go's testing package has no hooks into its reporting. Expect takes the drastic step of occasionally silencing os.Stdout, which many packages uses (such as fmt.Print). However, within your test, os.Stdout will work.

If you print anything outside of your test, say during init, it'll likely be silenced by Expect. You can disable this behavior with the -vv flag (use -v and -vv in combination to change the behavior of both Expect and Go's library)

Mixing with *testing.T

Since Expect runs within go test, you can mix Expect style tests with traditional Go tests. To do this, you'll probably want to run your tests with -vv (see stdout section above). Even without -vv, you will get the proper return code (!= 0 on failure).

This also means that go test features, such as -cover, work with Expect. However, Expect tests cannot be run in parallel.

Advanced Patterns

Since tests are organized within a class, there are patterns you can used for tests which require special care. For example, unexported methods can be used for helpers without conflicting with other helpers:

func (ct *CalculatorTests) AddsTwoNumbers() {
  c := ct.n()
  // ...
}

func (ct *CalculatorTests) n() *Calculator {
  return &Calculator{...}
}

Futhermore, when you setup the runner, you can setup code to before or after running tests (once for all tests, not once per test):

func Test_Caculator(t *testing.T) {
  // before all tests
  Expectify(new(CalculatorTests), t)
  // after all tests
}
Before / After Each

You can intercept each run test by creating a method named Each which takes a single parameter of type func():

func (_ *CalculatorTests) Each(f func()) {
  //run code before each test
  f()
  //run code after each test
}
Global Before Each

A before each can be registered for all suites. This function will be called before any suite-specific Each.

func init() {
  BeforeEach(func() {
    //do something
  })
}

Mocks

The mock sub-package provides mock objects and buiders for common standard library components.

Work in progress

net.Conn

The MockConn lets you test both the reading and writing to a net.Conn object.

Writes

Writes sent to the mock object are captured in the Written field. Note that this is a [][]byte - it captures each write individually.

Reads

You can Read from the mock object by first priming it with data via the Reading function:

conn := mock.Conn().Reading([]byte("hello"), []byte("world"))

To drain this connection Read will have to be called twice provided a large enough buffer is provided. If the supplied buffer is too small, the mock object will behave as expected, reading what it can, returning the length read and properly handling subsequent requests to Read.

Rather than reading data, the mock object can be primed to return an error:

conn := mock.Conn().Error(errors.New("some error"))

This will cause the first call to Read to return an error

Builders

The build sub-package provides build helpers for common standard library components. Builders expose a fluent interface for setting various properties. The default object returned from a builder should be safe to use as-is.

Work in progress

*http.Request

req := build.Request().
        Method("GET").
        URLString("http://openmymind.net/test").
        Request
  • Method(method string)
  • Proto(major, minor int)
  • URL(u *url.URL)
  • URLString(url string) - panics if url isn't a valid URL
  • Path(path string) - changes the path component of the URL only
  • RawQuery(query string) - changes the rawquery component of the URL only
  • Host(host string) - changes the host component of the URL only
  • Header(key, value string) - set the specified header
  • Body(body string) - set's the request's body

Documentation

Index

Constants

View Source
const (
	Equals comparitorType = iota
	NotEqual
	LessThan
	LessThanOrEqual
	GreaterThan
	GreaterThanOrEqual
)

Variables

View Source
var (
	FailureHandler = &FailurePostHandler{}
	SuccessHandler = &SuccessPostHandler{}
)
View Source
var (
	Comparitors = map[reflect.Kind]map[comparitorType]resolver{
		reflect.Int64: map[comparitorType]resolver{
			LessThan: func(a, b interface{}) bool { return a.(int64) < b.(int64) },
		},
		reflect.Uint64: map[comparitorType]resolver{
			LessThan: func(a, b interface{}) bool { return a.(uint64) < b.(uint64) },
		},
		reflect.Float32: map[comparitorType]resolver{
			LessThan: func(a, b interface{}) bool { return a.(float32) < b.(float32) },
		},
		reflect.Float64: map[comparitorType]resolver{
			LessThan: func(a, b interface{}) bool { return a.(float64) < b.(float64) },
		},
	}
)
View Source
var Errorf = func(format string, args ...interface{}) {
	runner.Errorf(format, args...)
}
View Source
var NotNil = struct{}{}

Functions

func BeforeEach

func BeforeEach(f func())

func EqualsComparitor

func EqualsComparitor(k reflect.Kind, a, b interface{}) bool

func Expectify

func Expectify(suite interface{}, t *testing.T)

func Fail

func Fail(format string, args ...interface{})

func GreaterOrEqualToComparitor

func GreaterOrEqualToComparitor(k reflect.Kind, a, b interface{}) bool

func GreaterThanComparitor

func GreaterThanComparitor(k reflect.Kind, a, b interface{}) bool

func IsInt

func IsInt(a interface{}) bool

func IsNil

func IsNil(a interface{}) bool

func IsNumeric

func IsNumeric(a interface{}) bool

func IsSlice

func IsSlice(a interface{}) bool

func IsString

func IsString(a interface{}) bool

func IsUint

func IsUint(a interface{}) bool

func LessThanComparitor

func LessThanComparitor(k reflect.Kind, a, b interface{}) bool

func LessThanOrEqualToComparitor

func LessThanOrEqualToComparitor(k reflect.Kind, a, b interface{}) bool

func MockConn

func MockConn() *mock.MockConn

func NotEqualsComparitor

func NotEqualsComparitor(k reflect.Kind, a, b interface{}) bool

func RequestBuilder

func RequestBuilder() *build.RequestBuilder

func SameKind

func SameKind(a, b interface{}) (reflect.Kind, bool)

func Skip

func Skip(format string, args ...interface{})

func ToInt64

func ToInt64(a, b interface{}) (interface{}, interface{})

func ToString

func ToString(a interface{}) string

func ToUint64

func ToUint64(a, b interface{}) (interface{}, interface{})

Types

type Expectation

type Expectation struct {
	Greater        *ThanAssertion
	GreaterOrEqual *ToAssertion
	Less           *ThanAssertion
	LessOrEqual    *ToAssertion
	To             *ToExpectation
	Not            *InvertedExpectation
	// contains filtered or unexported fields
}

func Expect

func Expect(actual interface{}, others ...interface{}) *Expectation

func (*Expectation) GreaterOrEqualTo

func (e *Expectation) GreaterOrEqualTo(expected interface{}) PostHandler

func (*Expectation) GreaterThan

func (e *Expectation) GreaterThan(expected interface{}) PostHandler

func (*Expectation) LessOrEqualTo

func (e *Expectation) LessOrEqualTo(expected interface{}) PostHandler

func (*Expectation) LessThan

func (e *Expectation) LessThan(expected interface{}) PostHandler

func (*Expectation) ToEql

func (e *Expectation) ToEql(expected interface{}, others ...interface{}) PostHandler

func (*Expectation) ToEqual

func (e *Expectation) ToEqual(expected interface{}, others ...interface{}) PostHandler

type Failure

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

type FailurePostHandler

type FailurePostHandler struct {
}

func (*FailurePostHandler) Message

func (h *FailurePostHandler) Message(format string, args ...interface{})

type InvertedExpectation

type InvertedExpectation struct {
	*Expectation
}

func NotExpect

func NotExpect(actual interface{}, others ...interface{}) *InvertedExpectation

type JSON

type JSON string

type PostHandler

type PostHandler interface {
	Message(format string, args ...interface{})
}

type Runner

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

func (*Runner) End

func (r *Runner) End() bool

func (*Runner) ErrorMessage

func (r *Runner) ErrorMessage(format string, args ...interface{})

func (*Runner) Errorf

func (r *Runner) Errorf(format string, args ...interface{})

func (*Runner) Passed

func (r *Runner) Passed() bool

func (*Runner) Skip

func (r *Runner) Skip(format string, args ...interface{})

func (*Runner) Start

func (r *Runner) Start(name string, typeName string) *result

type SuccessPostHandler

type SuccessPostHandler struct {
}

func (*SuccessPostHandler) Message

func (h *SuccessPostHandler) Message(format string, args ...interface{})

type ThanAssertion

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

func (*ThanAssertion) Than

func (a *ThanAssertion) Than(expected interface{}) PostHandler

type ToAssertion

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

func (*ToAssertion) To

func (a *ToAssertion) To(expected interface{}) PostHandler

type ToExpectation

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

func (*ToExpectation) Contain

func (e *ToExpectation) Contain(expected interface{}) PostHandler

func (*ToExpectation) Eql

func (e *ToExpectation) Eql(expected interface{}, others ...interface{}) PostHandler

func (*ToExpectation) Equal

func (e *ToExpectation) Equal(expected interface{}, others ...interface{}) PostHandler

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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