Skip to content

Commit

Permalink
fix several documentation spelling issues
Browse files Browse the repository at this point in the history
  • Loading branch information
onsi committed Jan 20, 2023
1 parent 36400cb commit e2eff1f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 26 deletions.
38 changes: 19 additions & 19 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Alternatively, such error assertions on multi return value functions can be simp
Ω(MultipleReturnValuesFunc()).Error().Should(HaveOccurred())
```

Similar, asserting that no error occured is supported, too (where the other return values are allowed to take on any value):
Similar, asserting that no error occurred is supported, too (where the other return values are allowed to take on any value):

```go
Ω(MultipleReturnValuesFunc()).Error().ShouldNot(HaveOccured())
Expand Down Expand Up @@ -296,7 +296,7 @@ Eventually(c, "50ms").Should(BeClosed())

will poll the channel repeatedly until it is closed. In this example `Eventually` will block until either the specified timeout of 50ms has elapsed or the channel is closed, whichever comes first.

Several Gomega libraries allow you to use Eventually in this way. For example, the `gomega/gexec` package allows you to block until a `*gexec.Session` exits successfuly via:
Several Gomega libraries allow you to use Eventually in this way. For example, the `gomega/gexec` package allows you to block until a `*gexec.Session` exits successfully via:

```go
Eventually(session).Should(gexec.Exit(0))
Expand Down Expand Up @@ -368,7 +368,7 @@ You can poll this function like so:
Eventually(FetchFullName).WithArguments(1138).Should(Equal("Wookie"))
```

`WithArguments()` supports multiple arugments as well as variadic arguments.
`WithArguments()` supports multiple arguments as well as variadic arguments.

It is important to note that the function passed into Eventually is invoked **synchronously** when polled. `Eventually` does not (in fact, it cannot) kill the function if it takes longer to return than `Eventually`'s configured timeout. This is where using a `context.Context` can be helpful. Here is an example that leverages Gingko's support for interruptible nodes and spec timeouts:

Expand Down Expand Up @@ -407,13 +407,13 @@ It("adds a few books and checks the count", func(ctx SpecContext) {
}, SpecTimeout(time.Second * 5))
```

In addition, Gingko's `SpecContext` allows Gomega to tell Ginkgo about the status of a currently running `Eventually` whenever a Progress Report is generated. So, if a spec times out while running an `Eventually` Ginkgo will not only show you which `Eventually` was running when the timeout occured, but will also include the failure the `Eventually` was hitting when the timeout occurred.
In addition, Gingko's `SpecContext` allows Gomega to tell Ginkgo about the status of a currently running `Eventually` whenever a Progress Report is generated. So, if a spec times out while running an `Eventually` Ginkgo will not only show you which `Eventually` was running when the timeout occurred, but will also include the failure the `Eventually` was hitting when the timeout occurred.

#### Category 3: Making assertions _in_ the function passed into `Eventually`

When testing complex systems it can be valuable to assert that a *set* of assertions passes `Eventually`. `Eventually` supports this by accepting functions that take **a single `Gomega` argument** and **return zero or more values**.

Here's an example that makes some asssertions and returns a value and error:
Here's an example that makes some assertions and returns a value and error:

```go
Eventually(func(g Gomega) (Widget, error) {
Expand Down Expand Up @@ -442,7 +442,7 @@ Eventually(func(g Gomega) {

will rerun the function until all assertions pass.

You can also pass additional arugments to functions that take a Gomega. The only rule is that the Gomega argument must be first. If you also want to pass the context attached to `Eventually` you must ensure that is the second argument. For example:
You can also pass additional arguments to functions that take a Gomega. The only rule is that the Gomega argument must be first. If you also want to pass the context attached to `Eventually` you must ensure that is the second argument. For example:

```go
Eventually(func(g Gomega, ctx context.Context, path string, expected ...string){
Expand Down Expand Up @@ -800,7 +800,7 @@ succeeds if `ACTUAL` is a non-nil `error` that matches `EXPECTED`. `EXPECTED` mu

- A string, in which case `ACTUAL.Error()` will be compared against `EXPECTED`.
- A matcher, in which case `ACTUAL.Error()` is tested against the matcher.
- An error, in which case anyo of the following is satisfied:
- An error, in which case any of the following is satisfied:
- `errors.Is(ACTUAL, EXPECTED)` returns `true`
- `ACTUAL` or any of the errors it wraps (directly or indirectly) equals `EXPECTED` in terms of `reflect.DeepEqual()`.

Expand Down Expand Up @@ -1641,7 +1641,7 @@ type GomegaMatcher interface {

For the simplest cases, new matchers can be [created by composition](#composing-matchers). Please also take a look at the [Building Custom Matchers](https://onsi.github.io/ginkgo/#building-custom-matchers) section of the Ginkgo and Gomega patterns chapter in the Ginkgo docs for additional examples.

In addition to composition, however, it is fairly straightforward to build domain-specific custom matchers. You can create new types that satisfy the `GomegaMatcher` interace *or* you can use the `gcustom` package to build matchers out of simple functions.
In addition to composition, however, it is fairly straightforward to build domain-specific custom matchers. You can create new types that satisfy the `GomegaMatcher` interface *or* you can use the `gcustom` package to build matchers out of simple functions.

Let's work through an example and illustrate both approaches.

Expand Down Expand Up @@ -1711,7 +1711,7 @@ Let's break this down:
- 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.

### gcustom: A convenient mechanism for buildling custom matchers
### gcustom: A convenient mechanism for building custom matchers

[`gcustom`](https:/onsi/gomega/tree/master/gcustom) is a package that makes building custom matchers easy. Rather than define new types, you can simply provide `gcustom.MakeMatcher` with a function. The [godocs](https://pkg.go.dev/github.com/onsi/gomega/gcustom) for `gcustom` have all the details but here's how `RepresentJSONifiedObject` could be implemented with `gcustom`:

Expand Down Expand Up @@ -1903,7 +1903,7 @@ type inner interface {
}
```

The `Inner()` method must return the actual `gomega.Default`. For Gomega to function properly your wrapper methods must call the same method on the real `gomega.Default` This allows you to wrap every Goemga method call (e.g. `Expect()`) with your own code across your test suite. You can use this to add random delays, additional logging, or just for tracking the number of `Expect()` calls made.
The `Inner()` method must return the actual `gomega.Default`. For Gomega to function properly your wrapper methods must call the same method on the real `gomega.Default` This allows you to wrap every Gomega method call (e.g. `Expect()`) with your own code across your test suite. You can use this to add random delays, additional logging, or just for tracking the number of `Expect()` calls made.

```go
func init() {
Expand Down Expand Up @@ -2467,7 +2467,7 @@ AfterSuite(func() {
})
```

> 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.
> 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 Go dependencies.
> 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)`.
Expand Down Expand Up @@ -2515,7 +2515,7 @@ session.Wait(5 * time.Second)
> Under the hood `session.Wait` simply uses `Eventually`.

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

```go
session.Terminate().Wait()
Expand Down Expand Up @@ -2819,7 +2819,7 @@ Expect(actual).To(MatchAllFields(Fields{

## `gmeasure`: Benchmarking Code

`gmeasure` provides support for measuring and recording benchmarks of your code and tests. It can be used as a simple standalone benchmarking framework, or as part of your code's test suite. `gmeasure` integrates cleanly with Ginkgo V2 to enable rich benchmarking of code alognside your tests.
`gmeasure` provides support for measuring and recording benchmarks of your code and tests. It can be used as a simple standalone benchmarking framework, or as part of your code's test suite. `gmeasure` integrates cleanly with Ginkgo V2 to enable rich benchmarking of code alongside your tests.

### A Mental Model for `gmeasure`

Expand Down Expand Up @@ -3158,7 +3158,7 @@ This simple connection point ensures that the output is appropriately formatted

### Caching Experiments

`gmeasure` supports caching experiments to local disk. Experiments can be stored and retreived from the cache by name and version number. Caching allows you to skip rerunning expensive experiments and versioned caching allows you to bust the cache by incrementing the version number. Under the hood, the cache is simply a set of files in a directory. Each file contains a JSON encoded header with the experiment's name and version number followed by the JSON-encoded experiment. The various cache methods are documented over at [pkg.go.dev](https://pkg.go.dev/github.com/onsi/gomega/gmeasure#ExperimentCache).
`gmeasure` supports caching experiments to local disk. Experiments can be stored and retrieved from the cache by name and version number. Caching allows you to skip rerunning expensive experiments and versioned caching allows you to bust the cache by incrementing the version number. Under the hood, the cache is simply a set of files in a directory. Each file contains a JSON encoded header with the experiment's name and version number followed by the JSON-encoded experiment. The various cache methods are documented over at [pkg.go.dev](https://pkg.go.dev/github.com/onsi/gomega/gmeasure#ExperimentCache).

Using an `ExperimentCache` with Ginkgo takes a little bit of wiring. Here's an example:

Expand Down Expand Up @@ -3358,7 +3358,7 @@ results in one or more goroutines. The ordering of the goroutines does not
matter.

`HaveLeaked` always takes the built-in list of well-known good goroutines into
consideration and this list can neither be overriden nor disabled. Additional
consideration and this list can neither be overridden nor disabled. Additional
known non-leaky goroutines `NONLEAKY1`, ... can be passed to `HaveLeaks` either
in form of `GomegaMatcher`s or in shorthand notation:

Expand Down Expand Up @@ -3435,11 +3435,11 @@ goroutine(s) as non-leaky. `IgnoringGoroutines` compares goroutines by their
Eventually(Goroutines).ShouldNot(HaveLeaked(IgnoringInBacktrace(FNAME)))
```

`IgnoringInBacktrace` succeeds if `ACTUAL` contains a groutine where `FNAME` is
`IgnoringInBacktrace` succeeds if `ACTUAL` contains a goroutine where `FNAME` is
contained anywhere within its call stack (backtrace), causing `HaveLeaked` to
filter out the matched goroutine as non-leaky. Please note that
`IgnoringInBacktrace` uses a (somewhat lazy) `strings.Contains` to check for any
occurence of `FNAME` in backtraces.
occurrence of `FNAME` in backtraces.

`ACTUAL` must be an array or slice of `Goroutine`s.

Expand All @@ -3450,7 +3450,7 @@ Eventually(Goroutines).ShouldNot(HaveLeaked(IgnoringCreator(CREATORNAME)))
```

In its most basic form, `IgnoringCreator` succeeds if `ACTUAL` contains a
groutine where the name of the function creating the goroutine matches
goroutine where the name of the function creating the goroutine matches
`CREATORNAME`, causing `HaveLeaked` to filter out the matched goroutine(s) as
non-leaky. `IgnoringCreator` uses `==` for comparing the creator function name.

Expand Down Expand Up @@ -3497,7 +3497,7 @@ names of the topmost functions on their stacks (backtraces):
- `testing.RunTests [chan receive]`,
- `testing.(*T).Run [chan receive]`,
- and `testing.(*T).Parallel [chan receive]`.
- the [Ginko testing framework](https://onsi.github.io/ginkgo/):
- the [Ginkgo testing framework](https://onsi.github.io/ginkgo/):
- `github.com/onsi/ginkgo/v2/internal.(*Suite).runNode` (including anonymous
inner functions),
- the anonymous inner functions of
Expand Down
13 changes: 6 additions & 7 deletions gcustom/make_matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func ParseTemplate(templ string) (*template.Template, error) {
/*
MakeMatcher builds a Gomega-compatible matcher from a function (the matchFunc).
matchFunc must return (bool, error) and take a single argument. If you want to perform type-checking yourself pass in a matchFunc of type `func(actual any) (bool, error)`. If you want to only operate on a specific type, pass in `func(actual DesiredType) (bool, error)`; MakeMatcher will take care of checking typues for you and notifying the user if they use the matcher with an invalid type.
matchFunc must return (bool, error) and take a single argument. If you want to perform type-checking yourself pass in a matchFunc of type `func(actual any) (bool, error)`. If you want to only operate on a specific type, pass in `func(actual DesiredType) (bool, error)`; MakeMatcher will take care of checking types for you and notifying the user if they use the matcher with an invalid type.
MakeMatcher(matchFunc) builds a matcher with generic failure messages that look like:
Expand All @@ -68,7 +68,7 @@ where templateString is a string that is compiled by WithTemplate into a matcher
template, err = gcustom.ParseTemplate(templateString) //use gcustom's ParseTemplate to get some additional functions mixed in
matcher := MakeMatcher(matchFunc, template)
matcher := MakeMatcher(matchFunc).WithPrcompiled(template)
matcher := MakeMatcher(matchFunc).WithPrecompiled(template)
When a simple message string is provided the positive failure message will look like:
Expand Down Expand Up @@ -161,25 +161,25 @@ Templates are provided the following variables and functions:
{{.To}} - is set to "to" if this is a positive failure message and "not to" if this is a negated failure message
{{.Actual}} - the actual passed in to the matcher
{{.FormattedActual}} - a string representing the formatted actual. This can be multiple lines and is always generated with an indentation of 1
{{format <object> <optional-indentaiton}} - a function that allows you to use Gomega's default formatting from within the template. The passed-in <object> is formatted and <optional-indentation> can be set to an integer to control indentation.
{{format <object> <optional-indentation}} - a function that allows you to use Gomega's default formatting from within the template. The passed-in <object> is formatted and <optional-indentation> can be set to an integer to control indentation.
In addition, you can provide custom data to the template by calling WithTemplate(templateString, data) (where data can be anything). This is provided to the template as {{.Data}}.
Here's a simple example of all these pieces working together:
func HaveWidget(widget Widget) OmegaMatcher {
return MakeMatcher(func(machine Machine) (bool, error) {
return maching.HasWidget(widget), nil
return machine.HasWidget(widget), nil
}).WithTemplate("Expected:\n{{.FormattedActual}}\n{{.To}} have widget named {{.Data.Name}}:\n{{format .Data 1}}", widget)
}
Expect(maching).To(HaveWidget(Widget{Name: "sprocket", Version: 2}))
Expect(machine).To(HaveWidget(Widget{Name: "sprocket", Version: 2}))
Would generate a failure message that looks like:
Expected:
<formatted machine>
to have widget named sprocker:
to have widget named sprocket:
<formatted sprocket>
*/
func (c CustomGomegaMatcher) WithTemplate(templ string, data ...any) CustomGomegaMatcher {
Expand All @@ -205,7 +205,6 @@ WithTemplateData() returns a CustomGomegaMatcher configured to provide it's temp
MakeMatcher(matchFunc).WithTemplate(templateString, data)
MakeMatcher(matchFunc).WithTemplate(templateString).WithTemplateData(data)
*/
func (c CustomGomegaMatcher) WithTemplateData(data any) CustomGomegaMatcher {
c.templateData = data
Expand Down

0 comments on commit e2eff1f

Please sign in to comment.