This repository has been archived by the owner on Sep 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 42
[PACT] feat: add Contract tests for Kibana Fleet #339
Closed
Closed
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
82ec16c
chore: add sequence diagrams for Fleet APIs
mdelapenya edb05f4
chore: add a unit test mocking Kibana response
mdelapenya d599c47
chore: bump minor version for Jeffail/gabs
mdelapenya bc67521
feat: first Pact tests for the E2E tests consumer
mdelapenya e67ac8d
chore: notice dependencies
mdelapenya 19dcd35
chore: apply basic auth in request headers
mdelapenya c7a3199
chore: move pacts to the root dir
mdelapenya d1deb1a
chore: move pact to the root directory
mdelapenya dc95dcf
chore: use a struct for the expected response
mdelapenya 81ba767
chore: rename variable
mdelapenya 53e0679
chore: add first contract test for the provider
mdelapenya 67ca63c
chore: set provider headers
mdelapenya b87e441
chore: add a test for getting an existing integration
mdelapenya 23468ba
chore: add a test for a non-existing integration
mdelapenya 3834cc7
fix: kibana returns a 500 when the integration is not found
mdelapenya ebd8a75
chore: add request headers in consumer contract
mdelapenya 9a717ff
fix: in master kibana returns a 404 not found, as expected
mdelapenya cdcf262
docs: document pact contracts
mdelapenya b7ca07a
chore: add missing license header to tests
mdelapenya 4394dee
chore: startup and tear down runtime dependencies
mdelapenya 9bcc623
chore: make sure the files are regen
mdelapenya 3a3a9fd
docs: fix typo
mdelapenya a304d8f
chore: decouple the destruction of runtime deps for pact tests
mdelapenya 0396fce
feat(ci): integrate contract tests in the CI
mdelapenya f171fcb
chore: archive pact logs
mdelapenya d64ff6a
fix: forgot to add the when expression
mdelapenya b7d1e7a
chore: make the contract tests timeout to be configurable
mdelapenya 1d84d84
fix: add docker login for private images
mdelapenya ce53845
chore: leverage Go build tags to skip pact tests from unit stage
mdelapenya 87a56c3
chore: add missing license header to test
mdelapenya e4ce4a4
fix: use declarative instead of classic IF
mdelapenya 114ea7c
chore: move contract tests stage to later in the pipeline
mdelapenya f0c8968
fixup
mdelapenya 945876d
fix(ci): use proper path (again)
mdelapenya 8b67b46
fix: typo
mdelapenya 1097e35
fix: typo
mdelapenya 0190346
Merge branch 'master' into pact
mdelapenya 0864146
Merge branch 'master' into pact
mdelapenya bbae5b0
chore: update fleet APIs
mdelapenya 87832b9
chore: update fleet paths in contract
mdelapenya b5d1a4f
chore: bump eastic-endpoint version
mdelapenya f6d67f7
fix: update fleet path
mdelapenya c52de78
fix: EPR returns 502 with not found integrations
mdelapenya 0aa330e
Revert "fix: EPR returns 502 with not found integrations"
mdelapenya bb6c7b3
chore: update diagrams with new endpoints
mdelapenya File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
bin | ||
outputs | ||
|
||
pact | ||
pact.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Contract tests for the E2E Testing project using PACT | ||
|
||
> We are basically extracting contents from [Pact's docs](https://docs.pact.io) | ||
|
||
## Introduction | ||
|
||
### What is contract testing? | ||
_**Contract testing** is a technique for testing an integration point by checking each application in isolation to ensure the messages it sends or receives conform to a shared understanding that is documented in a "contract"._ | ||
|
||
For applications that communicate via HTTP, these "messages" would be the HTTP request and response, and for an application that used queues, this would be the message that goes on the queue. | ||
|
||
In practice, a common way of implementing contract tests (and the way Pact does it) is to check that all the calls to your test doubles [return the same results](https://martinfowler.com/bliki/ContractTest.html) as a call to the real application would. | ||
|
||
### When would I use contract testing? | ||
Contract testing is immediately applicable anywhere where you have two services that need to communicate - such as an API client and a web front-end. Although a single client and a single service is a common use case, contract testing really shines in an environment with many services (as is common for a microservice architecture). Having well-formed contract tests makes it easy for developers to avoid version hell. Contract testing is the killer app for microservice development and deployment. | ||
|
||
### Contract testing terminology | ||
In general, a contract is between a _consumer_ (for example, a client that wants to receive some data) and a _provider_ (for example, an API on a server that provides the data the client needs). In microservice architectures, the traditional terms _client_ and _server_ are not always appropriate -- for example, when communication is achieved through message queues. For this reason, we stick to _consumer_ and _provider_ in this documentation. | ||
|
||
### Consumer Driven Contracts | ||
Pact is a code-first [consumer-driven](http://martinfowler.com/articles/consumerDrivenContracts.html) contract testing tool, and is generally used by developers and testers who code. The contract is generated during the execution of the automated consumer tests. A major advantage of this pattern is that only parts of the communication that are actually used by the consumer(s) get tested. This in turn means that any provider behaviour not used by current consumers is free to change without breaking tests. | ||
|
||
Unlike a schema or specification (eg. OAS), which is a static artefact that describes all possible states of a resource, a Pact contract is enforced by executing a collection of test cases, each of which describes a single concrete request/response pair - Pact is, in effect, "contract by example". | ||
|
||
### Provider contract testing | ||
The term "contract testing", or "provider contract testing", is sometimes used in other literature and documentation in the context of a standalone provider application (rather than in the context of an integration). When used in this context, "contract testing" means: a technique for ensuring a provider's actual behaviour conforms to its documented contract (for example, an Open API specification). This type of contract testing helps avoid integration failures by ensuring the provider code and documentation are in sync with each other. On its own, however, it does not provide any test based assurance that the consumers are calling the provider in the correct manner, or that the provider can meet all its consumers' expectations, and hence, it is not as effective in preventing integration bugs. | ||
|
||
## Fleet contracts | ||
We are already running E2E tests for Fleet, defining the scenarios and behaviours using Gherkin (see [here](./e2e/_suites/ingest-manager/features)). As explained above, we now want to verify that the contracts between Kibana Fleet and this project is not broken because of changes in the APIs the tests consume. | ||
|
||
For that reason, we are going to use Pact to get notified whenever the contracts are not satisfied. The steps that we are folowing are: | ||
|
||
1. Create unit tests mocking the HTTP requests/responses for Fleet APIs. As we all know, this approach will always work, as we predefine the mocks, but on the other hand we won't get notified if/when the provider changes, so we must be reactively checking for updates. | ||
1. Create a contract/pact for the consumer (the e2e tests), with the behaviours we expect from Fleet. The result will be a JSON file with the specs. | ||
1. Store the contract in some place that is accesible by the provider. In this case, we are using the file system to store them, but Pact recommends using a [Broker](https://github.com/pact-foundation/pact_broker). | ||
1. Verify the contract/pact from the provider side. The provider is able to check if a change breaks all its consumers by itself, as it has access to the contracts they provided (via file system or the aforementioned Broker). | ||
|
||
>Ideally, the provider project should be the one responsible of the verification but, for simplification, we are creating that verification in this project. Kibana should implement a way to verify contracts/pacts from its own build system, so any engineer is able to check if he/she breaks the consumers. | ||
|
||
### Executing the tests | ||
From root directory, use the following Make targets: | ||
|
||
#### Generate the contracts for the consumer | ||
```shell | ||
$ make pact-consumer | ||
``` | ||
|
||
It will execute Pact (using the [Go implementation](https://github.com/pact-foundation/pact-go/)) to generate the contract for the consumer (the E2E tests), generating a [JSON file](./pacts/e2e_testing_framework-fleet.json) representing the contract. This file will contain all the scenarios defined in the contract, highlighting the following sections: | ||
|
||
- **consumer**: the name of the consumer | ||
- **provider**: the name of the provider | ||
- **interactions**: the scenarios executed in the contract, defining the format of the HTTP request, HTTP headers and HTTP response for each one. It will use regex to handle the response values, so that it's not coupled with the real response data returned by the provider. | ||
- **meta**: Pact specification and version (2.0.0) | ||
|
||
|
||
#### Verify the contracts from provider side | ||
We want to verify that the provider satisfies the contracts. For that reason, we need the provider to be started first, and to achieve it, we are providing the following Make commands: | ||
|
||
```shell | ||
$ make prepare-pact-provider-deps # will run an Elasticsearch, Kibana andd Package Registry | ||
$ make pact-provider # will run the verification of the contracts by itself | ||
$ make verify-provider # will tear down the runtime dependencies | ||
``` | ||
|
||
Each target depends on the one above it, so running `make verify-provider` will run the run the full life cycle. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
verify-provider
seems to call some other make goals -> https://github.com/elastic/e2e-testing/pull/339/files#diff-b67911656ef5d18c4ae36cb6741b7965R47Is the comment correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's on purpose: verify is the last piece in the chain, defining a well-known life cycle: prepare > verify > destroy
I did this that way to support decoupling the destroy goal in the post stage of the CI pipeline (or to be run manually)