---
layout: default
title: Gomega
---

[Gomega](http://github.com/onsi/gomega) is a matcher/assertion library.  It is best paired with the [Ginkgo](http://github.com/onsi/ginkgo) BDD test framework, but can be adapted for use in other contexts too.

---

## Getting Gomega

Just `go get` it:

    $ go get github.com/onsi/gomega

---

## Using Gomega with Ginkgo

When a Gomega assertion fails, Gomega calls a `GomegaFailHandler`.  This is a function that you must provide using `gomega.RegisterFailHandler()`.

If you're using Ginkgo, all you need to do is:

    gomega.RegisterFailHandler(ginkgo.Fail)

before you start your test suite.

If you use the `ginkgo` CLI to `ginkgo bootstrap` a test suite, this hookup will be automatically generated for you.

> `GomegaFailHandler` is defined in the `types` subpackage.

---

## Using Gomega with Golang's XUnit-style Tests

Though Gomega is tailored to work best with Ginkgo it is easy to use Gomega with Golang's XUnit style tests.  Here's how:

To use Gomega with Golang's XUnit style tests:

    func TestFarmHasCow(t *testing.T) {
        RegisterTestingT(t)

        f := farm.New([]string{"Cow", "Horse"})
        Expect(f.HasCow()).To(BeTrue(), "Farm should have cow")
    }

There are two caveats:

- You **must** register the `t *testing.T` passed to your test with Gomega before you make any assertions associated with that test.  So every `Test...` function in your suite should have the `RegisterTestingT(t)` line.
- Gomega uses a global (singleton) fail handler.  This has the benefit that you don't need to pass the fail handler down to each test, but does mean that *you cannot run your XUnit style tests in parallel with Gomega*.  If you find this odious, open an issue on Github and let me know.

> Gomega tests written with Ginkgo *can* be run in parallel using the `ginkgo` CLI.  This is because Ginkgo runs its parallel specs in different *processes* whereas the default Golang test runner runs parallel tests in the *same* process.  The latter approach makes your test suite susceptible to test pollution and is avoided by Ginkgo.

---

## Making Assertions

Gomega provides two notations for making assertions.  These notations are functionally equivalent and their differences are purely aesthetic.

- When you use the `Ω` notation, your assertions look like this:

        Ω(ACTUAL).Should(Equal(EXPECTED))
        Ω(ACTUAL).ShouldNot(Equal(EXPECTED))

- When you use the `Expect` notation, your assertions look like this:

        Expect(ACTUAL).To(Equal(EXPECTED))
        Expect(ACTUAL).NotTo(Equal(EXPECTED))
        Expect(ACTUAL).ToNot(Equal(EXPECTED))

On OS X the `Ω` character should be easy to type, it is usually just option-z: `⌥z`.

On the left hand side, you can pass anything you want in to `Ω` and `Expect` for `ACTUAL`.  On the right hand side you must pass an object that satisfies the `GomegaMatcher` interface.  Gomega's matchers (e.g. `Equal(EXPECTED)`) are simply functions that create and initialize an appropriate `GomegaMatcher` object.

> The `GomegaMatcher` interface is pretty simple and is discussed in the [custom matchers](#adding-your-own-matchers) section.  It is defined in the `types` subpackage.

### Handling Errors

It is a common pattern, in Golang, for functions and methods to return two things - a value and an error.  For example:

    func DoSomethingHard() (string, error) {
        ...
    }

To assert on the return value of such a method you might write a test that looks like this:

    result, err := DoSomethingHard()
    Ω(err).ShouldNot(HaveOccurred())
    Ω(result).Should(Equal("foo"))

Gomega streamlines this very common use case.  Both `Ω` and `Expect` accept *multiple* arguments.  The first argument is passed to the matcher, and the match only succeeds if *all* subsequent arguments are `nil` or zero-valued.  With this, we can rewrite the above example as:

    Ω(DoSomethingHard()).Should(Equal("foo"))

This will only pass if the return value of `DoSomethingHard()` is `("foo", nil)`.

Additionally, if you call a function with a single `error` return value you can use the `Succeed` matcher to assert the function has returned without error.  So for a function of the form:

    func DoSomethingSimple() error {
        ...
    }

You can either write:

    err := DoSomethingSimple()
    Ω(err).ShouldNot(HaveOccurred())

Or you can write:

    Ω(DoSomethingSimple()).Should(Succeed())

> You should not use a function with multiple return values (like `DoSomethingHard`) with `Succeed`.  Matchers are only passed the *first* value provided to `Ω`/`Expect`, the subsequent arguments are handled by `Ω` and `Expect` as outlined above.  As a result of this behavior `Ω(DoSomethingHard()).ShouldNot(Succeed())` would never pass.

### Annotating Assertions

You can annotate any assertion by passing a format string (and optional inputs to format) after the `GomegaMatcher`:

    Ω(ACTUAL).Should(Equal(EXPECTED), "My annotation %d", foo)
    Ω(ACTUAL).ShouldNot(Equal(EXPECTED), "My annotation %d", foo)
    Expect(ACTUAL).To(Equal(EXPECTED), "My annotation %d", foo)
    Expect(ACTUAL).NotTo(Equal(EXPECTED), "My annotation %d", foo)
    Expect(ACTUAL).ToNot(Equal(EXPECTED), "My annotation %d", foo)

The format string and inputs will be passed to `fmt.Sprintf(...)`.  If the assertion fails, Gomega will print your annotation alongside its standard failure message.

This is useful in cases where the standard failure message lacks context.  For example, if the following assertion fails:

    Ω(SprocketsAreLeaky()).Should(BeFalse())

Gomega will output:

    Expected
      <bool>: true
    to be false

But this assertion:

    Ω(SprocketsAreLeaky()).Should(BeFalse(), "Sprockets shouldn't leak")

Will offer the more helpful output:

    Sprockets shouldn't leak
    Expected
      <bool>: true
    to be false


### Adjusting Output

When a failure occurs, Gomega prints out a recursive description of the objects involved in the failed assertion.  This output can be very verbose, but Gomega's philosophy is to give as much output as possible to aid in identifying the root cause of a test failure.

These recursive object renditions are performed by the `format` subpackage.  `format` provides some globally adjustable settings to tune Gomega's output:

- `format.MaxDepth = 10`: Gomega will recursively traverse nested data structures as it produces output.  By default the maximum depth of this recursion is set to `10` you can adjust this to see deeper or shallower representations of objects.
- `format.UseStringerRepresentation = false`: Gomega does *not* call `String` or `GoString` on objects that satisfy the `Stringer` and `GoStringer` interfaces.  Oftentimes such representations, while more human readable, do not contain all the relevant information associated with an object thereby making it harder to understand why a test might be failing.  If you'd rather see the output of `String` or `GoString` set this property to `true`.


> For a tricky example of why `format.UseStringerRepresentation = false` is your friend, check out issue [#37](https://github.com/onsi/gomega/issues/37).

- `format.PrintContextObjects = false`: Gomega by default will not print the content of objects satisfying the context.Context interface, due to too much output. If you want to enable displaying that content, set this property to `true`.

If you want to use Gomega's recursive object description in your own code you can call into the `format` package directly:

    fmt.Println(format.Object(theThingYouWantToPrint, 1))

---

## Making Asynchronous Assertions

Gomega has support for making *asynchronous* assertions.  There are two functions that provide this support: `Eventually` and `Consistently`.

### Eventually

`Eventually` checks that an assertion *eventually* passes.  It does this by polling its argument until the matcher succeeds.

For example:

    Eventually(func() []int {
        return thing.SliceImMonitoring
    }).Should(HaveLen(2))

    Eventually(func() string {
        return thing.Status
    }).ShouldNot(Equal("Stuck Waiting"))

`Eventually` will poll the passed in function (which must have zero-arguments and at least one return value) repeatedly and check the return value against the `GomegaMatcher`.  `Eventually` then blocks until the match succeeds or until a timeout interval has elapsed.

The default value for the timeout is 1 second and the default value for the polling interval is 10 milliseconds.  You can change these values by passing them in just after your function:

    Eventually(func() []int {
        return thing.SliceImMonitoring
    }, TIMEOUT, POLLING_INTERVAL).Should(HaveLen(2))

These can be passed in as `time.Duration`s, string representations of a `time.Duration` (e.g. `"2s"`) or `float64` values (in which case they are interpreted as seconds).

`Eventually` is especially handy when writing integration tests against asynchronous services or components:

    externalProcess.DoSomethingAmazing()
    Eventually(func() bool {
        return somethingAmazingHappened()
    }).Should(BeTrue())

The function that you pass to `Eventually` can have more than one return value.  In that case, `Eventually` passes the first return value to the matcher and asserts that all other return values are `nil` or zero-valued.  This allows you to use `Eventually` with functions that return a value and an error -- a common pattern in Go.  For example, say you have a method on an object named `FetchNameFromNetwork()` that returns a string value and an error.  Given an instance then you could simply write:

    Eventually(myInstance.FetchNameFromNetwork).Should(Equal("archibald"))

If the argument to `Eventually` is *not* a function, `Eventually` will simply run the matcher against the argument.  This works really well with the Gomega matchers geared towards working with channels:

    Eventually(channel).Should(BeClosed())
    Eventually(channel).Should(Receive())

This also pairs well with `gexec`'s `Session` command wrappers and `gbyte`'s `Buffer`s:

    Eventually(session).Should(gexec.Exit(0))
    //the wrapped command should exit with status 0, eventually

    Eventually(buffer).Should(Say("something matching this regexp"))
    Eventually(session.Out).Should(Say("Splines reticulated"))

> Note that `Eventually(slice).Should(HaveLen(N))` probably won't do what you think it should -- `Eventually` will be passed a pointer to the slice, yes, but if the slice is being `append`ed to (as in: `slice := append(slice, ...)`) Go will generate a new pointer and the pointer passed to `Eventually` will not contain the new elements.  In such cases you should always pass `Eventually` a function that, when polled, returns the slice.
> As with synchronous assertions, you can annotate asynchronous assertions by passing a format string and optional inputs after the `GomegaMatcher`.

### Consistently

`Consistently` checks that an assertion passes for a period of time.  It does this by polling its argument repeatedly during the period. It fails if the matcher ever fails during that period.

For example:

    Consistently(func() []int {
        return thing.MemoryUsage()
    }).Should(BeNumerically("<", 10))

`Consistently` will poll the passed in function (which must have zero-arguments and at least one return value) repeatedly and check the return value against the `GomegaMatcher`.  `Consistently` blocks and only returns when the desired duration has elapsed or if the matcher fails.  The default value for the wait-duration is 100 milliseconds.  The default polling interval is 10 milliseconds.  Like `Eventually`, you can change these values by passing them in just after your function:


    Consistently(func() []int {
        return thing.MemoryUsage()
    }, DURATION, POLLING_INTERVAL).Should(BeNumerically("<", 10))

As with `Eventually`, these can be `time.Duration`s, string representations of a `time.Duration` (e.g. `"200ms"`) or `float64`s that are interpreted as seconds.

`Consistently` tries to capture the notion that something "does not eventually" happen.  A common use-case is to assert that no goroutine writes to a channel for a period of time.  If you pass `Consistently` an argument that is not a function, it simply passes that argument to the matcher.  So we can assert that:

    Consistently(channel).ShouldNot(Receive())

To assert that nothing gets sent to a channel.

As with `Eventually`, if you pass `Consistently` a function that returns more than one value, it will pass the first value to the matcher and assert that all other values are `nil` or zero-valued.

> Developers often try to use `runtime.Gosched()` to nudge background goroutines to run.  This can lead to flaky tests as it is not deterministic that a given goroutine will run during the `Gosched`.  `Consistently` is particularly handy in these cases: it polls for 100ms which is typically more than enough time for all your Goroutines to run.  Yes, this is basically like putting a time.Sleep() in your tests... Sometimes, when making negative assertions in a concurrent world, that's the best you can do!

### Modifying Default Intervals

By default, `Eventually` will poll every 10 milliseconds for up to 1 second and `Consistently` will monitor every 10 milliseconds for up to 100 milliseconds.  You can modify these defaults across your test suite with:

    SetDefaultEventuallyTimeout(t time.Duration)
    SetDefaultEventuallyPollingInterval(t time.Duration)
    SetDefaultConsistentlyDuration(t time.Duration)
    SetDefaultConsistentlyPollingInterval(t time.Duration)

---

## Making Assertions in Helper Functions

While writing [custom matchers](#adding-your-own-matchers) is an expressive way to make assertions against your code, it is often more convenient to write one-off helper functions like so:

    var _ = Describe("Turbo-encabulator", func() {
        ...
        assertTurboEncabulatorContains(components ...string) {
            teComponents, err := turboEncabulator.GetComponents()
            Expect(err).NotTo(HaveOccurred())

            Expect(teComponents).To(HaveLen(components))
            for _, component := range components {
                Expect(teComponents).To(ContainElement(component))
            }
        }

        It("should have components", func() {
            assertTurboEncabulatorContains("semi-boloid slots", "grammeters")
        })
    })

This makes your tests more expressive and reduces boilerplate.  However, when an assertion in the helper fails the line numbers provided by Gomega are unhelpful.  Instead of pointing you to the line in your test that failed, they point you the line in the helper.

To get around this, Gomega provides versions of `Expect`, `Eventually` and `Consistently` named `ExpectWithOffset`, `EventuallyWithOffset` and `ConsistentlyWithOffset` that allow you to specify an *offset* in the call stack.  The offset is the first argument to these functions.

With this, we can rewrite our helper as:

    assertTurboEncabulatorContains(components ...string) {
        teComponents, err := turboEncabulator.GetComponents()
        ExpectWithOffset(1, err).NotTo(HaveOccurred())

        ExpectWithOffset(1, teComponents).To(HaveLen(components))
        for _, component := range components {
          ExpectWithOffset(1, teComponents).To(ContainElement(component))
        }
    }

Now, failed assertions will point to the correct call to the helper in the test.

---

## Provided Matchers

Gomega comes with a bunch of `GomegaMatcher`s.  They're all documented here.  If there's one you'd like to see written either [send a pull request or open an issue](http://github.com/onsi/gomega).

A number of community-supported matchers have appeared as well.  A list is maintained on the Gomega [wiki](https://github.com/onsi/gomega/wiki).

These docs only go over the positive assertion case (`Should`), the negative case (`ShouldNot`) is simply the negation of the positive case.  They also use the `Ω` notation, but - as mentioned above - the `Expect` notation is equivalent.

### Asserting Equivalence

#### Equal(expected interface{})

    Ω(ACTUAL).Should(Equal(EXPECTED))

uses [`reflect.DeepEqual`](http://golang.org/pkg/reflect#deepequal) to compare `ACTUAL` with `EXPECTED`.

`reflect.DeepEqual` is awesome.  It will use `==` when appropriate (e.g. when comparing primitives) but will recursively dig into maps, slices, arrays, and even your own structs to ensure deep equality.  `reflect.DeepEqual`, however, is strict about comparing types.  Both `ACTUAL` and `EXPECTED` *must* have the same type.  If you want to compare across different types (e.g. if you've defined a type alias) you should use `BeEquivalentTo`.

It is an error for both `ACTUAL` and `EXPECTED` to be nil, you should use `BeNil()` instead.

When both `ACTUAL` and `EXPECTED` are a very long strings, it will attempt to pretty-print the diff and display exactly where they differ.

> For asserting equality between numbers of different types, you'll want to use the [`BeNumerically()`](#benumericallycomparator-string-compareto-interface) matcher.

#### BeEquivalentTo(expected interface{})

    Ω(ACTUAL).Should(BeEquivalentTo(EXPECTED))

Like `Equal`, `BeEquivalentTo` uses `reflect.DeepEqual` to compare `ACTUAL` with `EXPECTED`.  Unlike `Equal`, however, `BeEquivalentTo` will first convert `ACTUAL`'s type to that of `EXPECTED` before making the comparison with `reflect.DeepEqual`.

This means that `BeEquivalentTo` will successfully match equivalent values of different types.  This is particularly useful, for example, with type aliases:

    type FoodSrce string

    Ω(FoodSrce("Cheeseboard Pizza")
     ).Should(Equal("Cheeseboard Pizza")) //will fail
    Ω(FoodSrce("Cheeseboard Pizza")
     ).Should(BeEquivalentTo("Cheeseboard Pizza")) //will pass

As with `Equal` it is an error for both `ACTUAL` and `EXPECTED` to be nil, you should use `BeNil()` instead.

As a rule, you **should not** use `BeEquivalentTo` with numbers.  Both of the following assertions are true:

    Ω(5.1).Should(BeEquivalentTo(5))
    Ω(5).ShouldNot(BeEquivalentTo(5.1))

the first assertion passes because 5.1 will be cast to an integer and will get rounded down!  Such false positives are terrible and should be avoided.  Use [`BeNumerically()`](#benumericallycomparator-string-compareto-interface) to compare numbers instead.

#### BeIdenticalTo(expected interface{})

    Ω(ACTUAL).Should(BeIdenticalTo(EXPECTED))

Like `Equal`, `BeIdenticalTo` compares `ACTUAL` to `EXPECTED` for equality. Unlike `Equal`, however, it uses `==` to compare values. In practice, this means that primitive values like strings, integers and floats are identical to, as well as pointers to values.

`BeIdenticalTo` is most useful when you want to assert that two pointers point to the exact same location in memory.

As with `Equal` it is an error for both `ACTUAL` and `EXPECTED` to be nil, you should use `BeNil()` instead.

#### BeAssignableToTypeOf(expected interface)

    Ω(ACTUAL).Should(BeAssignableToTypeOf(EXPECTED interface))

succeeds if `ACTUAL` is a type that can be assigned to a variable with the same type as `EXPECTED`.  It is an error for either `ACTUAL` or `EXPECTED` to be `nil`.

### Asserting Presence

#### BeNil()

    Ω(ACTUAL).Should(BeNil())

succeeds if `ACTUAL` is, in fact, `nil`.

#### BeZero()

    Ω(ACTUAL).Should(BeZero())

succeeds if `ACTUAL` is the zero value for its type *or* if `ACTUAL` is `nil`.

### Asserting Truthiness

#### BeTrue()

    Ω(ACTUAL).Should(BeTrue())

succeeds if `ACTUAL` is `bool` typed and has the value `true`.  It is an error for `ACTUAL` to not be a `bool`.

> Some matcher libraries have a notion of "truthiness" to assert that an object is present.  Gomega is strict, and `BeTrue()` only works with `bool`s.  You can use `Ω(ACTUAL).ShouldNot(BeZero())` or `Ω(ACTUAL).ShouldNot(BeNil())` to verify object presence.

#### BeFalse()

    Ω(ACTUAL).Should(BeFalse())

succeeds if `ACTUAL` is `bool` typed and has the value `false`.  It is an error for `ACTUAL` to not be a `bool`.

### Asserting on Errors

#### HaveOccurred()

    Ω(ACTUAL).Should(HaveOccurred())

succeeds if `ACTUAL` is a non-nil `error`.  Thus, the typical Go error checking pattern looks like:

    err := SomethingThatMightFail()
    Ω(err).ShouldNot(HaveOccurred())

#### Succeed()

    Ω(ACTUAL).Should(Succeed())

succeeds if `ACTUAL` is `nil`.  The intended usage is

    Ω(FUNCTION()).Should(Succeed())

where `FUNCTION()` is a function call that returns an error-type as its *first or only* return value.  See [Handling Errors](#handling-errors) for a more detailed discussion.

#### MatchError(expected interface{})

    Ω(ACTUAL).Should(MatchError(EXPECTED))

succeeds if `ACTUAL` is a non-nil `error` that matches `EXPECTED`.  `EXPECTED` can be a string, in which case `ACTUAL.Error()` will be compared against `EXPECTED`.  `EXPECTED` can also be an error, in which case `ACTUAL` and `ERROR` are compared via `reflect.DeepEqual`. Alternatively, `EXPECTED` can be a matcher, in which case it is tested against `ACTUAL.Error()`. Any other type for `EXPECTED` is an error.

### Working with Channels

#### BeClosed()

    Ω(ACTUAL).Should(BeClosed())

succeeds if `ACTUAL` is a closed channel. It is an error to pass a non-channel to `BeClosed`, it is also an error to pass `nil`.

In order to check whether or not the channel is closed, Gomega must try to read from the channel (even in the `ShouldNot(BeClosed())` case).  You should keep this in mind if you wish to make subsequent assertions about values coming down the channel.

Also, if you are testing that a *buffered* channel is closed you must first read all values out of the channel before asserting that it is closed (it is not possible to detect that a buffered-channel has been closed until all its buffered values are read).

Finally, as a corollary: it is an error to check whether or not a send-only channel is closed.

#### Receive()

    Ω(ACTUAL).Should(Receive(<optionalPointer>))

succeeds if there is a message to be received on actual. Actual must be a channel (and cannot be a send-only channel) -- anything else is an error.

`Receive` returns *immediately*.  It *never* blocks:

- If there is nothing on the channel `c` then `Ω(c).Should(Receive())` will fail and `Ω(c).ShouldNot(Receive())` will pass.
- If there is something on the channel `c` ready to be read, then `Ω(c).Should(Receive())` will pass and `Ω(c).ShouldNot(Receive())` will fail.
- If the channel `c` is closed then `Ω(c).Should(Receive())` will fail and `Ω(c).ShouldNot(Receive())` will pass.

If you have a go-routine running in the background that will write to channel `c`, for example:

    go func() {
        time.Sleep(100 * time.Millisecond)
        c <- true
    }()

you can assert that `c` receives something (anything!) eventually:

    Eventually(c).Should(Receive())

This will timeout if nothing gets sent to `c` (you can modify the timeout interval as you normally do with `Eventually`).

A similar use-case is to assert that no go-routine writes to a channel (for a period of time).  You can do this with `Consistently`:

    Consistently(c).ShouldNot(Receive())

`Receive` also allows you to make assertions on the received object.  You do this by passing `Receive` a matcher:

    Eventually(c).Should(Receive(Equal("foo")))

This assertion will only succeed if `c` receives an object *and* that object satisfies `Equal("foo")`.  Note that `Eventually` will continually poll `c` until this condition is met.  If there are objects coming down the channel that do not satisfy the passed in matcher, they will be pulled off and discarded until an object that *does* satisfy the matcher is received.

In addition, there are occasions when you need to grab the object sent down the channel (e.g. to make several assertions against the object).  To do this, you can ask the `Receive` matcher for the value passed to the channel by passing it a pointer to a variable of the appropriate type:

    var receivedBagel Bagel
    Eventually(bagelChan).Should(Receive(&receivedBagel))
    Ω(receivedBagel.Contents()).Should(ContainElement("cream cheese"))
    Ω(receivedBagel.Kind()).Should(Equal("sesame"))

Of course, this could have been written as `receivedBagel := <-bagelChan` - however using `Receive` makes it easy to avoid hanging the test suite should nothing ever come down the channel.

Finally, `Receive` *never* blocks.  `Eventually(c).Should(Receive())` repeatedly polls `c` in a non-blocking fashion.  That means that you cannot use this pattern to verify that a *non-blocking send* has occurred on the channel - [more details at this GitHub issue](https://github.com/onsi/gomega/issues/82).

#### BeSent(value interface{})

    Ω(ACTUAL).Should(BeSent(VALUE))

attempts to send `VALUE` to the channel `ACTUAL` without blocking.  It succeeds if this is possible.

`ACTUAL` must be a channel (and cannot be a receive-only channel) that can be sent the type of the `VALUE` passed into `BeSent` -- anything else is an error. In addition, `ACTUAL` must not be closed.

`BeSent` never blocks:

- If the channel `c` is not ready to receive then `Ω(c).Should(BeSent("foo"))` will fail immediately.
- If the channel `c` is eventually ready to receive then `Eventually(c).Should(BeSent("foo"))` will succeed... presuming the channel becomes ready to receive before `Eventually`'s timeout.
- If the channel `c` is closed then `Ω(c).Should(BeSent("foo"))` and `Ω(c).ShouldNot(BeSent("foo"))` will both fail immediately.

Of course, `VALUE` is actually sent to the channel.  The point of `BeSent` is less to make an assertion about the availability of the channel (which is typically an implementation detail that your test should not be concerned with). Rather, the point of `BeSent` is to make it possible to easily and expressively write tests that can timeout on blocked channel sends.

### Working with files

#### BeAnExistingFile

    Ω(ACTUAL).Should(BeAnExistingFile())

succeeds if a file located at `ACTUAL` exists.

`ACTUAL` must be a string representing the filepath.

#### BeARegularFile

    Ω(ACTUAL).Should(BeARegularFile())

succeeds IFF a file located at `ACTUAL` exists and is a regular file.

`ACTUAL` must be a string representing the filepath.

#### BeADirectory

    Ω(ACTUAL).Should(BeADirectory())

succeeds IFF a file is located at `ACTUAL` exists and is a directory.

`ACTUAL` must be a string representing the filepath.

### Working with Strings, JSON and YAML

#### ContainSubstring(substr string, args ...interface{})

    Ω(ACTUAL).Should(ContainSubstring(STRING, ARGS...))

succeeds if `ACTUAL` contains the substring generated by:

    fmt.Sprintf(STRING, ARGS...)

`ACTUAL` must either be a `string`, `[]byte` or a `Stringer` (a type implementing the `String()` method).  Any other input is an error.

> Note, of course, that the `ARGS...` are not required.  They are simply a convenience to allow you to build up strings programmatically inline in the matcher.

#### HavePrefix(prefix string, args ...interface{})

    Ω(ACTUAL).Should(HavePrefix(STRING, ARGS...))

succeeds if `ACTUAL` has the string prefix generated by:

    fmt.Sprintf(STRING, ARGS...)

`ACTUAL` must either be a `string`, `[]byte` or a `Stringer` (a type implementing the `String()` method).  Any other input is an error.

> Note, of course, that the `ARGS...` are not required.  They are simply a convenience to allow you to build up strings programmatically inline in the matcher.

#### HaveSuffix(suffix string, args ...interface{})

    Ω(ACTUAL).Should(HaveSuffix(STRING, ARGS...))

succeeds if `ACTUAL` has the string suffix generated by:

    fmt.Sprintf(STRING, ARGS...)

`ACTUAL` must either be a `string`, `[]byte` or a `Stringer` (a type implementing the `String()` method).  Any other input is an error.

> Note, of course, that the `ARGS...` are not required.  They are simply a convenience to allow you to build up strings programmatically inline in the matcher.

#### MatchRegexp(regexp string, args ...interface{})

    Ω(ACTUAL).Should(MatchRegexp(STRING, ARGS...))

succeeds if `ACTUAL` is matched by the regular expression string generated by:

    fmt.Sprintf(STRING, ARGS...)

`ACTUAL` must either be a `string`, `[]byte` or a `Stringer` (a type implementing the `String()` method).  Any other input is an error.  It is also an error for the regular expression to fail to compile.

> Note, of course, that the `ARGS...` are not required.  They are simply a convenience to allow you to build up strings programmatically inline in the matcher.

#### MatchJSON(json interface{})

    Ω(ACTUAL).Should(MatchJSON(EXPECTED))

Both `ACTUAL` and `EXPECTED` must be a `string`, `[]byte` or a `Stringer`.  `MatchJSON` succeeds if both `ACTUAL` and `EXPECTED` are JSON representations of the same object.  This is verified by parsing both `ACTUAL` and `EXPECTED` and then asserting equality on the resulting objects with `reflect.DeepEqual`.  By doing this `MatchJSON` avoids any issues related to white space, formatting, and key-ordering.

It is an error for either `ACTUAL` or `EXPECTED` to be invalid JSON.

#### MatchYAML(yaml interface{})

    Ω(ACTUAL).Should(MatchYAML(EXPECTED))

Both `ACTUAL` and `EXPECTED` must be a `string`, `[]byte` or a `Stringer`.  `MatchYAML` succeeds if both `ACTUAL` and `EXPECTED` are YAML representations of the same object.  This is verified by parsing both `ACTUAL` and `EXPECTED` and then asserting equality on the resulting objects with `reflect.DeepEqual`.  By doing this `MatchYAML` avoids any issues related to white space, formatting, and key-ordering.

It is an error for either `ACTUAL` or `EXPECTED` to be invalid YAML.

### Working with Collections

#### BeEmpty()

    Ω(ACTUAL).Should(BeEmpty())

succeeds if `ACTUAL` is, in fact, empty. `ACTUAL` must be of type `string`, `array`, `map`, `chan`, or `slice`.  It is an error for it to have any other type.

#### HaveLen(count int)

    Ω(ACTUAL).Should(HaveLen(INT))

succeeds if the length of `ACTUAL` is `INT`. `ACTUAL` must be of type `string`, `array`, `map`, `chan`, or `slice`.  It is an error for it to have any other type.

#### HaveCap(count int)

    Ω(ACTUAL).Should(HaveCap(INT))

succeeds if the capacity of `ACTUAL` is `INT`. `ACTUAL` must be of type `array`, `chan`, or `slice`.  It is an error for it to have any other type.

#### ContainElement(element interface{})

    Ω(ACTUAL).Should(ContainElement(ELEMENT))

succeeds if `ACTUAL` contains an element that equals `ELEMENT`.  `ACTUAL` must be an `array`, `slice`, or `map` -- anything else is an error.  For `map`s `ContainElement` searches through the map's values (not keys!).

By default `ContainElement()` uses the `Equal()` matcher under the hood to assert equality between `ACTUAL`'s elements and `ELEMENT`.  You can change this, however, by passing `ContainElement` a `GomegaMatcher`. For example, to check that a slice of strings has an element that matches a substring:

    Ω([]string{"Foo", "FooBar"}
     ).Should(ContainElement(ContainSubstring("Bar")))

#### ConsistOf(element ...interface{})

    Ω(ACTUAL).Should(ConsistOf(ELEMENT1, ELEMENT2, ELEMENT3, ...))

or

    Ω(ACTUAL).Should(
        ConsistOf([]SOME_TYPE{ELEMENT1, ELEMENT2, ELEMENT3, ...}))

succeeds if `ACTUAL` contains precisely the elements passed into the matcher. The ordering of the elements does not matter.

By default `ConsistOf()` uses `Equal()` to match the elements, however custom matchers can be passed in instead.  Here are some examples:

    Ω([]string{"Foo", "FooBar"}).Should(ConsistOf("FooBar", "Foo"))
    Ω([]string{"Foo", "FooBar"}).Should(ConsistOf(ContainSubstring("Bar"), "Foo"))
    Ω([]string{"Foo", "FooBar"}).Should(ConsistOf(ContainSubstring("Foo"), ContainSubstring("Foo")))

Actual must be an `array`, `slice` or `map`.  For maps, `ConsistOf` matches against the `map`'s values.

You typically pass variadic arguments to `ConsistOf` (as in the examples above).  However, if you need to pass in a slice you can provided that it
is the only element passed in to `ConsistOf`:

    Ω([]string{"Foo", "FooBar"}).Should(ConsistOf([]string{"FooBar", "Foo"}))

Note that Go's type system does not allow you to write this as `ConsistOf([]string{"FooBar", "Foo"}...)` as `[]string` and `[]interface{}` are different types - hence the need for this special rule.


#### HaveKey(key interface{})

    Ω(ACTUAL).Should(HaveKey(KEY))

succeeds if `ACTUAL` is a map with a key that equals `KEY`.  It is an error for `ACTUAL` to not be a `map`.

By default `HaveKey()` uses the `Equal()` matcher under the hood to assert equality between `ACTUAL`'s keys and `KEY`.  You can change this, however, by passing `HaveKey` a `GomegaMatcher`. For example, to check that a map has a key that matches a regular expression:

    Ω(map[string]string{"Foo": "Bar", "BazFoo": "Duck"}).Should(HaveKey(MatchRegexp(`.+Foo$`)))

#### HaveKeyWithValue(key interface{}, value interface{})

    Ω(ACTUAL).Should(HaveKeyWithValue(KEY, VALUE))

succeeds if `ACTUAL` is a map with a key that equals `KEY` mapping to a value that equals `VALUE`.  It is an error for `ACTUAL` to not be a `map`.

By default `HaveKeyWithValue()` uses the `Equal()` matcher under the hood to assert equality between `ACTUAL`'s keys and `KEY` and between the associated value and `VALUE`.  You can change this, however, by passing `HaveKeyWithValue` a `GomegaMatcher` for either parameter. For example, to check that a map has a key that matches a regular expression and which is also associated with a value that passes some numerical threshold:

    Ω(map[string]int{"Foo": 3, "BazFoo": 4}).Should(HaveKeyWithValue(MatchRegexp(`.+Foo$`), BeNumerically(">", 3)))

### Working with Numbers and Times

#### BeNumerically(comparator string, compareTo ...interface{})

    Ω(ACTUAL).Should(BeNumerically(COMPARATOR_STRING, EXPECTED, <THRESHOLD>))

performs numerical assertions in a type-agnostic way.  `ACTUAL` and `EXPECTED` should be numbers, though the specific type of number is irrelevant (`float32`, `float64`, `uint8`, etc...).  It is an error for `ACTUAL` or `EXPECTED` to not be a number.

There are six supported comparators:

- `Ω(ACTUAL).Should(BeNumerically("==", EXPECTED))`:
    asserts that `ACTUAL` and `EXPECTED` are numerically equal.

- `Ω(ACTUAL).Should(BeNumerically("~", EXPECTED, <THRESHOLD>))`:
    asserts that `ACTUAL` and `EXPECTED` are within `<THRESHOLD>` of one another.  By default `<THRESHOLD>` is `1e-8` but you can specify a custom value.

- `Ω(ACTUAL).Should(BeNumerically(">", EXPECTED))`:
    asserts that `ACTUAL` is greater than `EXPECTED`.

- `Ω(ACTUAL).Should(BeNumerically(">=", EXPECTED))`:
    asserts that `ACTUAL` is greater than or equal to  `EXPECTED`.

- `Ω(ACTUAL).Should(BeNumerically("<", EXPECTED))`:
    asserts that `ACTUAL` is less than `EXPECTED`.

- `Ω(ACTUAL).Should(BeNumerically("<=", EXPECTED))`:
    asserts that `ACTUAL` is less than or equal to `EXPECTED`.

Any other comparator is an error.

#### BeTemporally(comparator string, compareTo time.Time, threshold ...time.Duration)

    Ω(ACTUAL).Should(BeTemporally(COMPARATOR_STRING, EXPECTED_TIME, <THRESHOLD_DURATION>))

performs time-related assertions.  `ACTUAL` must be a `time.Time`.

There are six supported comparators:

- `Ω(ACTUAL).Should(BeTemporally("==", EXPECTED_TIME))`:
    asserts that `ACTUAL` and `EXPECTED_TIME` are identical `time.Time`s.

- `Ω(ACTUAL).Should(BeTemporally("~", EXPECTED_TIME, <THRESHOLD_DURATION>))`:
    asserts that `ACTUAL` and `EXPECTED_TIME` are within `<THRESHOLD_DURATION>` of one another.  By default `<THRESHOLD_DURATION>` is `time.Millisecond` but you can specify a custom value.

- `Ω(ACTUAL).Should(BeTemporally(">", EXPECTED_TIME))`:
    asserts that `ACTUAL` is after `EXPECTED_TIME`.

- `Ω(ACTUAL).Should(BeTemporally(">=", EXPECTED_TIME))`:
    asserts that `ACTUAL` is after or at `EXPECTED_TIME`.

- `Ω(ACTUAL).Should(BeTemporally("<", EXPECTED_TIME))`:
    asserts that `ACTUAL` is before `EXPECTED_TIME`.

- `Ω(ACTUAL).Should(BeTemporally("<=", EXPECTED_TIME))`:
    asserts that `ACTUAL` is before or at `EXPECTED_TIME`.

Any other comparator is an error.

### Asserting on Panics

#### Panic()

    Ω(ACTUAL).Should(Panic())

succeeds if `ACTUAL` is a function that, when invoked, panics.  `ACTUAL` must be a function that takes no arguments and returns no result -- any other type for `ACTUAL` is an error.

### Composing Matchers

You may form larger matcher expressions using the following operators: `And()`, `Or()`, `Not()` and `WithTransform()`.

Note: `And()` and `Or()` can also be referred to as `SatisfyAll()` and `SatisfyAny()`, respectively.

With these operators you can express multiple requirements in a single `Expect()` or `Eventually()` statement. For example:

    Expect(number).To(SatisfyAll(
                BeNumerically(">", 0),
                BeNumerically("<", 10)))

    Expect(msg).To(SatisfyAny(
                Equal("Success"),
                MatchRegexp(`^Error .+$`)))

It can also provide a lightweight syntax to create new matcher types from existing ones. For example:

    func BeBetween(min, max int) GomegaMatcher {
        return SatisfyAll(
                BeNumerically(">", min),
                BeNumerically("<", max))
    }

    Ω(number).Should(BeBetween(0, 10))

#### And(matchers ...GomegaMatcher)

#### SatisfyAll(matchers ...GomegaMatcher)

    Ω(ACTUAL).Should(And(MATCHER1, MATCHER2, ...))

or

    Ω(ACTUAL).Should(SatisfyAll(MATCHER1, MATCHER2, ...))

succeeds if `ACTUAL` satisfies all of the specified matchers (similar to a logical AND).

Tests the given matchers in order, returning immediately if one fails, without needing to test the remaining matchers.

#### Or(matchers ...GomegaMatcher)

#### SatisfyAny(matchers ...GomegaMatcher)

    Ω(ACTUAL).Should(Or(MATCHER1, MATCHER2, ...))

or

    Ω(ACTUAL).Should(SatisfyAny(MATCHER1, MATCHER2, ...))

succeeds if `ACTUAL` satisfies any of the specified matchers (similar to a logical OR).

Tests the given matchers in order, returning immediately if one succeeds, without needing to test the remaining matchers.

#### Not(matcher GomegaMatcher)

    Ω(ACTUAL).Should(Not(MATCHER))

succeeds if `ACTUAL` does **not** satisfy the specified matcher (similar to a logical NOT).

#### WithTransform(transform interface{}, matcher GomegaMatcher)

    Ω(ACTUAL).Should(WithTransform(TRANSFORM, MATCHER))

succeeds if applying the `TRANSFORM` function to `ACTUAL` (i.e. the value of `TRANSFORM(ACTUAL)`) will satisfy the given `MATCHER`. For example:

    GetColor := func(e Element) Color { return e.Color }

    Ω(element).Should(WithTransform(GetColor, Equal(BLUE)))

Or the same thing expressed by introducing a new, lightweight matcher:

    // HaveColor returns a matcher that expects the element to have the given color.
    func HaveColor(c Color) GomegaMatcher {
        return WithTransform(func(e Element) Color {
            return e.Color
        }, Equal(c))
    }

    Ω(element).Should(HaveColor(BLUE)))

---

## Adding Your Own Matchers

A matcher, in Gomega, is any type that satisfies the `GomegaMatcher` interface:

    type GomegaMatcher interface {
        Match(actual interface{}) (success bool, err error)
        FailureMessage(actual interface{}) (message string)
        NegatedFailureMessage(actual interface{}) (message string)
    }

For the simplest cases, new matchers can be [created by composition](#composing-matchers).

But writing domain-specific custom matchers is also trivial and highly encouraged.  Let's work through an example.

> The `GomegaMatcher` interface is defined in the `types` subpackage.

### A Custom Matcher: RepresentJSONifiedObject(EXPECTED interface{})

Say you're working on a JSON API and you want to assert that your server returns the correct JSON representation.  Rather than marshal/unmarshal JSON in your tests, you want to write an expressive matcher that checks that the received response is a JSON representation for the object in question.  This is what the `RepresentJSONifiedObject` matcher could look like:

    package json_response_matcher

    import (
        "github.com/onsi/gomega/types"

        "encoding/json"
        "fmt"
        "net/http"
        "reflect"
    )

    func RepresentJSONifiedObject(expected interface{}) types.GomegaMatcher {
        return &representJSONMatcher{
            expected: expected,
        }
    }

    type representJSONMatcher struct {
        expected interface{}
    }

    func (matcher *representJSONMatcher) Match(actual interface{}) (success bool, err error) {
        response, ok := actual.(*http.Response)
        if !ok {
            return false, fmt.Errorf("RepresentJSONifiedObject matcher expects an http.Response")
        }

        pointerToObjectOfExpectedType := reflect.New(reflect.TypeOf(matcher.expected)).Interface()
        err = json.NewDecoder(response.Body).Decode(pointerToObjectOfExpectedType)

        if err != nil {
            return false, fmt.Errorf("Failed to decode JSON: %s", err.Error())
        }

        decodedObject := reflect.ValueOf(pointerToObjectOfExpectedType).Elem().Interface()

        return reflect.DeepEqual(decodedObject, matcher.expected), nil
    }

    func (matcher *representJSONMatcher) FailureMessage(actual interface{}) (message string) {
        return fmt.Sprintf("Expected\n\t%#v\nto contain the JSON representation of\n\t%#v", actual, matcher.expected)
    }

    func (matcher *representJSONMatcher) NegatedFailureMessage(actual interface{}) (message string) {
        return fmt.Sprintf("Expected\n\t%#v\nnot to contain the JSON representation of\n\t%#v", actual, matcher.expected)
    }

Let's break this down:

- Most matchers have a constructor function that returns an instance of the matcher.  In this case we've created `RepresentJSONifiedObject`.  Where possible, your constructor function should take explicit types or interfaces.  For our use case, however, we need to accept any possible expected type so `RepresentJSONifiedObject` takes an argument with the generic `interface{}` type.
- The constructor function then initializes and returns an instance of our matcher: the `representJSONMatcher`.  These rarely need to be exported outside of your matcher package.
- The `representJSONMatcher` must satisfy the `GomegaMatcher` interface.  It does this by implementing the `Match`, `FailureMessage`, and `NegatedFailureMessage` method:
    - If the `GomegaMatcher` receives invalid inputs `Match` returns a non-nil error explaining the problems with the input.  This allows Gomega to fail the assertion whether the assertion is for the positive or negative case.
    - If the `actual` and `expected` values match, `Match` should return `true`.
    - Similarly, if the `actual` and `expected` values do not match, `Match` should return `false`.
    - If the `GomegaMatcher` was testing the `Should` case, and `Match` returned false, `FailureMessage` will be called to print a message explaining the failure.
    - Likewise, if the `GomegaMatcher` was testing the `ShouldNot` case, and `Match` returned false, `NegatedFailureMessage` will be called.
    - It is guaranteed that `FailureMessage` and `NegatedFailureMessage` will only be called *after* `Match`, so you can save off any state you need to compute the messages in `Match`.
- Finally, it is common for matchers to make extensive use of the `reflect` library to interpret the generic inputs they receive.  In this case, the `representJSONMatcher` goes through some `reflect` gymnastics to create a pointer to a new object with the same type as the `expected` object, read and decode JSON from `actual` into that pointer, and then deference the pointer and compare the result to the `expected` object.

You might test drive this matcher while writing it using Ginkgo.  Your test might look like:

    package json_response_matcher_test

    import (
        . "github.com/onsi/ginkgo"
        . "github.com/onsi/gomega"
        . "jsonresponsematcher"

        "bytes"
        "encoding/json"
        "io/ioutil"
        "net/http"
        "strings"

        "testing"
    )

    func TestCustomMatcher(t *testing.T) {
        RegisterFailHandler(Fail)
        RunSpecs(t, "Custom Matcher Suite")
    }

    type Book struct {
        Title  string `json:"title"`
        Author string `json:"author"`
    }

    var _ = Describe("RepresentJSONified Object", func() {
        var (
            book     Book
            bookJSON []byte
            response *http.Response
        )

        BeforeEach(func() {
            book = Book{
                Title:  "Les Miserables",
                Author: "Victor Hugo",
            }

            var err error
            bookJSON, err = json.Marshal(book)
            Ω(err).ShouldNot(HaveOccurred())
        })

        Context("when actual is not an http response", func() {
            It("should error", func() {
                _, err := RepresentJSONifiedObject(book).Match("not a response")
                Ω(err).Should(HaveOccurred())
            })
        })

        Context("when actual is an http response", func() {
            BeforeEach(func() {
                response = &http.Response{}
            })

            Context("with a body containing the JSON representation of actual", func() {
                BeforeEach(func() {
                    response.ContentLength = int64(len(bookJSON))
                    response.Body = ioutil.NopCloser(bytes.NewBuffer(bookJSON))
                })

                It("should succeed", func() {
                    Ω(response).Should(RepresentJSONifiedObject(book))
                })
            })

            Context("with a body containing the JSON representation of something else", func() {
                BeforeEach(func() {
                    reader := strings.NewReader(`{}`)
                    response.ContentLength = int64(reader.Len())
                    response.Body = ioutil.NopCloser(reader)
                })

                It("should fail", func() {
                    Ω(response).ShouldNot(RepresentJSONifiedObject(book))
                })
            })

            Context("with a body containing invalid JSON", func() {
                BeforeEach(func() {
                    reader := strings.NewReader(`floop`)
                    response.ContentLength = int64(reader.Len())
                    response.Body = ioutil.NopCloser(reader)
                })

                It("should error", func() {
                    _, err := RepresentJSONifiedObject(book).Match(response)
                    Ω(err).Should(HaveOccurred())
                })
            })
        })
    })

This also offers an example of what using the matcher would look like in your tests.  Note that testing the cases when the matcher returns an error involves creating the matcher and invoking `Match` manually (instead of using an `Ω` or `Expect` assertion).

### Aborting Eventually/Consistently

There are sometimes instances where `Eventually` or `Consistently` should stop polling a matcher because the result of the match simply cannot change.

For example, consider a test that looks like:

    Eventually(myChannel).Should(Receive(Equal("bar")))

`Eventually` will repeatedly invoke the `Receive` matcher against `myChannel` until the match succeeds.  However, if the channel becomes *closed* there is *no way* for the match to ever succeed.  Allowing `Eventually` to continue polling is inefficient and slows the test suite down.

To get around this, a matcher can optionally implement:

    MatchMayChangeInTheFuture(actual interface{}) bool

This is not part of the `GomegaMatcher` interface and, in general, most matchers do not need to implement `MatchMayChangeInTheFuture`.

If implemented, however, `MatchMayChangeInTheFuture` will be called with the appropriate `actual` value by `Eventually` and `Consistently` *after* the call to `Match` during every polling interval.  If `MatchMayChangeInTheFuture` returns `true`, `Eventually` and `Consistently` will continue polling.  If, however, `MatchMayChangeInTheFuture` returns `false`, `Eventually` and `Consistently` will stop polling and either fail or pass as appropriate.

If you'd like to look at a simple example of `MatchMayChangeInTheFuture` check out [`gexec`'s `Exit` matcher](https://github.com/onsi/gomega/tree/master/gexec/exit_matcher.go).  Here, `MatchMayChangeInTheFuture` returns true if the `gexec.Session` under test has not exited yet, but returns false if it has.  Because of this, if a process exits with status code 3, but an assertion is made of the form:

    Eventually(session, 30).Should(gexec.Exit(0))

`Eventually` will not block for 30 seconds but will return (and fail, correctly) as soon as the mismatched exit code arrives!

> Note: `Eventually` and `Consistently` only exercise the `MatchMayChangeInTheFuture` method *if* they are passed a bare value.  If they are passed functions to be polled it is not possible to guarantee that the return value of the function will not change between polling intervals.  In this case, `MatchMayChangeInTheFuture` is not called and the polling continues until either a match is found or the timeout elapses.

### Contributing to Gomega

Contributions are more than welcome.  Either [open an issue](http://github.com/onsi/gomega/issues) for a matcher you'd like to see or, better yet, test drive the matcher and [send a pull request](https://github.com/onsi/gomega/pulls).

When adding a new matcher please mimic the style use in Gomega's current matchers: you should use the `format` package to format your output, put the matcher and its tests in the `matchers` package, and the constructor in the `matchers.go` file in the top-level package.

## `ghttp`: Testing HTTP Clients
The `ghttp` package provides support for testing http *clients*.  The typical pattern in Go for testing http clients entails spinning up an `httptest.Server` using the `net/http/httptest` package and attaching test-specific handlers that perform assertions.

`ghttp` provides `ghttp.Server` - a wrapper around `httptest.Server` that allows you to easily build up a stack of test handlers.  These handlers make assertions against the incoming request and return a pre-fabricated response.  `ghttp` provides a number of prebuilt handlers that cover the most common assertions.  You can combine these handlers to build out full-fledged assertions that test multiple aspects of the incoming requests.

The goal of this documentation is to provide you with an adequate mental model to use `ghttp` correctly.  For a full reference of all the available handlers and the various methods on `ghttp.Server` look at the [godoc](https://godoc.org/github.com/onsi/gomega/ghttp) documentation.

### Making assertions against an incoming request

Let's start with a simple example.  Say you are building an API client that provides a `FetchSprockets(category string)` method that makes an http request to a remote server to fetch sprockets of a given category.

For now, let's not worry about the values returned by `FetchSprockets` but simply assert that the correct request was made.  Here's the setup for our `ghttp`-based Ginkgo test:


    Describe("The sprockets client", func() {
        var server *ghttp.Server
        var client *sprockets.Client

        BeforeEach(func() {
            server = ghttp.NewServer()
            client = sprockets.NewClient(server.URL())
        })

        AfterEach(func() {
            //shut down the server between tests
            server.Close()
        })
    })

Note that the server's URL is auto-generated and varies between test runs.  Because of this, you must always inject the server URL into your client.  Let's add a simple test that asserts that `FetchSprockets` hits the correct endpoint with the correct HTTP verb:

    Describe("The sprockets client", func() {
        //...see above

        Describe("fetching sprockets", func() {
            BeforeEach(func() {
                server.AppendHandlers(
                    ghttp.VerifyRequest("GET", "/sprockets"),
                )
            })

            It("should make a request to fetch sprockets", func() {
                client.FetchSprockets("")
                Ω(server.ReceivedRequests()).Should(HaveLen(1))
            })
        })
    })

Here we append a `VerifyRequest` handler to the `server` and call `client.FetchSprockets`.  This call (assuming it's a blocking call) will make a round-trip to the test `server` before returning.  The test `server` receives the request and passes it through the `VerifyRequest` handler which will validate that the request is a `GET` request hitting the `/sprockets` endpoint.  If it's not, the test will fail.

Note that the test can pass trivially if `client.FetchSprockets()` doesn't actually make a request.  To guard against this you can assert that the `server` has actually received a request.  All the requests received by the server are saved off and made available via `server.ReceivedRequests()`.  We use this to assert that there should have been exactly one received requests.

> Guarding against the trivial "false positive"  case outlined above isn't really necessary.  Just good practice when test *driving*.

Let's add some more to our example.  Let's make an assertion that `FetchSprockets` can request sprockets filtered by a particular category:


    Describe("The sprockets client", func() {
        //...see above

        Describe("fetching sprockets", func() {
            BeforeEach(func() {
                server.AppendHandlers(
                    ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                )
            })

            It("should make a request to fetch sprockets", func() {
                client.FetchSprockets("encabulators")
                Ω(server.ReceivedRequests()).Should(HaveLen(1))
            })
        })
    })

`ghttp.VerifyRequest` takes an optional third parameter that is matched against the request `URL`'s `RawQuery`.

Let's extend the example some more.  In addition to asserting that the request is a `GET` request to the correct endpoint with the correct query params, let's also assert that it includes the correct `BasicAuth` information and a correct custom header.  Here's the complete example:


    Describe("The sprockets client", func() {
        var (
            server *ghttp.Server
            client *sprockets.Client
            username, password string
        )

        BeforeEach(func() {
            username, password = "gopher", "tacoshell"
            server = ghttp.NewServer()
            client = sprockets.NewClient(server.URL(), username, password)
        })

        AfterEach(func() {
            server.Close()
        })

        Describe("fetching sprockets", func() {
            BeforeEach(func() {
                server.AppendHandlers(
                    ghttp.CombineHandlers(
                        ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                        ghttp.VerifyBasicAuth(username, password),
                        ghttp.VerifyHeader(http.Header{
                            "X-Sprocket-API-Version": []string{"1.0"},
                        }),
                    )
                )
            })

            It("should make a request to fetch sprockets", func() {
                client.FetchSprockets("encabulators")
                Ω(server.ReceivedRequests()).Should(HaveLen(1))
            })
        })
    })

This example *combines* multiple `ghttp` verify handlers using `ghttp.CombineHandlers`.  Under the hood, this returns a new handler that wraps and invokes the three passed in verify handlers.  The request sent by the client will pass through each of these verify handlers and must pass them all for the test to pass.

Note that you can easily add your own verify handler into the mix.  Just pass in a regular `http.HandlerFunc` and make assertions against the received request.

> It's important to understand that you must pass `AppendHandlers` **one** handler *per* incoming request (see [below](#handling-multiple-requests)).  In order to apply multiple handlers to a single request we must first combine them with `ghttp.CombineHandlers` and then pass that *one* wrapper handler in to `AppendHandlers`.

### Providing responses

So far, we've only made assertions about the outgoing request.  Clients are also responsible for parsing responses and returning valid data.  Let's say that `FetchSprockets()` returns two things: a slice `[]Sprocket` and an `error`.  Here's what a happy path test that asserts the correct data is returned might look like:


    Describe("The sprockets client", func() {
        //...
        Describe("fetching sprockets", func() {
            BeforeEach(func() {
                server.AppendHandlers(
                    ghttp.CombineHandlers(
                        ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                        ghttp.VerifyBasicAuth(username, password),
                        ghttp.VerifyHeader(http.Header{
                            "X-Sprocket-API-Version": []string{"1.0"},
                        }),
                        ghttp.RespondWith(http.StatusOK, `[
                            {"name": "entropic decoupler", "color": "red"},
                            {"name": "defragmenting ramjet", "color": "yellow"}
                        ]`),
                    )
                )
            })

            It("should make a request to fetch sprockets", func() {
                sprockets, err := client.FetchSprockets("encabulators")
                Ω(err).ShouldNot(HaveOccurred())
                Ω(sprockets).Should(Equal([]Sprocket{
                    sprockets.Sprocket{Name: "entropic decoupler", Color: "red"},
                    sprockets.Sprocket{Name: "defragmenting ramjet", Color: "yellow"},
                }))
            })
        })
    })

We use `ghttp.RespondWith` to specify the response return by the server.  In this case we're passing back a status code of `200` (`http.StatusOK`) and a pile of JSON.  We then assert, in the test, that the client succeeds and returns the correct set of sprockets.

The fact that details of the JSON encoding are bleeding into this test is somewhat unfortunate, and there's a lot of repetition going on.  `ghttp` provides a `RepondWithJSONEncoded` handler that accepts an arbitrary object and JSON encodes it for you.  Here's a cleaner test:

    Describe("The sprockets client", func() {
        //...
        Describe("fetching sprockets", func() {
            var returnedSprockets []Sprocket
            BeforeEach(func() {
                returnedSprockets = []Sprocket{
                    sprockets.Sprocket{Name: "entropic decoupler", Color: "red"},
                    sprockets.Sprocket{Name: "defragmenting ramjet", Color: "yellow"},
                }

                server.AppendHandlers(
                    ghttp.CombineHandlers(
                        ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                        ghttp.VerifyBasicAuth(username, password),
                        ghttp.VerifyHeader(http.Header{
                            "X-Sprocket-API-Version": []string{"1.0"},
                        }),
                        ghttp.RespondWithJSONEncoded(http.StatusOK, returnedSprockets),
                    )
                )
            })

            It("should make a request to fetch sprockets", func() {
                sprockets, err := client.FetchSprockets("encabulators")
                Ω(err).ShouldNot(HaveOccurred())
                Ω(sprockets).Should(Equal(returnedSprockets))
            })
        })
    })

### Testing different response scenarios

Our test currently only handles the happy path where the server returns a `200`.  We should also test a handful of sad paths.  In particular, we'd like to return a `SprocketsErrorNotFound` error when the server `404`s and a `SprocketsErrorUnauthorized` error when the server returns a `401`.  But how to do this without redefining our server handler three times?

`ghttp` provides `RespondWithPtr` and `RespondWithJSONEncodedPtr` for just this use case.  Both take *pointers* to status codes and respond bodies (objects for the `JSON` case).  Here's the more complete test:

    Describe("The sprockets client", func() {
        //...
        Describe("fetching sprockets", func() {
            var returnedSprockets []Sprocket
            var statusCode int

            BeforeEach(func() {
                returnedSprockets = []Sprocket{
                    sprockets.Sprocket{Name: "entropic decoupler", Color: "red"},
                    sprockets.Sprocket{Name: "defragmenting ramjet", Color: "yellow"},
                }

                server.AppendHandlers(
                    ghttp.CombineHandlers(
                        ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                        ghttp.VerifyBasicAuth(username, password),
                        ghttp.VerifyHeader(http.Header{
                            "X-Sprocket-API-Version": []string{"1.0"},
                        }),
                        ghttp.RespondWithJSONEncodedPtr(&statusCode, &returnedSprockets),
                    )
                )
            })

            Context("when the request succeeds", func() {
                BeforeEach(func() {
                    statusCode = http.StatusOK
                })

                It("should return the fetched sprockets without erroring", func() {
                    sprockets, err := client.FetchSprockets("encabulators")
                    Ω(err).ShouldNot(HaveOccurred())
                    Ω(sprockets).Should(Equal(returnedSprockets))
                })
            })

            Context("when the response is unauthorized", func() {
                BeforeEach(func() {
                    statusCode = http.StatusUnauthorized
                })

                It("should return the SprocketsErrorUnauthorized error", func() {
                    sprockets, err := client.FetchSprockets("encabulators")
                    Ω(sprockets).Should(BeEmpty())
                    Ω(err).Should(MatchError(SprocketsErrorUnauthorized))
                })
            })

            Context("when the response is not found", func() {
                BeforeEach(func() {
                    statusCode = http.StatusNotFound
                })

                It("should return the SprocketsErrorNotFound error", func() {
                    sprockets, err := client.FetchSprockets("encabulators")
                    Ω(sprockets).Should(BeEmpty())
                    Ω(err).Should(MatchError(SprocketsErrorNotFound))
                })
            })
        })
    })

In this way, the status code and returned value (not shown here) can be changed in sub-contexts without having to modify the original test setup.

### Handling multiple requests

So far, we've only seen examples where one request is made per test.  `ghttp` supports handling *multiple* requests too.  `server.AppendHandlers` can be passed multiple handlers and these handlers are evaluated in order as requests come in.

This can be helpful in cases where it is not possible (or desirable) to have calls to the client under test only generate *one* request.  A common example is pagination.  If the sprockets API is paginated it may be desirable for `FetchSprockets` to provide a simpler interface that simply fetches all available sprockets.

Here's what a test might look like:

    Describe("fetching sprockets from a paginated endpoint", func() {
        var returnedSprockets []Sprocket
        var firstResponse, secondResponse PaginatedResponse
        var statusCode int

        BeforeEach(func() {
            returnedSprockets = []Sprocket{
                sprockets.Sprocket{Name: "entropic decoupler", Color: "red"},
                sprockets.Sprocket{Name: "defragmenting ramjet", Color: "yellow"},
                sprockets.Sprocket{Name: "parametric demuxer", Color: "blue"},
            }

            firstReponse = sprockets.PaginatedResponse{
                Sprockets: returnedSprockets[0:2], //first batch
                PaginationToken: "get-second-batch", //some opaque non-empty token
            }

            secondReponse = sprockets.PaginatedResponse{
                Sprockets: returnedSprockets[2:], //second batch
                PaginationToken: "", //signifies the last batch
            }

            server.AppendHandlers(
                ghttp.CombineHandlers(
                    ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                    ghttp.RespondWithJSONEncoded(http.StatusOK, firstReponse),
                ),
                ghttp.CombineHandlers(`
                    ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators&pagination-token=get-second-batch"),
                    ghttp.RespondWithJSONEncoded(http.StatusOK, secondResponse),
                )
            )
        })

        It("should fetch all the sprockets", func() {
            sprockets, err := client.FetchSprockets("encabulators")
            Ω(err).ShouldNot(HaveOccurred())
            Ω(sprockets).Should(Equal(returnedSprockets))
        })
    })

By default the `ghttp` server fails the test if the number of requests received exceeds the number of handlers registered, so this test ensures that the `client` stops sending requests after receiving the second (and final) set of paginated data.

### MUXing Routes to Handlers

`AppendHandlers` allows you to make ordered assertions about incoming requests.  This places a strong constraint on all incoming requests: namely that exactly the right requests have to arrive in exactly the right order and that no additional requests are allowed.

One can take a different testing strategy, however.  Instead of asserting that requests come in in a predefined order, you may which to build a test server that can handle arbitrarily many requests to a set of predefined routes.  In fact, there may be some circumstances where you want to make ordered assertions on *some* requests (via `AppendHandlers`) but still support sending particular responses to *other* requests that may interleave the ordered assertions.

`ghttp` supports these sorts of usecases via `server.RouteToHandler(method, path, handler)`.

Let's cook up an example.  Perhaps, instead of authenticating via basic auth our sprockets client logs in and fetches a token from the server when performing requests that require authentication.  We could pepper our `AppendHandlers` calls with a handler that handles these requests (this is not a terrible idea, of course!) *or* we could set up a single route at the top of our tests.

Here's what such a test might look like:

    Describe("CRUDing sprockes", func() {
        BeforeEach(func() {
            server.RouteToHandler("POST", "/login", ghttp.CombineHandlers(
                ghttp.VerifyRequest("POST", "/login", "user=bob&password=password"),
                ghttp.RespondWith(http.StatusOK, "your-auth-token"),
            ))
        })
        Context("GETting sprockets", func() {
            var returnedSprockets []Sprocket

            BeforeEach(func() {
                returnedSprockets = []Sprocket{
                    sprockets.Sprocket{Name: "entropic decoupler", Color: "red"},
                    sprockets.Sprocket{Name: "defragmenting ramjet", Color: "yellow"},
                    sprockets.Sprocket{Name: "parametric demuxer", Color: "blue"},
                }

                server.AppendHandlers(
                    ghttp.CombineHandlers(
                        ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
                        ghttp.RespondWithJSONEncoded(http.StatusOK, returnedSprockets),
                    ),
                )
            })

            It("should fetch all the sprockets", func() {
                sprockets, err := client.FetchSprockes("encabulators")
                Ω(err).ShouldNot(HaveOccurred())
                Ω(sprockets).Should(Equal(returnedSprockets))
            })
        })

        Context("POSTing sprockets", func() {
            var sprocketToSave Sprocket
            BeforeEach(func() {
                sprocketToSave = sprockets.Sprocket{Name: "endothermic penambulator", Color: "purple"}

                server.AppendHandlers(
                    ghttp.CombineHandlers(
                        ghttp.VerifyRequest("POST", "/sprocket", "token=your-auth-token"),
                        ghttp.VerifyJSONRepresenting(sprocketToSave)
                        ghttp.RespondWithJSONEncoded(http.StatusOK, nil),
                    ),
                )
            })

            It("should save the sprocket", func() {
                err := client.SaveSprocket(sprocketToSave)
                Ω(err).ShouldNot(HaveOccurred())
            })
        })
    })

Here, saving a sprocket triggers authentication, which is handled by the registered `RouteToHandler` handler whereas fetching the list of sprockets does not.

> `RouteToHandler` can take either a string as a route (as seen in this example) or a `regexp.Regexp`.

### Allowing unhandled requests

By default, `ghttp`'s server marks the test as failed if a request is made for which there is no registered handler.

It is sometimes useful to have a fake server that simply returns a fixed status code for all unhandled incoming requests.  `ghttp` supports this: just set `server.AllowUnhandledRequests = true` and `server.UnhandledRequestStatusCode` to whatever status code you'd like to return.

In addition to returning the registered status code, `ghttp`'s server will also save all received requests.  These can be accessed by calling `server.ReceivedRequests()`.  This is useful for cases where you may want to make assertions against requests *after* they've been made.

To bring it all together: there are three ways to instruct a `ghttp` server to handle requests: you can map routes to handlers using `RouteToHandler`, you can append handlers via `AppendHandlers`, and you can `AllowUnhandledRequests` and specify an `UnhandledRequestStatusCode`.

When a `ghttp` server receives a request it first checks against the set of handlers registered via `RouteToHandler` if there is no such handler it proceeds to pop an `AppendHandlers` handler off the stack, if the stack of ordered handlers is empty, it will check whether `AllowUnhandledRequests` is `true` or `false`.  If `false` the test fails.  If `true`, a response is sent with `UnhandledRequestStatusCode`.

## `gbytes`: Testing Streaming Buffers

`gbytes` implements `gbytes.Buffer` - an `io.WriteCloser` that captures all input to an in-memory buffer.

When used in concert with the `gbytes.Say` matcher, the `gbytes.Buffer` allows you make *ordered* assertions against streaming data.

What follows is a contrived example.  `gbytes` is best paired with [`gexec`](#gexec-testing-external-processes).

Say you have an integration test that is streaming output from an external API.  You can feed this stream into a `gbytes.Buffer` and make ordered assertions like so:

    Describe("attach to the data stream", func() {
        var (
            client *apiclient.Client
            buffer *gbytes.Buffer
        )
        BeforeEach(func() {
            buffer = gbytes.NewBuffer()
            client := apiclient.New()
            go client.AttachToDataStream(buffer)
        })

        It("should stream data", func() {
            Eventually(buffer).Should(gbytes.Say(`Attached to stream as client \d+`))

            client.ReticulateSplines()
            Eventually(buffer).Should(gbytes.Say(`reticulating splines`))
            client.EncabulateRetros(7)
            Eventually(buffer).Should(gbytes.Say(`encabulating 7 retros`))
        })
    })

These assertions will only pass if the strings passed to `Say` (which are interpreted as regular expressions - make sure to escape characters appropriately!) appear in the buffer.  An opaque read cursor (that you cannot access or modify) is fast-forwarded as successful assertions are made. So, for example:

    Eventually(buffer).Should(gbytes.Say(`reticulating splines`))
    Consistently(buffer).ShouldNot(gbytes.Say(`reticulating splines`))

will (counterintuitively) pass.  This allows you to write tests like:

    client.ReticulateSplines()
    Eventually(buffer).Should(gbytes.Say(`reticulating splines`))
    client.ReticulateSplines()
    Eventually(buffer).Should(gbytes.Say(`reticulating splines`))

and ensure that the test is correctly asserting that `reticulating splines` appears *twice*.

At any time, you can access the entire contents written to the buffer via `buffer.Contents()`.  This includes *everything* ever written to the buffer regardless of the current position of the read cursor.

### Handling branches

Sometimes (rarely!) you must write a test that must perform different actions depending on the output streamed to the buffer.  This can be accomplished using `buffer.Detect`. Here's a contrived example:

    func LoginIfNecessary() {
        client.Authorize()
        select {
        case <-buffer.Detect("You are not logged in"):
            client.Login()
        case <-buffer.Detect("Success"):
            return
        case <-time.After(time.Second):
            ginkgo.Fail("timed out waiting for output")
        }
        buffer.CancelDetects()
    }

`buffer.Detect` takes a string (interpreted as a regular expression) and returns a channel that will fire *once* if the requested string is detected.  Upon detection, the buffer's opaque read cursor is fast-forwarded so subsequent uses of `gbytes.Say` will pick up from where the succeeding `Detect` left off.  You *must* call `buffer.CancelDetects()` to clean up afterwards (`buffer` spawns one goroutine per call to `Detect`).

## `gexec`: Testing External Processes

`gexec` simplifies testing external processes.  It can help you [compile go binaries](#compiling-external-binaries), [start external processes](#starting-external-processes), [send signals and wait for them to exit](#sending-signals-and-waiting-for-the-process-to-exit), make [assertions against the exit code](#asserting-against-exit-code), and stream output into `gbytes.Buffer`s to allow you [make assertions against output](#making-assertions-against-the-process-output).

### Compiling external binaries

You use `gexec.Build()` to compile Go binaries.  These are built using `go build` and are stored off in a temporary directory.  You'll want to `gexec.CleanupBuildArtifacts()` when you're done with the test.

A common pattern is to compile binaries once at the beginning of the test using `BeforeSuite` and to clean up once at the end of the test using `AfterSuite`:

    var pathToSprocketCLI string

    BeforeSuite(func() {
        var err error
        pathToSprocketCLI, err = gexec.Build("github.com/spacely/sprockets")
        Ω(err).ShouldNot(HaveOccurred())
    })

    AfterSuite(func() {
        gexec.CleanupBuildArtifacts()
    })

> By default, `gexec.Build` uses the GOPATH specified in your environment.  You can also use `gexec.BuildIn(gopath string, packagePath string)` to specify a custom GOPATH for the build command.  This is useful to, for example, build a binary against its vendored Godeps.

> You can specify arbitrary environment variables for the build command – such as GOOS and GOARCH for building on other platforms – using `gexec.BuildWithEnvironment(packagePath string, envs []string)`.

### Starting external processes

`gexec` provides a `Session` that wraps `exec.Cmd`.  `Session` includes a number of features that will be explored in the next few sections.  You create a `Session` by instructing `gexec` to start a command:

    command := exec.Command(pathToSprocketCLI, "-api=127.0.0.1:8899")
    session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
    Ω(err).ShouldNot(HaveOccurred())

`gexec.Start` calls `command.Start` for you and forwards the command's `stdout` and `stderr` to `io.Writer`s that you provide. In the code above, we pass in Ginkgo's `GinkgoWriter`.  This makes working with external processes quite convenient: when a test passes no output is printed to screen, however if a test fails then any output generated by the command will be provided.

> If you want to see all your output regardless of test status, just run `ginkgo` in verbose mode (`-v`) - now everything written to `GinkgoWriter` makes it onto the screen.

### Sending signals and waiting for the process to exit

`gexec.Session` makes it easy to send signals to your started command:

    session.Kill() //sends SIGKILL
    session.Interrupt() //sends SIGINT
    session.Terminate() //sends SIGTERM
    session.Signal(signal) //sends the passed in os.Signal signal

If the process has already exited these signal calls are no-ops.

In addition to starting the wrapped command, `gexec.Session` also *monitors* the command until it exits.  You can ask `gexec.Session` to `Wait` until the process exits:

    session.Wait()

this will block until the session exits and will *fail* if it does not exit within the default `Eventually` timeout.  You can override this timeout by specifying a custom one:

    session.Wait(5 * time.Second)

> Though you can access the wrapped command using `session.Command` you should not attempt to `Wait` on it yourself.  `gexec` has already called `Wait` in order to monitor your process for you.

> Under the hood `session.Wait` simply uses `Eventually`.


Since the signalling methods return the session you can chain calls together:

    session.Terminate().Wait()

will send `SIGTERM` and then wait for the process to exit.

### Asserting against exit code

Once a session has exited you can fetch its exit code with `session.ExitCode()`.  You can subsequently make assertions against the exit code.

A more idiomatic way to assert that a command has exited is to use the `gexec.Exit()` matcher:

    Eventually(session).Should(Exit())

Will verify that the `session` exits within `Eventually`'s default timeout.  You can assert that the process exits with a specified exit code too:

    Eventually(session).Should(Exit(0))

> If the process has not exited yet, `session.ExitCode()` returns `-1`

### Making assertions against the process output

In addition to streaming output to the passed in `io.Writer`s (the `GinkgoWriter` in our example above), `gexec.Start` attaches `gbytes.Buffer`s to the command's output streams.  These are available on the `session` object via:

    session.Out //a gbytes.Buffer connected to the command's stdout
    session.Err //a gbytes.Buffer connected to the command's stderr

This allows you to make assertions against the stream of output:

    Eventually(session.Out).Should(gbytes.Say("hello [A-Za-z], nice to meet you"))
    Eventually(session.Err).Should(gbytes.Say("oops!"))

Since `gexec.Session` is a `gbytes.BufferProvider` that provides the `Out` buffer you can write assertions against `stdout` output like so:

    Eventually(session).Should(gbytes.Say("hello [A-Za-z], nice to meet you"))

Using the `Say` matcher is convenient when making *ordered* assertions against a stream of data generated by a live process.  Sometimes, however, all you need is to
wait for the process to exit and then make assertions against the entire contents of its output.  Since `Wait()` returns `session` you can wait for the process to exit, then grab all its stdout as a `[]byte` buffer with a simple one-liner:

    Ω(session.Wait().Out.Contents()).Should(ContainSubstring("finished successfully"))

### Signaling all processes
`gexec` provides methods to track and send signals to all processes that it starts.

    gexec.Kill() //sends SIGKILL to all processes
    gexec.Terminate() //sends SIGTERM to all processes
    gexec.Signal(int)  //sends the passed in os.Signal signal to all the processes
    gexec.Interrupt() //sends SIGINT to all processes

If the any of the processes have already exited these signal calls are no-ops.

`gexec` also provides methods to cleanup and wait for all the processes it started.

    gexec.KillAndWait()
    gexec.TerminateAndWait()

You can specify a custom timeout by:

    gexec.KillAndWait(5 * time.Second)
    gexec.TerminateAndWait(2 * time.Second)

The timeout is applied for each of the processes.

It is considered good practice to ensure all of your processes have been killed before the end of the test suite. If you are using `ginkgo` you can use:

    AfterSuite(func(){
        gexec.KillAndWait()
    })

Due to the global nature of these methods, keep in mind that signaling processes will affect all processes started by `gexec`, in any context. For example if these methods where used in an `AfterEach`, then processes started in `BeforeSuite` would also be signaled.

---

## `gstruct`: Testing Complex Data Types

`gstruct` simplifies testing large and nested structs and slices. It is used for building up complex matchers that apply different tests to each field or element.

### Testing type `struct`

`gstruct` provides the `FieldsMatcher` through the `MatchAllFields` and `MatchFields` functions for applying a separate matcher to each field of a struct:

    actual := struct{
        A int
        B bool
        C string
    }{5, true, "foo"}
    Expect(actual).To(MatchAllFields(Fields{
        "A": BeNumerically("<", 10),
        "B": BeTrue(),
        "C": Equal("foo"),
    })

`MatchAllFields` requires that every field is matched, and each matcher is mapped to a field. To match a subset or superset of a struct, you should use the `MatchFields` function with the `IgnoreExtras` and `IgnoreMissing` options. `IgnoreExtras` will ignore fields that don't map to a matcher, e.g.

    Expect(actual).To(MatchFields(IgnoreExtras, Fields{
        "A": BeNumerically("<", 10),
        "B": BeTrue(),
        // Ignore lack of "C" in the matcher.
    })

`IgnoreMissing` will ignore matchers that don't map to a field, e.g.

    Expect(actual).To(MatchFields(IgnoreExtras, Fields{
        "A": BeNumerically("<", 10),
        "B": BeTrue(),
        "C": Equal("foo"),
        "D": Equal("bar"), // Ignored, since actual.D does not exist.
    })

The options can be combined with the binary or: `IgnoreMissing|IgnoreExtras`.

### Testing type slice

`gstruct` provides the `ElementsMatcher` through the `MatchAllElements` and `MatchElements` function for applying a separate matcher to each element, identified by an `Identifier` function:

    actual := []string{
        "A: foo bar baz",
        "B: once upon a time",
        "C: the end",
    }
    id := func(element interface{}) {
        return element.(string)[0]
    }
    Expect(actual).To(MatchAllElements(id, Elements{
        "A": Not(BeZero()),
        "B": MatchRegexp("[A-Z]: [a-z ]+"),
        "C": ContainSubstring("end"),
    })

`MatchAllElements` requires that there is a 1:1 mapping from every element to every matcher. To match a subset or superset of elements, you should use the `MatchElements` function with the `IgnoreExtras` and `IgnoreMissing` options. `IgnoreExtras` will ignore elements that don't map to a matcher, e.g.

    Expect(actual).To(MatchElements(IgnoreExtras, Fields{
        "A": Not(BeZero()),
        "B": MatchRegexp("[A-Z]: [a-z ]+"),
        // Ignore lack of "C" in the matcher.
    })

`IgnoreMissing` will ignore matchers that don't map to an element, e.g.

    Expect(actual).To(MatchFields(IgnoreExtras, Fields{
        "A": Not(BeZero()),
        "B": MatchRegexp("[A-Z]: [a-z ]+"),
        "C": ContainSubstring("end"),
        "D": Equal("bar"), // Ignored, since actual.D does not exist.
    })

You can also use the flag `AllowDuplicates` to permit multiple elements in your slice to map to a single key and matcher in your fields (this flag is not meaningful when applied to structs).

    everyElementID := func(element interface{}) {
        return "a constant" // Every element will map to the same key in this case; you can group them into multiple keys, however.
    }
    Expect(actual).To(MatchElements(everyElementID, AllowDuplicates, Elements{
        "a constant": ContainSubstring(": "), // Because every element passes this test
    }))
    Expect(actual).NotTo(MatchElements(everyElementID, AllowDuplicates, Elements{
        "a constant": ContainSubstring("foo bar baz"), // Only the first element passes this test
    }))

The options can be combined with the binary or: `IgnoreMissing|IgnoreExtras|AllowDuplicates`.

### Testing pointer values

`gstruct` provides the `PointTo` function to apply a matcher to the value pointed-to. It will fail if the pointer value is `nil`:

    foo := 5
    Expect(&foo).To(PointTo(Equal(5)))
    var bar *int
    Expect(bar).NotTo(PointTo(BeNil()))

### Putting it all together: testing complex structures

The `gsturct` matchers are intended to be composable, and can be combined to apply fuzzy-matching to large and deeply nested structures. The additional `Ignore()` and `Reject()` matchers are provided for ignoring (always succeed) fields and elements, or rejecting (always fail) fields and elements.

Example:

    coreID := func(element interface{}) string {
        return strconv.Itoa(element.(CoreStats).Index)
    }
    Expect(actual).To(MatchAllFields(Fields{
	    "Name":      Ignore(),
		"StartTime": BeTemporally(">=", time.Now().Add(-100 * time.Hour)),
		"CPU": PointTo(MatchAllFields(Fields{
			"Time":                 BeTemporally(">=", time.Now().Add(-time.Hour)),
			"UsageNanoCores":       BeNumerically("~", 1E9, 1E8),
			"UsageCoreNanoSeconds": BeNumerically(">", 1E6),
            "Cores": MatchElements(coreID, IgnoreExtras, Elements{
                "0": MatchAllFields(Fields{
                    Index: Ignore(),
	                "UsageNanoCores":       BeNumerically("<", 1E9),
	                "UsageCoreNanoSeconds": BeNumerically(">", 1E5),
                }),
                "1": MatchAllFields(Fields{
                    Index: Ignore(),
	                "UsageNanoCores":       BeNumerically("<", 1E9),
	                "UsageCoreNanoSeconds": BeNumerically(">", 1E5),
                }),
            }),
		})),
		"Memory": PointTo(MatchAllFields(Fields{
			"Time": BeTemporally(">=", time.Now().Add(-time.Hour)),
			"AvailableBytes":  BeZero(),
			"UsageBytes":      BeNumerically(">", 5E6),
			"WorkingSetBytes": BeNumerically(">", 5E6),
			"RSSBytes":        BeNumerically("<", 1E9),
			"PageFaults":      BeNumerically("~", 1000, 100),
			"MajorPageFaults": BeNumerically("~", 100, 50),
		})),
		"Rootfs":             m.Ignore(),
		"Logs":               m.Ignore(),
	}))
