Skip to content

feat: ffi verifier cli #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 48 commits into
base: archived/feat/ffi-provider
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
4fdabdd
feat: added rust linux/osx support
elliottmurray Jul 17, 2021
2d7f943
feat: fix to pytest request signature@
elliottmurray Jul 17, 2021
488d55f
feat: first ffi interface
elliottmurray Jul 19, 2021
cf77d09
feat: added so file
elliottmurray Jul 19, 2021
f914c50
fix: so now a relative path so picked up by tests (temp fix) Also som…
elliottmurray Jul 19, 2021
cd85969
chore: move dyn libs to libs folder@
elliottmurray Jul 24, 2021
2b67e39
feat: some work on preparing verify call
elliottmurray Jul 24, 2021
60ac756
feat: refactoring to prepare verify
elliottmurray Jul 24, 2021
7dc8864
fix: make uvicorn versions over 0.14 (#255)
elliottmurray Aug 17, 2021
e370786
chore: Releasing version 1.4.1
elliottmurray Aug 17, 2021
7d18a2f
docs(readme): trivial 'hello world' changes :)
mikegeeves Aug 18, 2021
214c47d
docs(readme): update python versions mentioned to those supported (go…
mikegeeves Aug 18, 2021
a84f856
build(flake8): exclude venv and tox dirs from flake8 linting
mikegeeves Aug 18, 2021
2d30706
build(ffi): use libs from pact dir instead of libs. Bump to 0.0.1. Mi…
mikegeeves Aug 18, 2021
c6ded0a
feat(ffi verifier): very basic call of verify, with no args
mikegeeves Aug 20, 2021
e9c1bb0
feat(ffi verifier): verifier test, looking at log output
mikegeeves Aug 21, 2021
358748f
feat(ffi verifier): verifier test, looking at log output
mikegeeves Aug 21, 2021
070f905
feat(ffi verifier): set log level for output
mikegeeves Aug 21, 2021
cf0bfee
feat(ffi verifier): help and version tests
mikegeeves Aug 21, 2021
f2230b6
chore: Bundle Ruby standalones into dist artifact. (#256)
taj-p Aug 22, 2021
43fedd1
chore: Releasing version 1.4.2
elliottmurray Aug 22, 2021
3471c12
feat(ffi verifier cli): use FFI to determine the args for the CLI wra…
mikegeeves Aug 22, 2021
11228ed
feat(ffi verifier): add possible values e.g. to loglevel
mikegeeves Aug 23, 2021
69233a6
feat(ffi verify): add in default value
mikegeeves Aug 23, 2021
3486281
feat(ffi verifier cli): handle both flags and options, along with mul…
mikegeeves Aug 26, 2021
283dcef
feat(ffi verifier cli): construct args string from inputs. Call pactf…
mikegeeves Aug 27, 2021
411ad66
feat(ffi verifier): add a first (currently broken) test
mikegeeves Aug 27, 2021
bd809ff
feat(ffi verifier cli): call verifier from CLI
mikegeeves Aug 27, 2021
08f0dc0
feat: added support for message provider using pact broker (#257)
pulphix Sep 5, 2021
216229e
chore: Releasing version 1.4.3
elliottmurray Sep 5, 2021
d773d85
Add support for ENVs, tidy, docs
mikegeeves Sep 8, 2021
a2ce9f4
feat(ffi verifier cli): correct return type of cli_args
mikegeeves Sep 8, 2021
65d99d3
feat(ffi verifier): switch to using the log buffer instead of interme…
mikegeeves Sep 8, 2021
ccb2641
feat(ffi verifier cli): adding in real test using httpserver
mikegeeves Sep 8, 2021
273e1f3
feat(ffi verifier cli): both a successful and an unsuccessful verific…
mikegeeves Sep 8, 2021
55f4e55
feat(ffi verifier): add same success and fail tests to the verifier d…
mikegeeves Sep 8, 2021
8701015
feat(ffi verifier): minor tidy
mikegeeves Sep 8, 2021
087a655
feat(ffi verifier): generate Verifier args class by various methods
mikegeeves Sep 8, 2021
f3601fd
Merge branch 'master' into feat/ffi-provider-mike
mikegeeves Sep 13, 2021
741cf99
feat(ffi verifier): tidy, comments
mikegeeves Sep 13, 2021
5703160
Merge branch 'feat/ffi-provider-mike' of https://github.com/mikegeeve…
mikegeeves Sep 13, 2021
b18128a
refactor(setup.py): minor tidy
mikegeeves Sep 13, 2021
5ebf947
feat(ffi verifier): tidying up
mikegeeves Sep 20, 2021
53819eb
feat(ffi verifier cli): tidy usage etc, add info about ENVs being used
mikegeeves Sep 21, 2021
3882837
test(pact): fixing tests, failing after allowRedirect was added elsew…
mikegeeves Sep 21, 2021
3c82f1f
refactor(setup.py): black
mikegeeves Sep 21, 2021
778ef4c
feat(ffi): use the same approach to download the FFI libs as the Ruby…
mikegeeves Sep 21, 2021
f91e9b1
Merge branch 'feat/ffi-provider' into feat/ffi-provider-mike
mikegeeves Sep 21, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
ignore = E226,E302,E41,W503
max-line-length = 160
max-complexity = 10
exclude = venv, .tox
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
### 1.4.3
* 08f0dc0 - feat: added support for message provider using pact broker (#257) (Fabio Pulvirenti, Sun Sep 5 22:49:51 2021 +0200)
### 1.4.2
* f2230b6 - chore: Bundle Ruby standalones into dist artifact. (#256) (Taj Pereira, Sun Aug 22 19:53:53 2021 +0930)
* e370786 - chore: Releasing version 1.4.1 (Elliott Murray, Tue Aug 17 18:55:53 2021 +0100)
* 7dc8864 - fix: make uvicorn versions over 0.14 (#255) (Elliott Murray, Tue Aug 17 18:51:52 2021 +0100)
* da49cd7 - chore: Releasing version 1.4.0 (Elliott Murray, Sat Aug 7 10:17:26 2021 +0100)
* 0089937 - fix: issue originating from snyk with requests and urllib (#252) (Elliott Murray, Sat Jul 31 12:46:15 2021 +0100)
* 903371b - feat: added support for message provider (#251) (Fabio Pulvirenti, Sat Jul 31 13:24:19 2021 +0200)
* 2c81029 - chore(snyk): update fastapi (#239) (Elliott Murray, Fri Jun 11 09:12:38 2021 +0100)
### 1.4.1
* 7dc8864 - fix: make uvicorn versions over 0.14 (#255) (Elliott Murray, Tue Aug 17 18:51:52 2021 +0100)
### 1.4.0
* 0089937 - fix: issue originating from snyk with requests and urllib (#252) (Elliott Murray, Sat Jul 31 12:46:15 2021 +0100)
* 903371b - feat: added support for message provider (#251) (Fabio Pulvirenti, Sat Jul 31 13:24:19 2021 +0200)
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include LICENSE
include *.txt
include *.md
include pact/bin/*
prune pact/test
prune pact/bin
prune e2e
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ define messaging
cd examples/message
pip install -r requirements.txt
pip install -e ../../
pytest
./run_pytest.sh
endef
export messaging

Expand Down
53 changes: 35 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ Note: As of Version 1.0 deprecates support for python 2.7 to allow us to incorpo
# How to use pact-python

## Installation

```
pip install pact-python
```

## Getting started

<!-- Absolute link for rendering page in docs.pact.io -->
A guide follows but if you go to the [e2e examples](https://github.com/pact-foundation/pact-python/tree/master/examples/e2e). This has a consumer, provider and pact-broker set of tests.

## Writing a Pact

Creating a complete contract is a two step process:
Creating a complete contract is a two-step process:

1. Create a test on the consumer side that declares the expectations it has of the provider
2. Create a provider state that allows the contract to pass when replayed against the provider
Expand Down Expand Up @@ -82,7 +84,6 @@ class GetUserInfoContract(unittest.TestCase):
result = user('UserA')

self.assertEqual(result, expected)

```

This does a few important things:
Expand Down Expand Up @@ -164,11 +165,13 @@ The mock service offers you several important features when building your contra
- Finally, it will record your contracts as a JSON file that you can store in your repository or publish to a Pact broker.

## Expecting Variable Content

The above test works great if that user information is always static, but what happens if
the user has a last updated field that is set to the current time every time the object is
modified? To handle variable data and make your tests more robust, there are 3 helpful matchers:

### Term(matcher, generate)

Asserts the value should match the given regular expression. You could use this
to expect a timestamp with a particular format in the request or response where
you know you need a particular format, but are unconcerned about the exact date:
Expand All @@ -194,6 +197,7 @@ provider, the regex will be used to search the response from the real provider s
and the test will be considered successful if the regex finds a match in the response.

### Like(matcher)

Asserts the element's type matches the matcher. For example:

```python
Expand All @@ -202,6 +206,7 @@ Like(123) # Matches if the value is an integer
Like('hello world') # Matches if the value is a string
Like(3.14) # Matches if the value is a float
```

The argument supplied to `Like` will be what the mock service responds with.

When a dictionary is used as an argument for Like, all the child objects (and their child objects etc.) will be matched according to their types, unless you use a more specific matcher like a Term.
Expand Down Expand Up @@ -262,18 +267,18 @@ Format().ip_address # Matches if the value is a ip address

We've created a number of them for you to save you the time:

| matcher | description |
|-----------------|-------------------------------------------------------------------------------------------------|
| `identifier` | Match an ID (e.g. 42) |
| `integer` | Match all numbers that are integers (both ints and longs) |
| `decimal` | Match all real numbers (floating point and decimal) |
| `hexadecimal` | Match all hexadecimal encoded strings |
| `date` | Match string containing basic ISO8601 dates (e.g. 2016-01-01) |
| `timestamp` | Match a string containing an RFC3339 formatted timestapm (e.g. Mon, 31 Oct 2016 15:21:41 -0400) |
| `time` | Match string containing times in ISO date format (e.g. T22:44:30.652Z) |
| `ip_address` | Match string containing IP4 formatted address |
| matcher | description |
|----------------|-------------------------------------------------------------------------------------------------|
| `identifier` | Match an ID (e.g. 42) |
| `integer` | Match all numbers that are integers (both ints and longs) |
| `decimal` | Match all real numbers (floating point and decimal) |
| `hexadecimal` | Match all hexadecimal encoded strings |
| `date` | Match string containing basic ISO8601 dates (e.g. 2016-01-01) |
| `timestamp` | Match a string containing an RFC3339 formatted timestamp (e.g. Mon, 31 Oct 2016 15:21:41 -0400) |
| `time` | Match string containing times in ISO date format (e.g. T22:44:30.652Z) |
| `ip_address` | Match string containing IP4 formatted address |
| `ipv6_address` | Match string containing IP6 formatted address |
| `uuid` | Match strings containing UUIDs |
| `uuid` | Match strings containing UUIDs |

These can be used to replace other matchers

Expand Down Expand Up @@ -399,18 +404,20 @@ The provider application version. Required for publishing verification results.
Publish verification results to the broker.

### Python API

You can use the Verifier class. This has all the same parameters as the cli tool but allows you to write native python code and the test framework of your choice.

```python
verifier = Verifier(provider='UserService',
provider_base_url=PACT_URL)

output, logs = verifier.verify_pacts('./userserviceclient-userservice.json')

```

You can see more details in the [e2e examples](https://github.com/pact-foundation/pact-python/tree/master/examples/e2e/tests/provider/test_provider.py).

### Provider States

In many cases, your contracts will need very specific data to exist on the provider
to pass successfully. If you are fetching a user profile, that user needs to exist,
if querying a list of records, one or more records needs to exist. To support
Expand All @@ -429,19 +436,20 @@ on the provider application or a separate one. Some strategies for managing stat
For more information about provider states, refer to the [Pact documentation] on [Provider States].

# Development

<!-- Absolute link for rendering page in docs.pact.io -->
Please read [CONTRIBUTING.md](https://github.com/pact-foundation/pact-python/blob/master/CONTRIBUTING.md)

To setup a development environment:

1. If you want to run tests for all Python versions, install 2.7, 3.3, 3.4, 3.5, and 3.6 from source or using a tool like [pyenv]
2. Its recommended to create a Python [virtualenv] for the project.
1. If you want to run tests for all Python versions, install 3.6, 3.7, 3.8, and 3.9 from source or using a tool like [pyenv]
2. It's recommended to create a Python [virtualenv] for the project.
3. We are now using FFI bindings. For mac you might want to read these [setup FFI](https://cffi.readthedocs.io/en/latest/installation.html)

The setup the environment, run tests, and package the application, run:
To setup the environment, run tests, and package the application, run:
`make release`

If you are just interested in packaging pact-python so you can install it using pip:
If you are just interested in packaging pact-python you can install it using pip:

`make package`

Expand All @@ -450,6 +458,15 @@ From there you can use pip to install it:

`pip install ./dist/pact-python-N.N.N.tar.gz`

## Offline Installation of Standalone Packages

Although all Ruby standalone applications are predownloaded into the wheel artifact, it may be useful, for development, purposes to install custom Ruby binaries. In which case, use the `bin-path` flag.
```
pip install pact-python --bin-path=/absolute/path/to/folder/containing/pact/binaries/for/your/os
```

Pact binaries can be found at [Pact Ruby Releases](https://github.com/pact-foundation/pact-ruby-standalone/releases).

## Testing

This project has unit and end to end tests, which can both be run from make:
Expand Down
17 changes: 17 additions & 0 deletions examples/ffi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# FFI Examples

This contains the following files which are for reference/information purposes
only i.e. they are not functionally used by end users. They may be used where
documented by developer helper scripts. The files are included here to make it
easier to identify when any changes have occurred in a new version of the Pact
FFI library.

### pact_ffi_verifier_args.json

The various arguments available to the Pact Verifier, both options and flags.
This format is used to construct the CLI arguments for `pact-verifier`, which
calls the method that produces this data each time during runtime.

### pact_ffi_verifier_help.txt

The output from ``pact-verifier --help``
187 changes: 187 additions & 0 deletions examples/ffi/pact_ffi_verifier_args.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
{
"options": [
{
"long": "loglevel",
"short": "l",
"help": "Log level (defaults to warn)",
"possible_values": [
"error",
"warn",
"info",
"debug",
"trace",
"none"
],
"multiple": false
},
{
"long": "file",
"short": "f",
"help": "Pact file to verify (can be repeated)",
"multiple": true
},
{
"long": "dir",
"short": "d",
"help": "Directory of pact files to verify (can be repeated)",
"multiple": true
},
{
"long": "url",
"short": "u",
"help": "URL of pact file to verify (can be repeated)",
"multiple": true
},
{
"long": "broker-url",
"short": "b",
"help": "URL of the pact broker to fetch pacts from to verify (requires the provider name parameter)",
"multiple": false,
"env": "PACT_BROKER_BASE_URL"
},
{
"long": "hostname",
"short": "h",
"help": "Provider hostname (defaults to localhost)",
"multiple": false
},
{
"long": "port",
"short": "p",
"help": "Provider port (defaults to protocol default 80/443)",
"multiple": false
},
{
"long": "scheme",
"help": "Provider URI scheme (defaults to http)",
"possible_values": [
"http",
"https"
],
"default_value": "http",
"multiple": false
},
{
"long": "provider-name",
"short": "n",
"help": "Provider name (defaults to provider)",
"multiple": false
},
{
"long": "state-change-url",
"short": "s",
"help": "URL to post state change requests to",
"multiple": false
},
{
"long": "filter-description",
"help": "Only validate interactions whose descriptions match this filter",
"multiple": false,
"env": "PACT_DESCRIPTION"
},
{
"long": "filter-state",
"help": "Only validate interactions whose provider states match this filter",
"multiple": false,
"env": "PACT_PROVIDER_STATE"
},
{
"long": "filter-no-state",
"help": "Only validate interactions that have no defined provider state",
"multiple": false,
"env": "PACT_PROVIDER_NO_STATE"
},
{
"long": "filter-consumer",
"short": "c",
"help": "Consumer name to filter the pacts to be verified (can be repeated)",
"multiple": true
},
{
"long": "user",
"help": "Username to use when fetching pacts from URLS",
"multiple": false,
"env": "PACT_BROKER_USERNAME"
},
{
"long": "password",
"help": "Password to use when fetching pacts from URLS",
"multiple": false,
"env": "PACT_BROKER_PASSWORD"
},
{
"long": "token",
"short": "t",
"help": "Bearer token to use when fetching pacts from URLS",
"multiple": false,
"env": "PACT_BROKER_TOKEN"
},
{
"long": "provider-version",
"help": "Provider version that is being verified. This is required when publishing results.",
"multiple": false
},
{
"long": "build-url",
"help": "URL of the build to associate with the published verification results.",
"multiple": false
},
{
"long": "provider-tags",
"help": "Provider tags to use when publishing results. Accepts comma-separated values.",
"multiple": false
},
{
"long": "base-path",
"help": "Base path to add to all requests",
"multiple": false
},
{
"long": "consumer-version-tags",
"help": "Consumer tags to use when fetching pacts from the Broker. Accepts comma-separated values.",
"multiple": false
},
{
"long": "consumer-version-selectors",
"help": "Consumer version selectors to use when fetching pacts from the Broker. Accepts a JSON string as per https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/",
"multiple": false
},
{
"long": "include-wip-pacts-since",
"help": "Allow pacts that don't match given consumer selectors (or tags) to be verified, without causing the overall task to fail. For more information, see https://pact.io/wip",
"multiple": false
},
{
"long": "request-timeout",
"help": "Sets the HTTP request timeout in milliseconds for requests to the target API and for state change requests.",
"multiple": false
}
],
"flags": [
{
"long": "state-change-as-query",
"help": "State change request data will be sent as query parameters instead of in the request body",
"multiple": false
},
{
"long": "state-change-teardown",
"help": "State change teardown requests are to be made after each interaction",
"multiple": false
},
{
"long": "publish",
"help": "Enables publishing of verification results back to the Pact Broker. Requires the broker-url and provider-version parameters.",
"multiple": false
},
{
"long": "disable-ssl-verification",
"help": "Disables validation of SSL certificates",
"multiple": false
},
{
"long": "enable-pending",
"help": "Enables Pending Pacts",
"multiple": false
}
]
}
Loading