Skip to content

Commit

Permalink
chore: cleanup docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mefellows committed Jun 14, 2021
1 parent 700e9ce commit 1fd7edc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 40 deletions.
19 changes: 11 additions & 8 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
1. Ability to create and verify both [v2] and [v3] [specification] pacts
1. A bunch of new features, including the new v3 specification [matchers and generators](https://github.com/pact-foundation/pact-specification/tree/version-3/), injected provider states and more.
1. Each test is given a dedicated server and port, simplifying lifecycle events and improving isolation between tests.
1. You _must_ clear out any pact directory prior to the tests running. Any pact files will be appended to during test execution or may result in conflicts.

### Package version

Expand All @@ -20,6 +21,7 @@ i.e. `github.com/pact-foundation/pact-go/v2`
#### Sugar interface

The following package exposes aliases for the most commonly used interfaces for Matchers, common types and builders:

```
. "github.com/pact-foundation/pact-go/v2/sugar"
```
Expand All @@ -28,8 +30,8 @@ The following package exposes aliases for the most commonly used interfaces for

#### Primary Interface

* `dsl.Pact` was the primary interface. This is now replaced with `NewPactV2` and the `NewPactV3` methods, which will return you a builder for the corresponding specification.
* `Verify` is now `ExecuteTest` to avoid ambiguity with provider side verification.
- `dsl.Pact` was the primary interface. This is now replaced with `NewPactV2` and the `NewPactV3` methods, which will return you a builder for the corresponding specification.
- `Verify` is now `ExecuteTest` to avoid ambiguity with provider side verification.

These are available in consumer package: `"github.com/pact-foundation/pact-go/v2/consumer"`

Expand All @@ -48,6 +50,7 @@ You can now use proper POSIX compliant regexes :)
#### Speed / Parallelism

the `NewV2Pact` and `NewV3Pact` interfaces are not thread safe (i.e. you shouldn't run parallel tests with them), but you don't need to. Here is one of the examples run on a loop 1000 times, writing to a different file on each run:

```
➜ examples ✗ time go test -count=1 -tags=consumer -run TestConsumerV2 .
ok github.com/pact-foundation/pact-go/examples 4.269s
Expand All @@ -67,8 +70,8 @@ The `content-type` is now a mandatory field, to improve matching for bodies of v

Two new builder methods exist for binary/file payloads:

* `WithBinaryBody` accepts a `[]byte` for matching on binary payloads (e.g. images)
* `WithMultipartFile` accepts a path to file from the file system, and the multipart boundary
- `WithBinaryBody` accepts a `[]byte` for matching on binary payloads (e.g. images)
- `WithMultipartFile` accepts a path to file from the file system, and the multipart boundary

#### Query Strings

Expand All @@ -78,7 +81,7 @@ Query strings are now accepted (and [encoded](https://github.com/pact-foundation

#### Provider Interface

* `dsl.Pact` was the primary interface. This is now replaced with `HTTPVerifier` struct and `VerifyProvider` method.
- `dsl.Pact` was the primary interface. This is now replaced with `HTTPVerifier` struct and `VerifyProvider` method.

These are available in consumer package: `"github.com/pact-foundation/pact-go/v2/provider"`

Expand All @@ -96,16 +99,16 @@ The `StateHandler` type has also changed in 3 important ways:

#### Consumer

* `dsl.Pact` was the primary interface. This is now replaced with `NewMessagePactV3` builder. The `VerifyMessageConsumer` method is now replaced by the method `Verify` on the builder.
- `dsl.Pact` was the primary interface. This is now replaced with `NewMessagePactV3` builder. The `VerifyMessageConsumer` method is now replaced by the method `Verify` on the builder.

#### Provider

* `dsl.Pact` was the primary interface. This is now replaced by the `MessageVerifier` struct and the `Verify` method. The main difference is the state handlers, as discussed above.
- `dsl.Pact` was the primary interface. This is now replaced by the `MessageVerifier` struct and the `Verify` method. The main difference is the state handlers, as discussed above.

These are available in message package: `"github.com/pact-foundation/pact-go/v2/message"`

[CLI Tools](https://docs.pact.io/implementation_guides/cli/)
[v2](https://github.com/pact-foundation/pact-specification/tree/version-3/)
[v3](https://github.com/pact-foundation/pact-specification/tree/version-2/)
[specification](https://github.com/pact-foundation/pact-specification/)
[parameters](https://github.com/pact-foundation/pact-specification/tree/version-3/#allow-multiple-provider-states-with-parameters)
[parameters](https://github.com/pact-foundation/pact-specification/tree/version-3/#allow-multiple-provider-states-with-parameters)
9 changes: 2 additions & 7 deletions consumer/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func init() {
logging.InitLogging()
}

// MockHTTPProviderConfig provides the configuration options for an HTTP mock server
// consumer test.
type MockHTTPProviderConfig struct {
// Consumer is the name of the Consumer/Client.
Consumer string
Expand Down Expand Up @@ -59,15 +61,8 @@ type MockHTTPProviderConfig struct {
// Port the mock service should run on. Leave blank to have one assigned
// automatically by the OS.
// Use AllowedMockServerPorts to constrain the assigned range.
// TODO: visit port at this level. If we want to allow multiple interaction tests for
// the same consumer provider, this is probably best done at the Verify() step
Port int

// DisableToolValidityCheck prevents CLI version checking - use this carefully!
// The ideal situation is to check the tool installation with before running
// the tests, which should speed up large test suites significantly
DisableToolValidityCheck bool

// ClientTimeout specifies how long to wait for Pact CLI to start
// Can be increased to reduce likelihood of intermittent failure
// Defaults to 10s
Expand Down
2 changes: 1 addition & 1 deletion consumer/interaction_v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type InteractionV3 struct {
Interaction
}

// Given specifies a provider state. Optional.
// Given specifies a provider state, may be called multiple times. Optional.
func (i *InteractionV3) Given(state models.ProviderStateV3) *InteractionV3 {
i.Interaction.interaction.GivenWithParameter(state.Name, state.Parameters)

Expand Down
63 changes: 39 additions & 24 deletions docs/consumer.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The consumer interface is in the package: `github.com/pact-foundation/pact-go/v2

The two primary interfaces are `NewV2Pact` and `NewV3Pact`. If your provider is also V3 compatible, you can use the V3 variant, otherwise you should stick with V2.

## Writing a Consumer test
### Writing a Consumer test

The purpose of a Pact test is to unit test the API Client of the consumer.

Expand Down Expand Up @@ -53,7 +53,7 @@ func TestProductAPIClient(t *testing.T) {
UponReceiving("A request for Product 10").
WithRequest("GET", S("/product/10")).
WillRespondWith(200).
WithBodyMatch(&Product{})
WithBodyMatch(&Product{}) // This uses struct tags for matchers

// Act: test our API client behaves correctly
err = mockProvider.ExecuteTest(func(config MockServerConfig) error {
Expand All @@ -74,10 +74,10 @@ func TestProductAPIClient(t *testing.T) {
}
```

## Matching
### Matching

In addition to matching on exact values, there are a number of useful matching functions
in the `matching` package that can increase expressiveness of your tests and reduce brittle
in the `matching` package that can increase the expressiveness of your tests and reduce brittle
test cases.

Rather than use hard-coded values which must then be present on the Provider side,
Expand Down Expand Up @@ -105,11 +105,24 @@ _NOTE: Some matchers are only compatible with the V3 interface, and must not be
| `TimeGenerated` | V3 | Matches a cross platform formatted date, and generates a current time during verification |
| `DateTimeGenerated` | V3 | Matches a cross platform formatted datetime, and generates a current datetime during verification |

### Matching by regular expression
#### Match common formats

_Example:_
| method | Min. Compatibility | description |
| --------------- | ------------------ | ----------------------------------------------------------------------------------------------- |
| `Identifier()` | V2 | Match an ID (e.g. 42) |
| `Integer()` | V3 | Match all numbers that are integers (both ints and longs) |
| `Decimal()` | V3 | Match all real numbers (floating point and decimal) |
| `HexValue()` | V2 | Match all hexadecimal encoded strings |
| `Date()` | V2 | Match string containing basic ISO8601 dates (e.g. 2016-01-01) |
| `Timestamp()` | V2 | Match a string containing an RFC3339 formatted timestamp (e.g. Mon, 31 Oct 2016 15:21:41 -0400) |
| `Time()` | V2 | Match string containing times in ISO date format (e.g. T22:44:30.652Z) |
| `IPv4Address()` | V2 | Match string containing IP4 formatted address |
| `IPv6Address()` | V2 | Match string containing IP6 formatted address |
| `UUID()` | V2 | Match strings containing UUIDs |

#### Nesting Matchers

Here is a more complex example that shows how all 3 terms can be used together:
Matchers may be nested in other objects. Here is a more complex example that shows how 3 common matchers can be used together:

```go
body :=
Expand All @@ -134,22 +147,7 @@ This example will result in a response body from the mock server that looks like
}
```

### Match common formats

| method | Min. Compatibility | description |
| --------------- | ------------------ | ----------------------------------------------------------------------------------------------- |
| `Identifier()` | V2 | Match an ID (e.g. 42) |
| `Integer()` | V3 | Match all numbers that are integers (both ints and longs) |
| `Decimal()` | V3 | Match all real numbers (floating point and decimal) |
| `HexValue()` | V2 | Match all hexadecimal encoded strings |
| `Date()` | V2 | Match string containing basic ISO8601 dates (e.g. 2016-01-01) |
| `Timestamp()` | V2 | Match a string containing an RFC3339 formatted timestamp (e.g. Mon, 31 Oct 2016 15:21:41 -0400) |
| `Time()` | V2 | Match string containing times in ISO date format (e.g. T22:44:30.652Z) |
| `IPv4Address()` | V2 | Match string containing IP4 formatted address |
| `IPv6Address()` | V2 | Match string containing IP6 formatted address |
| `UUID()` | V2 | Match strings containing UUIDs |

### Auto-generate matchers from struct tags
#### Auto-generate matchers from struct tags

Furthermore, if you isolate your Data Transfer Objects (DTOs) to an adapters package so that they exactly reflect the interface between you and your provider, then you can leverage `WithBodyMatch(object)` option to auto-generate the expected response body in your contract tests. Under the hood, it recursively traverses the DTO struct and uses `Term, Like, and EachLike` to create the contract.

Expand Down Expand Up @@ -178,7 +176,24 @@ then specifying a response body is as simple as:

The `pact` struct tags shown above are optional. By default, it asserts that the JSON shape matches the struct and that the field types match.

## Publishing Pacts to a Broker
#### Matching binary payload and multipart requests

Two builder methods exist for binary/file payloads:

- `WithBinaryBody` accepts a `[]byte` for matching on binary payloads (e.g. images)
- `WithMultipartFile` accepts a path to file from the file system, and the multipart boundary

### Provider States

There are several ways to define a provider state:

1. Using the `Given` builder method passing in a plain string.
1. Using the `GivenWithParameters` builder method, passing in a string description and a hash of parameters to be used by the provider during verification.
1. Using the `FromProviderState` builder methid, specifying an expression to be replaced by the provider during erification, and example value to use in the consumer test. Example: `FromProviderState("${name}", "billy"),`. [Read more](https://pactflow.io/blog/injecting-values-from-provider-states/) on this feature.

For V3 tests, these methods may be called multiple times, resulting in more than 1 state for a given interaction.

## Publishing pacts to a Broker

We recommend publishing the contracts to a Pact Broker (or https://pactflow.io) using the [CLI Tools]()https://docs.pact.io/implementation_guides/cli/#pact-cli.

Expand Down

0 comments on commit 1fd7edc

Please sign in to comment.