Skip to content

Commit

Permalink
Merge pull request #1 from pact-foundation/conceptual_model
Browse files Browse the repository at this point in the history
Conceptual model
  • Loading branch information
davidvc authored Apr 1, 2022
2 parents 99e08f1 + 4d2298d commit 6f00ece
Show file tree
Hide file tree
Showing 42 changed files with 604 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ Pact is a tool for implementing "consumer driven contracts" - a technique for te

Since its creation in 2013, Pact has come a long way. We're always adding new features in response to the feedback we get from our users and our own experience, but recently we've realised that we've done a poor job of letting everyone know about the awesome new things we've added along the way.

So, we've started blog.pact.io as a place to let everyone know about new features in Pact, to share people's Pact experiences (good and bad!), and to help build a community of Pact users who can help each other. If you haven't already, please join us at [slack.pact.io](http://slack.pact.io/), and if you'd like to contribute a post to our blog, chat to us on the #blog channel.
So, we've started [docs.pact.io/blog](https://docs.pact.io/blog) as a place to let everyone know about new features in Pact, to share people's Pact experiences (good and bad!), and to help build a community of Pact users who can help each other. If you haven't already, please join us at [slack.pact.io](http://slack.pact.io/), and if you'd like to contribute a post to our blog, chat to us on the #blog channel.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
title: Publishing Pact verification statuses to Github
author: Beth Skurrie
authorURL: http://twitter.com/bethesque
tags: [verification]
keywords: [verification]
date: 2018-07-16
draft: false
hide_table_of_contents: true
---

If you're using Travis CI, Code Climate, or one of many other CI tools with Github, you've probably noticed the little checklist of items that shows just above the "merge" button when you open a pull request.

![commit-statuses](https://s3-ap-southeast-2.amazonaws.com/blog-pact-io/2018/07/commit-statuses.png)

These are called commit "statuses", and there is a [Github API][github-api] for reporting these (Gitlab also has a similar [API][gitlab-api]). If you are using a git sha for the [consumer version number][pacticipant-version-numbers] when you publish your pacts, you can now use Pact Broker webhooks to report the verification statuses of your pacts back to Github.

To do this, open up your Pact Broker API Browser, and click on the `NON-GET` button next to the `pb:webhooks` relation. Modify the JSON below to match your consumer, repository and Github auth details (we recommend you make a separate [token][github-token] for this purpose with the `repo:status` grant), and click `Make Request`.

```json
{
"consumer": {
"name": "<consumer name>"
},
"events": [
{
"name": "contract_published"
},
{
"name": "provider_verification_published"
}
],
"request": {
"method": "POST",
"url": "https://api.github.com/repos/<organization>/<project>/statuses/${pactbroker.consumerVersionNumber}",
"headers": {
"Content-Type": "application/json"
},
"body": {
"state": "${pactbroker.githubVerificationStatus}",
"description": "Pact Verification Tests ${pactbroker.providerVersionTags}",
"context": "${pactbroker.providerName}",
"target_url": "${pactbroker.verificationResultUrl}"
},
"username": "USERNAME",
"password": "PASSWORD"
}
}

```

If all your consumer names match their repository names in Github, you can make this a global webhook by removing the `consumer` node, and replacing the hardcoded `<project>` name in the URL with the parameter `${pactbroker.consumerName}`.

Want to use this cool feature? You'll need version [2.47.1][pact-broker-release] or later of the Pact Broker.

Check out the [webhook template library][webhook-template-library] for more handy webhooks.

[gitlab-api]: https://docs.gitlab.com/ee/api/commits.html#post-the-build-status-to-a-commit
[github-api]: https://developer.github.com/v3/repos/statuses/
[pacticipant-version-numbers]: https://github.com/pact-foundation/pact_broker/wiki/Pacticipant-version-numbers
[github-token]: https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
[pact-broker-release]: https://github.com/pact-foundation/pact_broker/releases/tag/v2.47.1
[webhook-template-library]: https://github.com/pact-foundation/pact_broker/wiki/Webhook-template-library

101 changes: 101 additions & 0 deletions website/blog/2018-07-24-contract-testing-a-graphql-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: Contract testing a GraphQL API
author: Matt Fellows
authorURL: https://twitter.com/matthewfellows
tags: [GraphQL]
keywords: [GraphQL]
date: 2018-07-24
draft: false
hide_table_of_contents: true
---

> REST is dead, long live REST
GraphQL is being hailed by many as the _new REST_ - it has type safety, a neat DSL and a great ecosystem. Perhaps best of all, it focuses on the needs of the client; consumers get the data they want, in the shape they want it - nothing more and nothing less.

I can now fetch data from my [BFF](https://samnewman.io/patterns/architectural/bff/) via my React Component with caching, error handling and state management all taken care of for me, just like so:

```js
import { Query } from "react-apollo";
import gql from "graphql-tag";

const ExchangeRates = () => (
<Query
query={gql`
{
rates(currency: "USD") {
currency
rate
}
}
`}
>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;

return data.rates.map(({ currency, rate }) => (
<div key={currency}>
<p>{`${currency}: ${rate}`}</p>
</div>
));
}}
</Query>
);
```
For some, however, this ability to define a schema and even [generate client code](https://github.com/apollographql/apollo-cli#apollo-codegengenerate-output), harkens back to the [brittle and dark ages of WSDL](http://greglturnquist.com/2017/05/23/power-rest-part-1/), whereby clients are tightly coupled to their API implementation.
Can we have our cake and it it too?
<blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Do you see this as a bad thing? WSDL absolutely has its issues, but it is a definition language. CDC is an approach, which can work with WSDL, Swagger, or any definition format or wire protocol. They are orthogonal concepts</p>&mdash; Matt Fellows (@matthewfellows) <a href="https://twitter.com/matthewfellows/status/1019685135891849216?ref_src=twsrc%5Etfw">July 18, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>&nbsp;</p>
If you look under the covers, it turns out GraphQL is actually just a simple abstraction over REST, which means we can still test GraphQL as we do with regular RESTful APIs - including using contract testing! 🙌
GraphQL (mostly) follows just a few simple rules:
1. Requests are made via an `HTTP POST`
2. GraphQL queries are sent as stringified JSON contained within a `query` property of the request
3. The response body is wrapped in the `data` sub-property, namespaced by the operation (Query or Mutation) that is being called, alongside any `errors` for the operation.
Read more about the GraphQL specification [here](https://graphql.org/learn/queries/)
Constructing a basic cURL for a simplistic `hello` operation looks something like this:
```sh
curl -X POST \
-H 'content-type: application/json' \
-d '{ "query": "{ hello }" }' \
http://someapi/api
```
Whilst you can create this request using the usual Pact DSL, in our latest version of [Pact JS](https://github.com/pact-foundation/pact-js/tree/6.x.x/) (`6.x.x` or `@prerelease`) we have even created a `GraphQLInteraction` interface to simplify creating the expectations - including [variables](https://graphql.org/learn/queries/#variables) support and matching rules:
```js
const graphqlQuery = new GraphQLInteraction()
.uponReceiving("a hello request")
.withQuery(`{ hello(person: $person }`)
.withRequest({
path: "/graphql",
method: "POST",
})
.withVariables({
person: "Sally",
})
.willRespondWith({
status: 200,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
body: {
data: {
hello: like("Hello Sally"),
},
},
});
```
So there it is, Pact + GraphQL: a match made in heaven.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
title: Announcing Pactflow - our managed Pact Broker
author: Matt Fellows
authorURL: https://twitter.com/matthewfellows
tags: [Pactflow]
keywords: [Pactflow]
date: 2019-05-01
draft: false
hide_table_of_contents: true
---

If you use Pact and would like to support us in realising our vision of transforming the way teams test and release distributed systems, we have recently released [Pactflow](http://pactflow.io) - our fully managed Pact Broker with additional features to simplify teams getting started and scaling with Pact and contract testing.

Read our [launch announcement](https://blog.pactflow.io/pactflow-continuous-delivery-for-microservices/) for more background as to why and how this all came about. It's just the start, but we're really excited about the future.

If you're hosting your own broker, or are looking to set one up, you can get started quickly and for free on our [Developer Plan](https://pactflow.io/pricing/).

We hope to see you soon!
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: v3 Provider state support added to Pact Ruby, JS, Go, .NET
author: Beth Skurrie
authorURL: https://twitter.com/bethskurrie
tags: [ruby,js,go,.net,v3,pact]
keywords: [ruby,js,go,.net,v3,pact]
date: 2019-05-29
draft: false
hide_table_of_contents: true
---

While full Pact specification v3 support is still a while off, you can now verify pacts that use [multiple provider states and provider state params](https://github.com/pact-foundation/pact-specification/tree/version-3#allow-multiple-provider-states-with-parameters) from the v3 compliant implementations (eg. JVM and Rust)

The provider state setup url will be called once for each provider state.
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: How we've fixed the biggest problem with the Pact workflow
author: Beth Skurrie
authorURL: https://twitter.com/bethskurrie
tags: [pact]
keywords: [pact]
date: 2020-02-24
draft: false
hide_table_of_contents: true
---


### tl&semi;dr
Changes to the contract made by the consumer teams can no longer break the provider builds. Hooray!

Read on for the longer version...
# The problem

Pact is a consumer driven contract testing tool that allows you to test your integration points without dependencies. The consumer is tested with a mock provider, and a contract ("pact") is generated from the tests. The contract is taken over to the provider and then "verified" to make sure that the real provider and the mock provider behave the same way.

During the verification step, each request from the contract is replayed against a running test instance of the provider, and the responses are compared to the expected responses. If they match, the verification is successful. If they do not match, the verification has failed, and the provider build fails.

In the context of an existing contract, there are two reasons that the pact verification step can fail when it was previously passing.

1. The provider has changed.
2. The contract (consumer expectations) has changed.

In scenario 1, we actually want the provider build to fail, as this is the purpose of contract testing - it prevents breaking changes being made by the provider for existing consumers.

In scenario 2 however, when the contract has changed, the failure of the provider build is an undesirable consequence of the workflow. The contract may have changed due to the teams following the "consumer driven" nature of the process whereby the expectations come before the implementation (TDD for services); there may be an issue with the provider state data; or there may just be incorrect expectations about existing behaviour.

The fact that the provider build can be broken by new or incorrect expectations in the contract (which is effectively written by the consumer team) is one of the biggest problems people have with Pact. It leads to contention between teams, and in some cases, stops teams using Pact at all.

One solution could be to run all pact verification builds in such a way as to ignore any failures that might occur, but then we'd miss being alerted to potentially breaking changes by the provider, which defeats the purpose of using contracts in the first place.

What we want is a way to get feedback on changed contracts without breaking the provider build, but for the build to correctly identify and fail when a provider is making a breaking change.
# The solution
The Pact team is extremely happy to introduce the new "pending pacts" feature.

Those familiar with automated testing frameworks have probably come across the term "pending" tests. These are tests that have a particular flag on them that causes them (depending on the framework) to either be skipped, or if executed, to not fail the build. In the case of Pact, we want the feedback we get from execution, so rather than a "pending pact" being one which will be skipped, it is one which can be verified without its failure causing the overall verification task to fail.

So how does the Pact verification tool know if a pact is in "pending" state or not? This is where the Pact Broker comes in. The Pact Broker is a service that sits between the consumer and provider builds, and allows the contracts and verification results to be exchanged between the consumer and provider teams. The Pact Broker can identify when a contract with new content has been published, and when it is retrieved for verification by the provider's Pact library, it flags it as "pending". The Pact library executes the verification, ensuring that the status of the overall task is not affected by any failures. At the end of the verification process, the outcome of the verification is published back to the Pact Broker. Once the pact has been successfully verified it ceases to be "pending". This means that any subsequent verification failures for a pact with identical content will cause the provider build to fail, as the failure can now only be due to a change in the provider code.
# How do I start using pending pacts?

Head to https://docs.pact.io/pending for information on how to setup your Pact Broker to enable this feature (it is enabled by default on https://pactflow.io).

To start getting the benefit of this new and improved workflow, you will need to upgrade to the latest version of the Pact Broker and your Pact testing libraries. Consult the documentation for your language to find out how to enable the `pending` feature.

If you're on a consumer team, and have, until now, relied on the provider team to alert you to verification failures, you'll want to make sure that you're getting this information via another channel now. We recommend that you use [can-i-deploy][can-i-deploy] to make sure that you aren't deploying with a broken contract, and that you set up [webhooks][webhooks] to ensure you're made aware of the verification outcomes of your contracts as soon as possible (eg. posting to a team's [Slack][slack] channel, or updating a [Github commit status][github].)

### A note for advanced Pact Broker users

If you're not using tags in the Pact Broker you can skip this section! But take the time you've saved reading the next paragraph, and spend it reading up on [tags][tags] because if you're not using them, you're probably not getting the full benefit out of your Pact Broker.

Tag users - the "pending" status is calculated using the provider version tag(s) that will be published with your verification results. The provider tags are sent to the Pact Broker when retriving the list of pacts to verify, and are used to determine the pending status for each pact returned. For example, once you have successfully verified a pact with a version of the provider tagged as `feat-x`, then pacts with the same content will be non-pending for any subsequent verifications by a `feat-x` version. However, the same pact could still be in "pending" state for the `master`.

Why is this important? It means that if you're using a feature branch tagged `feat-x` on your provider to implement a new interaction, the pact will remain pending on your `master` branch even after it passes verification on the `feat-x` branch. It will only become non-pending on `master` once the feature branch has been merged in, and the pact has passed verification on the merged code.
# Conclusion
We're pretty excited about this new workflow, and we hope it will help make your experience testing with Pact a smoother and happier one. Let us know how you find it on the [Pact Foundation Slack][pact-foundation-slack] (join [here][join]).

[tags]: https://docs.pact.io/best_practices/pact_nirvana#5-allow-contracts-to-change-without-breaking-your-builds
[webhooks]: https://docs.pact.io/pact_broker/advanced_topics/webhooks
[github]: https://docs.pact.io/blog/2018/07/16/publishing-pact-verification-statuses-to-github/
[slack]: https://github.com/pact-foundation/pact_broker/wiki/Webhook-template-library#slack---post-notification
[pact-foundation-slack]: https://pact-foundation.slack.com
[join]: https://slack.pact.io
[can-i-deploy]: https://docs.pact.io/pact_broker/can_i_deploy
Loading

0 comments on commit 6f00ece

Please sign in to comment.