Giter Site home page Giter Site logo

pact-foundation / pact-python Goto Github PK

View Code? Open in Web Editor NEW
565.0 21.0 136.0 13.2 MB

Python version of Pact. Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.

Home Page: http://pact.io

License: MIT License

Makefile 0.14% Python 99.51% Dockerfile 0.12% Shell 0.22%
hacktoberfest pact contract-testing apis smartbear-supported

pact-python's Introduction

Pact Python

Fast, easy and reliable testing for your APIs and microservices.
Package Version Python Versions Downloads
CI/CD Test Status Build Status Build Status
Meta Hatch project linting - Ruff style - Ruff types - Mypy License
Community Slack Stack Overflow Twitter
Pact is the de-facto API contract testing tool. Replace expensive and brittle end-to-end integration tests with fast, reliable and easy to debug unit tests.
  • ⚡ Lightning fast
  • 🎈 Effortless full-stack integration testing - from the front-end to the back-end
  • 🔌 Supports HTTP/REST and event-driven systems
  • 🛠️ Configurable mock server
  • 😌 Powerful matching rules prevents brittle tests
  • 🤝 Integrates with Pact Broker / PactFlow for powerful CI/CD workflows
  • 🔡 Supports 12+ languages

Why use Pact? Contract testing with Pact lets you:

  • ⚡ Test locally
  • 🚀 Deploy faster
  • ⬇️ Reduce the lead time for change
  • 💰 Reduce the cost of API integration testing
  • 💥 Prevent breaking changes
  • 🔎 Understand your system usage
  • 📃 Document your APIs for free
  • 🗄 Remove the need for complex data fixtures
  • 🤷‍♂️ Reduce the reliance on complex test environments

Watch our series on the problems with end-to-end integrated tests, and how contract testing can help.

Documentation

This readme provides a high-level overview of the Pact Python library. For detailed documentation, please refer to the full Pact Python documentation. For a more general overview of Pact and the rest of the ecosystem, please refer to the Pact documentation.

Documentation for the API is generated from the docstrings in the code which you can view here. Please be aware that only the [pact.v3 module][pact.v3] is thoroughly documented at this time.

Need Help

V3 Preview

Pact Python is currently undergoing a major rewrite which will be released with the 3.0.0 version. This rewrite will replace the existing Ruby backend with a Rust backend which will provide a significant performance improvement and will allow us to support more features in the future. You can find more information about this rewrite in this tracking issue on GitHub.

You can preview the new version by using the [pact.v3 module][pact.v3]. The new version is not yet feature complete, and may be subject to changes. Having said that, we would love to get your feedback on the new version:

Installation

The latest version of Pact Python can be installed from PyPi:

pip install pact-python
# 🚀 now write some tests!

Requirements

Pact Python tries to support all versions of Python that are still supported by the Python Software Foundation. Older version of Python may work, but are not officially supported.

In order to support the broadest range of use cases, Pact Python tries to impose the least restrictions on the versions of libraries that it uses.

Do Not Track

In order to get better statistics as to who is using Pact, we have an anonymous tracking event that triggers when Pact installs for the first time. The only things we track are your type of OS, and the version information for the package being installed. No personally identifiable information is sent as part of this request. You can disable tracking by setting the environment variable PACT_DO_NOT_TRACK=1:

Contributing

We welcome contributions to the Pact Python library in many forms. There are many ways to help, from writing code, to providing new examples, to writing documentation, to testing the library and providing feedback. For more information, see the contributing guide.

Table of contributors

pact-python's People

Contributors

alecgerona avatar b3nnyl avatar bassdread avatar bethesque avatar dependabot[bot] avatar dhoomakethu avatar dlmiddlecote avatar elliottmurray avatar ftobia avatar hartror avatar jp-ellis avatar jslvtr avatar jstoebel avatar m-aciek avatar matthewbalvanz-wf avatar mefellows avatar mikahjc avatar mikegeeves avatar pulphix avatar pyasi avatar renovate[bot] avatar sergeyklay avatar simkev2 avatar snyk-bot avatar thatguysimon avatar tuan-pham avatar valkolovos avatar williaminfante avatar yangineer avatar you54f avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pact-python's Issues

Setup

Im currently trying to get some very simple python pact examples running. I tried a bunch of projects. But either they were to unspecific or just didnt work for me.. python pact testing example seamed to be the most simple one. So i tried it. Unfortunately im not even getting this one to run.
What it did:

downloaded the project
followed the description and did the install & execution
Im getting the folling error

invoke test_consumer
============================= test session starts ==============================
platform linux2 -- Python 2.7.12, pytest-3.5.0, py-1.5.3, pluggy-0.6.0
rootdir: /home/ubuntu/python-pact-testing-example, inifile:
collected 0 items / 1 errors

==================================== ERRORS ====================================
______________________ ERROR collecting test_consumer.py _______________________
test_consumer.py:11: in <module>
    pact.start_service()
/usr/local/lib/python2.7/dist-packages/pact/pact.py:161: in start_service
    self._process = Popen(command)
/usr/lib/python2.7/subprocess.py:711: in __init__
    errread, errwrite)
/usr/lib/python2.7/subprocess.py:1343: in _execute_child
    raise child_exception
E   OSError: [Errno 2] No such file or directory
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.28 seconds ============================

Now i have a couple of questions:

General pact paython question; project independent:
Do i have to install and run the pact mock service independently or should this be done automatically?
Is there a detailed guideline or an simple to run example (complete) available?
I pact python mature enough? Just for simple and demostrative issues?

Project specific:
Why does the example fail?
Do i need any additional packages?

pact-verifier always results in an error when using pact broker with authentication

When I run:

pact-verifier --provider-base-url http://localhost:7599 --pact-urls https://my.pact.broker/pacts/provider/my-provider/consumer/my-consumer/latest --pact-broker-username username --pact-broker-password password

I always get:

ERROR: "pact-provider-verifier.rb verify" was called with arguments ["--pact-broker-username=username", "--pact-broker-password=password"]
Usage: "pact-provider-verifier.rb verify -h, --provider-base-url=PROVIDER_BASE_URL -u, --pact-urls=PACT_URLS"

Contributors wanted: support V3+ of the pact specification (via the pact rust core)

The ask from the community

The README says you currently support V2 of the spec, please support V3 as well.

Our response

Thank you, we would <3 to see support for v3, and beyond in pact-python. It will involve migrating pact-python from the current ruby based reference implementation (the core), to a rust based reference implementaiton.

We are severely lacking in willing participants, and we are happy to lend a hand in moving things forward <3

If you would love to practise some python and become a pythonista, or you are a seasoned pythonista, drop into #88 and give us a shout!

Current state of play

There has been a few attempts so far at helping tickle along progress of Pact-Python to utilise the new Rust Core.

2 on the verifier side

Examples of python integrating with the FFI

I've put together a demonstration of Python and the Pact FFI based on some of the work done by awesome folk above.

Pact reference

dev rel samples

These are for the consumer side, showing up to v4 Pact's being generated, and utilising the new Pact plugin framework

You can play with it in your browser here

The ask from you

Review the following project tracking is here

https://github.com/pact-foundation/pact-python/projects/1

Get involved!

We would love to find new maintainers or long term contributors to the projects, so would appreciate anyone sharing the word out amongst fellow Pythonista's and see if we can bring this to the masses

Workaround for python provider teams, being provided v3/v4 pacts

You can use the standalone verifier (based on the rust core) as an interim measure

https://docs.pact.io/implementation_guides/cli#native-binary-new

Real Workaround for python provider teams, being provided v3/v4 pacts

  • Help review the outstanding PR's
  • Fork the project and propose a PR
  • Let us know you want to get involved and we can run a hack day

Edits

  1. Update to provide a coherent response with actionable items at a top level

Provider state teardown

Hi,

I went through the doc and tried to check the implementation but I could not find a any way to provide a teardown callback for a particular provider state.
Is this possible right know and I am missing something or there is no such functionality yet?
Was this previously considered? If so, or not, were there any ideas that we could push forward, possibly that I could try to implement?
I could see that for pact-jvm this option is available pact-foundation/pact-jvm#568.

I was thinking whether this could be done the very same way that setting provider state is being done now, just another URL that will accept the details

@edit.
Now that I think of it, most of the time teardown will be provided by the application that listens on provider-states-setup-url.
The only thing that is missing in current pact-verifier implementation is a way to tell pact-verifier that once the provider state was set and test was executed it needs to call provider-states-teardown-url (or something) with the very same consumer name and state (optionally). The underlying application would know what to do.

Using Term causes the consumer test to fail if self.assertEqual is used

My code:

   expected = {
      u'name':u'#3455',
      u'timestamp': Term('\d+-\d+-\d+T\d+:\d+:\d+.+', u'2017-09-17T19:43:12+03:00'),
    }

    (pact
     .given('build 3455 exists')
     .upon_receiving('a request for build 3455')
     .with_request('get', '/builds/3455')
     .will_respond_with(200, body=expected))


    with pact:
      result = client.build(3455)

    self.assertEqual(result, expected)

causes:

FAIL: test_get_build (build_test.GetBuildInfoContract)

Traceback (most recent call last):
File "build_test.py", line 38, in test_get_build
self.assertEqual(result, expected)
AssertionError: {u'timestamp': u'2017-09-17T19:43:12+03:00', u'name': u'#3455'} != {u'timestamp': <pact.matchers.Term object at 0x1019355d0>, u'name': u'#3455'}

  • {u'name': u'#3455', u'timestamp': u'2017-09-17T19:43:12+03:00'}
  • {u'name': u'#3455', u'timestamp': <pact.matchers.Term object at 0x1019355d0>}

Ran 1 test in 0.035s

FAILED (failures=1)

the pact file is written ok but I'd expect this to succeed

ImportError: No module named requests

Is there a missing dependency declaration, or am I just a python noob?

$ pip install pact-python
Collecting pact-python
  Downloading pact-python-0.6.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/c8/ypphsm1d4gq3klcygh889hjm0000gn/T/pip-build-ffGYmj/pact-python/setup.py", line 14, in <module>
        import pact
      File "pact/__init__.py", line 2, in <module>
        from .consumer import Consumer
      File "pact/consumer.py", line 2, in <module>
        from .pact import Pact
      File "pact/pact.py", line 7, in <module>
        import requests
    ImportError: No module named requests

pact-verifier fails when running against a service using SSL

I am attempting to verify my contract against a running provider. The provider uses SSL verification, and When I run pact-verifier, all I get is a bunch of SSL errors. pact-verifier does not provide a way to disable SSL verification.

Failures:

  1) Verifying a pact between consumer and provider Given A service is deployed A request for a service with GET /api/services/contract/test/my_service returns a response which has status code 200
     Failure/Error: replay_interaction interaction

     OpenSSL::SSL::SSLError:
       SSL_connect returned=1 errno=0 state=error: certificate verify failed
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/ruby/lib/ruby/2.2.0/net/http.rb:923:in `connect'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/ruby/lib/ruby/2.2.0/net/http.rb:923:in `block in connect'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/ruby/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/ruby/lib/ruby/2.2.0/net/http.rb:923:in `connect'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/ruby/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/ruby/lib/ruby/2.2.0/net/http.rb:858:in `start'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rack-proxy-0.6.1/lib/rack/http_streaming_response.rb:71:in `session'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rack-proxy-0.6.1/lib/rack/http_streaming_response.rb:60:in `response'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rack-proxy-0.6.1/lib/rack/http_streaming_response.rb:29:in `headers'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-proxy-2.1.0/vendor/rack-reverse-proxy/lib/rack/reverse_proxy.rb:77:in `proxy'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-proxy-2.1.0/vendor/rack-reverse-proxy/lib/rack/reverse_proxy.rb:29:in `call'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rack-test-0.6.3/lib/rack/test.rb:58:in `get'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/test_methods.rb:23:in `replay_interaction'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec.rb:82:in `block (4 levels) in describe_interaction'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec.rb:171:in `run_once'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec.rb:79:in `block (3 levels) in describe_interaction'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:447:in `instance_exec'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:447:in `instance_exec'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:350:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:507:in `block in run_owned_hooks_for'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:506:in `each'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:506:in `run_owned_hooks_for'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:593:in `block in run_example_hooks_for'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:592:in `reverse_each'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:592:in `run_example_hooks_for'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:462:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:494:in `run_before_example'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:253:in `block in run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:500:in `block in with_around_and_singleton_context_hooks'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:457:in `block in with_around_example_hooks'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:464:in `block in run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:602:in `run_around_example_hooks_for'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:464:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:457:in `with_around_example_hooks'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:500:in `with_around_and_singleton_context_hooks'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:251:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:627:in `block in run_examples'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:623:in `map'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:623:in `run_examples'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:589:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `map'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:1894:in `with_suite_hooks'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:113:in `block in run_specs'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/reporter.rb:79:in `report'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:112:in `run_specs'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:87:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:71:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:94:in `run_specs'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:35:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:60:in `run_with_pact_uri'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:48:in `run_specs'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:22:in `call'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:14:in `call'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:66:in `block in verify_pacts'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in `collect'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in `verify_pacts'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/cli.rb:21:in `verify'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
     # /usr/local/lib/python2.7/dist-packages/pact/bin/pact/lib/app/pact-provider-verifier.rb:2:in `<main>'

The verifier always returns exit code 0

When invoking the underlying Ruby library the popen call doesn't communicate and as such always returns the exit code None which ends up being 0.

pact-python/pact/verify.py

Lines 139 to 143 in 589224a

p = subprocess.Popen(command, bufsize=1, env=env, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, universal_newlines=True)
sanitize_logs(p, verbose)
sys.exit(p.returncode)

If the code is changed to issue communicate on the pipe it'll wait and return the actual returncode at the end, so we can use the exit code properly. :)

That is:

    p = subprocess.Popen(command, bufsize=1, env=env, stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT, universal_newlines=True)

    sanitize_logs(p, verbose)
    try:
        p.communicate(timeout=timeout * 2)
    except TimeoutExpired:
        p.kill()

    sys.exit(p.returncode)

I'm not actually running the verifier from the CLI but rather I'm invoking the main from inside a test, because I want pact to just run as part of my whole suite instead of as a completely separate process. It was a bit iffy to make invoke click, but possible. That said, it would be nice if invoking the verifier from inside of Python code didn't have to be done through click and instead on a normal python function. :)

Execution hangs with error - 'C:\Program Files (x86)\Python36-32\Lib\site-packages\pact\bin\pact\lib\ruby\bin..\bin.real\ruby.exe: No such file or directory -- Files (LoadError)'

I am new to pact and am trying to run the pact tests in python , but get this error every time 'C:\Program Files (x86)\Python36-32\Lib\site-packages\pact\bin\pact\lib\ruby\bin..\bin.real\ruby.exe: No such file or directory -- Files (LoadError)' and the execution hangs there ? i see that the file exists in the path . How do i run the tests ? i run from the terminal using 'python -m unittest python-filename'

python version - 3.6.1
os - win 8

`socket.gaierror: [Errno 8] nodename nor servname provided, or not known` when running Pact test

I am trying to start using Pact. I'm using Python 3.6 installed with Miniconda (https://conda.io/miniconda.html).

My environment.yml is below. You can create it with conda env create after you put environment.yml in your directory. I have a Pact test written using Pytest.

The test looks like:

tests/api_pact_test.py

import atexit
from pact import Consumer, Provider

pact = Consumer('Consumer').has_pact_with(Provider('Provider'), host_name='mockservice', port=9188)
pact.start_service()
atexit.register(pact.stop_service)


def test_check_status():
    (pact
     .given('The API is alive')
     .upon_receiving('a status check')
     .with_request(method='get',
                   path='/status',
                   body=None,
                   headers={'x-api-key': 'keygoeshere',
                            'If-Modified-Since': 'Wed, 14 Mar 2018 21:17:29 GMT'})
     .will_respond_with(200, body=None))

I know this isn't a full test, but I've been trying to get as bare-bones as possible. When I run the test python -m pytest I get the following error:

============================================================= ERRORS =============================================================
____________________________________________ ERROR collecting tests/api_pact_test.py _____________________________________________
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/connection.py:141: in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/util/connection.py:60: in create_connection
    for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
../../../miniconda3/envs/deckard/lib/python3.6/socket.py:743: in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
E   socket.gaierror: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/connectionpool.py:601: in urlopen
    chunked=chunked)
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/connectionpool.py:357: in _make_request
    conn.request(method, url, **httplib_request_kw)
../../../miniconda3/envs/deckard/lib/python3.6/http/client.py:1239: in request
    self._send_request(method, url, body, headers, encode_chunked)
../../../miniconda3/envs/deckard/lib/python3.6/http/client.py:1285: in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
../../../miniconda3/envs/deckard/lib/python3.6/http/client.py:1234: in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
../../../miniconda3/envs/deckard/lib/python3.6/http/client.py:1026: in _send_output
    self.send(msg)
../../../miniconda3/envs/deckard/lib/python3.6/http/client.py:964: in send
    self.connect()
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/connection.py:166: in connect
    conn = self._new_conn()
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/connection.py:150: in _new_conn
    self, "Failed to establish a new connection: %s" % e)
E   urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x10b6a0b70>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known

During handling of the above exception, another exception occurred:
tests/api_pact_test.py:13: in <module>
    pact.start_service()
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/pact/pact.py:162: in start_service
    self._wait_for_server_start()
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/pact/pact.py:261: in _wait_for_server_start
    resp = s.get(self.uri, headers=self.HEADERS)
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/requests/sessions.py:521: in get
    return self.request('GET', url, **kwargs)
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/requests/sessions.py:508: in request
    resp = self.send(prep, **send_kwargs)
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/requests/sessions.py:618: in send
    r = adapter.send(request, **kwargs)
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/requests/adapters.py:440: in send
    timeout=timeout
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/connectionpool.py:639: in urlopen
    _stacktrace=sys.exc_info()[2])
../../../miniconda3/envs/deckard/lib/python3.6/site-packages/urllib3/util/retry.py:337: in increment
    total -= 1
E   TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'

environment.yml

name: my_env
channels:
- defaults
dependencies:
- certifi=2017.*
- mkl=2017.0.3=0
- numpy=1.13.1=py36_0
- openssl=1.0.*
- pandas=0.20.3=py36_0
- pip=9.0.1=py36_1
- py=1.4.34=py36_0
- pytest=3.2.1=py36_0
- python=3.6.2=0
- python-dateutil=2.6.1=py36_0
- pytz=2017.2=py36_0
- readline=6.2=2
- requests=2.14.2=py36_0
- Sphinx==1.6.3
- scikit-learn=0.19.0=np113py36_0
- scipy=0.19.1=np113py36_0
- setuptools=36.4.0=py36_0
- six=1.10.0=py36_0
- sqlite=3.13.0=0
- tk=8.5.18=0
- wheel=0.29.0=py36_0
- xz=5.2.3=0
- zlib=1.2.11=0
- pip:
  - pact-python==0.16.*
  - asn1crypto==0.23.0
  - awscli==1.11.156
  - boto==2.48.0
  - boto3==1.4.7
  - botocore==1.7.14
  - cffi==1.11.2
  - chardet==3.0.4
  - colorama==0.3.7
  - contexttimer==0.3.3
  - cookies==2.2.1
  - cryptography==2.1.1
  - daiquiri==1.3.0
  - dicttoxml==1.7.4
  - docker==2.5.1
  - docker-pycreds==0.2.1
  - docutils==0.14
  - idna==2.6
  - jinja2==2.9.6
  - jmespath==0.9.3
  - markupsafe==1.0
  - mock==2.0.0
  - moto==1.1.21
  - pbr==3.1.1
  - pyaml==17.8.0
  - pyasn1==0.3.5
  - pycparser==2.18
  - pyyaml==3.12
  - recommonmark==0.4.0
  - requests==2.18.4
  - rsa==3.4.2
  - s3transfer==0.1.11
  - urllib3==1.22
  - websocket-client==0.44.0
  - werkzeug==0.12.2
  - xmltodict==0.11.0
  - sphinx_rtd_theme==0.2.5b1
  - mypy
  - pylint

Pact-Python verifier fails to verify against remote broker

pact-verifier --provider-base-url=http://localhost:8081 --pact-broker-username MyBasicAuthUser123 --pact-broker-password MyBasicAuthPassword123 --pact-urls https://myremotebroker.pact.dius.com.au/

shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory chdir: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory chdir: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory chdir: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory chdir: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/shared_helpers.rb:53:in chdir': No such file or directory - getcwd (Errno::ENOENT)
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/shared_helpers.rb:53:in block in chdir' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/2.2.0/monitor.rb:211:in mon_synchronize'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/shared_helpers.rb:52:in chdir' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler.rb:363:in load_gemspec_uncached'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler.rb:353:in load_gemspec' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/dsl.rb:53:in gemspec'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/vendor/Gemfile:3:in eval_gemfile' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/dsl.rb:32:in instance_eval'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/dsl.rb:32:in eval_gemfile' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/dsl.rb:10:in evaluate'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/definition.rb:25:in build' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler.rb:155:in definition'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler.rb:118:in setup' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/gems/2.2.0/gems/bundler-1.9.9/lib/bundler/setup.rb:8:in <top (required)>'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:128:in require' from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:128:in rescue in require'
from /Library/Python/2.7/site-packages/pact/bin/verifier/lib/ruby/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:39:in require'

run e2e example, get error.

use python 3.6.0 and pact1.10.0. when pact-verifier --provider-base-url=http://localhost:5000 ./pacts/consumer-provider.json, get these errors:

  1. Verifying a pact between consumer and provider Given a simple json blob exists a request for a user with GET /users/Jonas returns a response which has a matching body
    Failure/Error: expect(response_body).to match_term expected_response_body, diff_options

    Actual:

    Diff

    Key: - is expected
    + is actual
    Matching keys and values are not shown

    -{

    • "name": "Jonas"
      -}

    Description of differences

    • Expected a Hash but got a String ("") at $.
      My computer region setting is set as Chinese. It looks like something wrong with ruby encoding.
      Does anyone have a way to solve this? Thanks.

Suggestion: rename SomethingLike to just Like

When the SomethingLike was invented, it was a bit of a hack to help out with some brittle tests we had at REA, and I never thought it would become the standard tool it has become! In the other implementations, we're using just the name "Like" rather than "SomethingLike". It's a bit pithier. Can I suggest that you do the same for python?

Allow pacts to be stored in a specified directory

Hi there,
First of all: Great, that you have created pact-python! I was just in the process of trying to resuscitate another pact implementation for Python. Yours, however, is much nicer.
Here is my feature request in story form (as you seem to prefer them that way):

As a user creating consumer contracts,
I want to be able to specify a directory in which pacts, that have been successfully verified are stored,
and I want that pact files are named "sensibly" and that name clashes are automatically resolved,
So that I do not have to use a docker volume to collect pacts.

The idea would be to allow a directory to be specified in the has_pact_with() method which will be passed to the Pact instance. Then the pact returned by the POST to /pact in Pact.__exit__() can be saved to a file.
If there are no objections, I would be happy to submit a pull request!

Could not install pact-python using pip

Python version: 3.6.0
OS: Windows 10

Description:
When I try to install python using pip install pact-python as per the instructions. I get the following error message:

Could not find a version that satisfies the requirement pact-python (from versions: )
No matching distribution found for pact-python

I'm not sure if others are seeing this.

On another note.. it looks like this is in beta, any ideas on the full release? Is it 3-6 months away? or more?

Cannot supply multiple files to pact-verifier

According to the README, to supply multiple local pact files you give the --pact-urls argument a comma separated list of files.

However, this will give you an error that the file cannot be found and that file is the combined paths,

Error: The following Pact files could not be found:
/tmp/pacts/pact1.json,/tmp/pacts/pact2.json

when they should be separated by a new line.

This is because for the click option --pact-urls the parameter multiple=True is used. However this is meant for providing multiple --pact-urls flags such as

pact-verifier --pact-urls=./provider/pact1.json --pact-urls=./provider/pact2.json

http://click.pocoo.org/5/options/#multiple-options

Either the documentation should be updated to list that you should provide an argument for each file, or remove multiple=True and just do a .split(',') when reading the pact-urls argument.

Support matchingRules

If I'm not mistaken, this is currently not supported by the pact-verifier.
It would be great to support it since it's part of V2 spec

MockService blocks test execution if pact-python is installed in system Python's site-packages

Package versions:

  • pact-python 0.14.0
  • Python 3.6.3 from official docker image

When installing pact-python into system-Python's site-packages, which is quite common when using a docker container, the Mock-Service cannot be started if the Python tests in the docker-container are not executed with root permissions.

Basically I have a test that creates a pact.Consumer and then calls consumer.pact.start_service() to run the mock service within a pytest fixture. That's roughly equivalent to:

import pact

consumer = pact.Consumer('consumer').has_pact_with(
    provider=pact.Provider('provider'),
    host_name='localhost',
    mock_port=1234,
)
consumer.pact.start_service()

# Execute test here.
# Tests want to access the running mock-service.

consumer.pact.stop_service()

However, during consumer.service_start() the MockService tries to modify its Gemfile.lock which is located at /usr/local/lib/python3.6/site-packages/pact/bin/pact/lib.
When running the docker container without root permissions, this file cannot be modified.

pytest prints the error message when invoked with -s (no capture) flag:

There was an error while trying to write to Gemfile.lock. It is likely that 
you need to allow write permissions for the file at path: 
/usr/local/lib/python3.6/site-packages/pact/bin/pact/lib/vendor/Gemfile.lock

I posted a pull request (#72) for a related problem, which is that during the call to consumer.pact.server_start() the Pact._wait_for_server_start method retries a connection to the started MockService 15 times. With the implementation of urllib3.utils.retry.Retry with a backoff_factor of 0.1 that means 54 minutes wait time before the tests actually fail.

Thus it appears as if the tests would simply block. In combination with pytest's output capturing this was pretty hard to spot. :)

I don't really know Ruby, so I cannot tell why the Gemfile.lock has to be modified when starting the MockService. However, when installed as a vendored library of a global Python site-package, that doesn't work.
Maybe you could download the vendored ruby libs to a temporary / cache directory?

pact verification issue

Hi,
I am new to contract testing and I am trying to find out how it works.
I have copied animal example and started animal service:

Animal Profile Service listening on http://localhost:8081
Animal Matching Service listening on http://localhots:8080

I have started also pact mock service locally

My code looks like that:

pact = Consumer('Consumer').has_pact_with(Provider('Provider'), host_name='localhost', port=1234)  

class ContractTest(unittest.TestCase):

    def test_first(self):
        url = 'http://localhost:8081/animals/1'
        response = requests.get(url)
        print(response.status_code)
        print(response.json())
        expected = {'first_name': 'Billy', 'last_name': 'Goat', 'animal': 'goat', 'age': 21, 'gender': 'M', 'location': {'description': 'Melbourne Zoo', 'country': 'Australia', 'post_code': 3000},
                    'eligibility': {'available': True, 'previously_married': False}, 'interests': ['walks in the garden/meadow', 'munching on a paddock bomb', 'parkour'], 'id': 1}

        (pact
         .given('UserA exists and is not an administrator')
         .upon_receiving('a request for UserA')
         .with_request('get', '/animals/1')
         .will_respond_with(200, body=expected))

        with pact:
            result = requests.get(url)
        self.assertEqual(result, expected)
        # self.assertEqual(response.json(), expected)

When I am running my test I am getting Missing Request warning and tests fails
Here is mock service console output:

D:\Pact_Mock_Service\pact-mock-service-2.1.0-1-win32>.\bin\pact-mock-service.bat -p 1234
[2017-07-14 13:35:17] INFO  WEBrick 1.3.1
[2017-07-14 13:35:17] INFO  ruby 2.2.2 (2015-04-13) [i386-mingw32]
[2017-07-14 13:35:17] INFO  WEBrick::HTTPServer#start: pid=13608 port=1234
I, [2017-07-14T13:35:28.695586 #13608]  INFO -- : Cleared interactions before example ""
I, [2017-07-14T13:35:28.732112 #13608]  INFO -- : Cleared interactions before example ""
I, [2017-07-14T13:35:28.740117 #13608]  INFO -- : Registered expected interaction GET /animals/1
D, [2017-07-14T13:35:28.740618 #13608] DEBUG -- : {
  "description": "a request for UserA",
  "providerState": "UserA exists and is not an administrator",
  "request": {
    "method": "get",
    "path": "/animals/1"
  },
  "response": {
    "status": 200,
    "headers": {
    },
    "body": {
      "first_name": "Billy",
      "last_name": "Goat",
      "animal": "goat",
      "age": 21,
      "gender": "M",
      "location": {
        "description": "Melbourne Zoo",
        "country": "Australia",
        "post_code": 3000
      },
      "eligibility": {
        "available": true,
        "previously_married": false
      },
      "interests": [
        "walks in the garden/meadow",
        "munching on a paddock bomb",
        "parkour"
      ],
      "id": 1
    }
  }
}
W, [2017-07-14T13:35:28.761633 #13608]  WARN -- : Verifying - actual interactions do not match expected interactions for example "".
Missing requests:
        GET /animals/1


W, [2017-07-14T13:35:28.761633 #13608]  WARN -- : Missing requests:
        GET /animals/1

Is this a verification issue or is my code wrong? (if my code is wrong then how can I fix it?)

pip fails to find pact-mock-service-linux-x64.tar.gz

i tried to install pack-python in a venv and it ended up with the following error

(testing1)iob@iob-pc:~/Devel/packtesting$ pip install pact-python/.
Processing ./pact-python
Requirement already satisfied (use --upgrade to upgrade): requests==2.12.3 in /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages (from pact-python==0.1.0)
Requirement already satisfied (use --upgrade to upgrade): six==1.10.0 in /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages (from pact-python==0.1.0)
Building wheels for collected packages: pact-python
  Running setup.py bdist_wheel for pact-python
  Complete output from command /home/iob/.virtualenvs/testing1/bin/python -c "import setuptools;__file__='/tmp/pip-vDkaMF-build/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" bdist_wheel -d /tmp/tmp0heJ4Ypip-wheel-:
  running bdist_wheel
  running build
  running build_py
  creating build
  creating build/lib.linux-x86_64-2.7
  creating build/lib.linux-x86_64-2.7/e2e
  copying e2e/app.py -> build/lib.linux-x86_64-2.7/e2e
  copying e2e/__init__.py -> build/lib.linux-x86_64-2.7/e2e
  creating build/lib.linux-x86_64-2.7/pact
  copying pact/consumer.py -> build/lib.linux-x86_64-2.7/pact
  copying pact/pact.py -> build/lib.linux-x86_64-2.7/pact
  copying pact/__init__.py -> build/lib.linux-x86_64-2.7/pact
  copying pact/provider.py -> build/lib.linux-x86_64-2.7/pact
  copying pact/matchers.py -> build/lib.linux-x86_64-2.7/pact
  installing to build/bdist.linux-x86_64/wheel
  running install
  running install_lib
  creating build/bdist.linux-x86_64
  creating build/bdist.linux-x86_64/wheel
  creating build/bdist.linux-x86_64/wheel/e2e
  copying build/lib.linux-x86_64-2.7/e2e/app.py -> build/bdist.linux-x86_64/wheel/e2e
  copying build/lib.linux-x86_64-2.7/e2e/__init__.py -> build/bdist.linux-x86_64/wheel/e2e
  creating build/bdist.linux-x86_64/wheel/pact
  copying build/lib.linux-x86_64-2.7/pact/consumer.py -> build/bdist.linux-x86_64/wheel/pact
  copying build/lib.linux-x86_64-2.7/pact/pact.py -> build/bdist.linux-x86_64/wheel/pact
  copying build/lib.linux-x86_64-2.7/pact/__init__.py -> build/bdist.linux-x86_64/wheel/pact
  copying build/lib.linux-x86_64-2.7/pact/provider.py -> build/bdist.linux-x86_64/wheel/pact
  copying build/lib.linux-x86_64-2.7/pact/matchers.py -> build/bdist.linux-x86_64/wheel/pact
  running install_egg_info
  running egg_info
  creating pact_python.egg-info
  writing requirements to pact_python.egg-info/requires.txt
  writing pact_python.egg-info/PKG-INFO
  writing top-level names to pact_python.egg-info/top_level.txt
  writing dependency_links to pact_python.egg-info/dependency_links.txt
  writing manifest file 'pact_python.egg-info/SOURCES.txt'
  warning: manifest_maker: standard file '-c' not found
  
  reading manifest file 'pact_python.egg-info/SOURCES.txt'
  reading manifest template 'MANIFEST.in'
  warning: no files found matching '*.gz'
  no previously-included directories found matching '*test'
  no previously-included directories found matching 'e2e/*'
  writing manifest file 'pact_python.egg-info/SOURCES.txt'
  Copying pact_python.egg-info to build/bdist.linux-x86_64/wheel/pact_python-0.1.0-py2.7.egg-info
  running install_scripts
  error: [Errno 2] No such file or directory: 'build/bdist.linux-x86_64/wheel/pact/bin/pact-mock-service-linux-x64.tar.gz'
  
  ----------------------------------------
  Failed building wheel for pact-python
Failed to build pact-python
Installing collected packages: pact-python
  Running setup.py install for pact-python
    Complete output from command /home/iob/.virtualenvs/testing1/bin/python -c "import setuptools, tokenize;__file__='/tmp/pip-vDkaMF-build/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-d4ziQV-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/iob/.virtualenvs/testing1/include/site/python2.7/pact-python:
    running install
    running build
    running build_py
    running install_lib
    creating /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/e2e
    copying build/lib.linux-x86_64-2.7/e2e/app.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/e2e
    copying build/lib.linux-x86_64-2.7/e2e/__init__.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/e2e
    creating /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact
    copying build/lib.linux-x86_64-2.7/pact/consumer.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact
    copying build/lib.linux-x86_64-2.7/pact/pact.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact
    copying build/lib.linux-x86_64-2.7/pact/__init__.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact
    copying build/lib.linux-x86_64-2.7/pact/provider.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact
    copying build/lib.linux-x86_64-2.7/pact/matchers.py -> /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/e2e/app.py to app.pyc
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/e2e/__init__.py to __init__.pyc
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact/consumer.py to consumer.pyc
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact/pact.py to pact.pyc
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact/__init__.py to __init__.pyc
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact/provider.py to provider.pyc
    byte-compiling /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact/matchers.py to matchers.pyc
    running install_egg_info
    running egg_info
    writing requirements to pact_python.egg-info/requires.txt
    writing pact_python.egg-info/PKG-INFO
    writing top-level names to pact_python.egg-info/top_level.txt
    writing dependency_links to pact_python.egg-info/dependency_links.txt
    warning: manifest_maker: standard file '-c' not found
    
    reading manifest file 'pact_python.egg-info/SOURCES.txt'
    reading manifest template 'MANIFEST.in'
    warning: no files found matching '*.gz'
    no previously-included directories found matching '*test'
    no previously-included directories found matching 'e2e/*'
    writing manifest file 'pact_python.egg-info/SOURCES.txt'
    Copying pact_python.egg-info to /home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact_python-0.1.0-py2.7.egg-info
    running install_scripts
    writing list of installed files to '/tmp/pip-d4ziQV-record/install-record.txt'
    error: [Errno 2] No such file or directory: '/home/iob/.virtualenvs/testing1/lib/python2.7/site-packages/pact/bin/pact-mock-service-linux-x64.tar.gz'
    
    ----------------------------------------
Command "/home/iob/.virtualenvs/testing1/bin/python -c "import setuptools, tokenize;__file__='/tmp/pip-vDkaMF-build/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-d4ziQV-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/iob/.virtualenvs/testing1/include/site/python2.7/pact-python" failed with error code 1 in /tmp/pip-vDkaMF-build

site-packages do not have any bin directory inside pack.

"There was an error when stopping the Pact mock service"


System Info

⇒  uname -a
Linux dev 4.10.0-28-generic #32~16.04.2-Ubuntu SMP Thu Jul 20 10:19:48 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Versions

⇒  python3 --version
Python 3.5.2
⇒  pip3 --version
pip 9.0.1 from /usr/local/lib/python3.5/dist-packages (python 3.5)

version of pact-python is 0.10.0


Recreating the Issue

So you can recreate using just the example consumer test included in the README. Here, I've modified it slightly.

From consumer_contract.py:

import atexit
import unittest
import requests

from pact import Consumer, Provider

pact = Consumer('Consumer').has_pact_with(Provider('Provider'))
pact.start_service()
atexit.register(pact.stop_service)

class GetUserInfoContract(unittest.TestCase):
  def test_get_user(self):
    expected = {
      'username': 'UserA',
      'id': 123,
      'groups': ['Editors']
    }

    (pact
     .given('UserA exists and is not an administrator')
     .upon_receiving('a request for UserA')
     .with_request('get', '/users/UserA')
     .will_respond_with(200, body=expected))

    with pact:
      r = requests.get('http://localhost:1234/users/UserA')

    self.assertEqual(r.json()['username'], 'UserA')

if __name__ == '__main__':
    unittest.main()

The Problem

If I now do a python3 consumer_contract.py, I get the following stack traces:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 137, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
  File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 91, in create_connection
    raise err
  File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 81, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 560, in urlopen
    body=body, headers=headers)
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 354, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.5/http/client.py", line 1106, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python3.5/http/client.py", line 1151, in _send_request
    self.endheaders(body)
  File "/usr/lib/python3.5/http/client.py", line 1102, in endheaders
    self._send_output(message_body)
  File "/usr/lib/python3.5/http/client.py", line 934, in _send_output
    self.send(msg)
  File "/usr/lib/python3.5/http/client.py", line 877, in send
    self.connect()
  File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 162, in connect
    conn = self._new_conn()
  File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 146, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
requests.packages.urllib3.exceptions.NewConnectionError: <requests.packages.urllib3.connection.HTTPConnection object at 0x7f8379434518>: Failed to establish a new connection: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "foo.py", line 8, in <module>
    pact.start_service()
  File "/usr/local/lib/python3.5/dist-packages/pact/pact.py", line 152, in start_service
    self._wait_for_server_start()
  File "/usr/local/lib/python3.5/dist-packages/pact/pact.py", line 256, in _wait_for_server_start
    resp = s.get(self.uri, headers=self.HEADERS)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 480, in get
    return self.request('GET', url, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 468, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python3/dist-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python3/dist-packages/requests/adapters.py", line 376, in send
    timeout=timeout
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 610, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 228, in increment
    total -= 1
TypeError: unsupported operand type(s) for -=: 'Retry' and 'int'

WEBrick then goes on to start up asynchronously and run in the background. If I then attempt to generate the contract file again, I get the following:

.
----------------------------------------------------------------------
Ran 1 test in 0.057s

OK
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/pact/pact.py", line 168, in stop_service
    'There was an error when stopping the Pact mock service.')
RuntimeError: There was an error when stopping the Pact mock service.

...because the mock server is still running. Only once I manually kill ruby does the contract get written. What am I doing wrong? It seems like my use case is pretty simple here.

Provide a way to hide ruby traceback on provider verification failure

At present the failure of provider verification tests results in massive ruby traceback which is not really required for the end user. Please provide an option to hide this traceback.

Ex.

Failure/Error: expect(response_body).to match_term expected_response_body, diff_options

     RuntimeError:
       Sorry, "\d+" is too vague, try setting a range: "\d{1, 5}"
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:82:in `digit'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:19:in `random'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:4:in `reduce'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:12:in `quantify'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:4:in `reduce'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:53:in `block in union'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:53:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:53:in `union'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/reducer.rb:4:in `reduce'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp.rb:9:in `reduce'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/randexp-0.1.7/lib/randexp/core_ext/regexp.rb:3:in `generate'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/reification.rb:17:in `from_term'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/reification.rb:20:in `block in from_term'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/reification.rb:19:in `each'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/reification.rb:19:in `inject'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/reification.rb:19:in `from_term'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/matchers/matchers.rb:126:in `hash_diff'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/matchers/matchers.rb:43:in `calculate_diff'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/matchers/matchers.rb:31:in `diff'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/shared/json_differ.rb:10:in `call'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec/matchers.rb:36:in `matches?'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:50:in `block in handle_matcher'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:27:in `with_matcher'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/expectation_target.rb:65:in `to'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec.rb:138:in `block (2 levels) in describe_response'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:254:in `instance_exec'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:254:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:500:in `block in with_around_and_singleton_context_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:457:in `block in with_around_example_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:464:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:602:in `run_around_example_hooks_for'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:464:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:457:in `with_around_example_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:500:in `with_around_and_singleton_context_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:251:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:627:in `block in run_examples'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:623:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:623:in `run_examples'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:589:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:1894:in `with_suite_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:113:in `block in run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/reporter.rb:79:in `report'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:112:in `run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:87:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:71:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:94:in `run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:35:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:60:in `run_with_pact_uri'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:48:in `run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:22:in `call'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:14:in `call'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:66:in `block in verify_pacts'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in `collect'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in `verify_pacts'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/cli.rb:21:in `verify'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/app/pact-provider-verifier.rb:2:in `<main>'
Failure/Error: expect(header_value).to match_header(name, expected_header_value)
       Expected header "Content-Type" to match "application/json", but was "text/plain; charset=utf-8"
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-support-3.6.0/lib/rspec/support.rb:87:in `block in <module:Support>'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-support-3.6.0/lib/rspec/support.rb:96:in `call'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-support-3.6.0/lib/rspec/support.rb:96:in `notify_failure'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/fail_with.rb:35:in `fail_with'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:40:in `handle_failure'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:50:in `block in handle_matcher'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:27:in `with_matcher'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/handler.rb:48:in `handle_matcher'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-expectations-3.6.0/lib/rspec/expectations/expectation_target.rb:65:in `to'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec.rb:130:in `block (4 levels) in describe_response'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:254:in `instance_exec'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:254:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:500:in `block in with_around_and_singleton_context_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:457:in `block in with_around_example_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:464:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:602:in `run_around_example_hooks_for'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/hooks.rb:464:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:457:in `with_around_example_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:500:in `with_around_and_singleton_context_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example.rb:251:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:627:in `block in run_examples'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:623:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:623:in `run_examples'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:589:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `block in run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/example_group.rb:590:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `block (3 levels) in run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `map'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:118:in `block (2 levels) in run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/configuration.rb:1894:in `with_suite_hooks'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:113:in `block in run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/reporter.rb:79:in `report'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:112:in `run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:87:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/rspec-core-3.6.0/lib/rspec/core/runner.rb:71:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:94:in `run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:35:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:60:in `run_with_pact_uri'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:48:in `run_specs'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:22:in `call'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:14:in `call'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:66:in `block in verify_pacts'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in `collect'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in `verify_pacts'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/cli.rb:21:in `verify'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/base.rb:444:in `start'
     # /usr/local/lib/python3.5/site-packages/pact/bin/pact/lib/app/pact-provider-verifier.rb:2:in `<main>'

3 interactions, 1 failure

Failed interactions:

bundle exec rake pact:verify:at[pacts/auth-userservice.json] PACT_DESCRIPTION="a request is made to validate user" PACT_PROVIDER_STATE=""

API should allow multiple requests to be stubbed at the same time

Multiple interactions should be allowed to be set up at the same time. The /delete call should be called before the test, not before each interaction is set up.

See this example using bash here: https://gist.github.com/bethesque/9d81f21d6f77650811f4

https://github.com/pact-foundation/pact-python/blob/master/pact/pact.py#L119

def setup(self):
        """Configure the Mock Service to ready it for a test."""
        try:
            payload = {
                'description': self._description,
                'provider_state': self._provider_state,
                'request': self._request,
                'response': self._response
            }

            resp = requests.delete(
                self.uri + '/interactions', headers=self.HEADERS)

            assert resp.status_code == 200, resp.content
            resp = requests.post(
                self.uri + '/interactions',
                headers=self.HEADERS, json=payload)

            assert resp.status_code == 200, resp.content
        except AssertionError:
            raise

No clear instructions on setting up development environment for pact-python

Clear instructions on setting up development environment is missing in the README.md
Multiple preconditions required to use pact-python .
on OSX, I had to

  • Install ruby --> specifically v2.2.2
  • Install bundler, rake and any other ruby related dependencies
  • use ./scripts/build to build mock service (which again failed complaining Gem::InstallError: rack requires Ruby version >= 2.2.2. An error occurred while installing rack (2.0.3), and Bundler cannot continue. Make sure that gem install rack -v '2.0.3' succeeds before bundling.
  • spend hours finding a way to make the build script work (with no success)

-----update----
I was able to build the mockservice binary successfully, but running it resulted in the following error/Users/sanjay/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in require': cannot load such file -- pact/mock_service/cli (LoadError)
from /Users/sanjay/.rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in require' from ./pact-mock-service:2:in

'`

-----update2----
Finally I got the build working, all I did was

  1. install ruby v2.2.2 with rvm
  2. install bundler
  3. ran make package

The key was earlier I was using v2.4.0 but the make package command ended with
You can only 'bundle install' using Ruby 2.2, because that's what Traveling Ruby uses.

I am updating here, so that any new user (read ruby noob) trying pact-python and getting lost :P

Pact-Python verifier requires a set_up_provider_state and tear_down_provider_state to be provided

For each response verification to be run against a provider, the pact-verifier program tries to find the set_up_provider_state and the tear_down_provider_state.

pact-verifier --provider-base-url=http://localhost:8081 --pact-urls=./consumer_api_contract.json

 Got 0 failures and 2 other errors:

 1.1) Failure/Error: set_up_provider_state interaction.provider_state, options[:consumer]
      
      RuntimeError:
        Could not find provider state "Administrator user" for consumer platform_ui

 1.2) Failure/Error: tear_down_provider_state interaction.provider_state, options[:consumer]
      
      RuntimeError:
        Could not find provider state "Administrator user" for consumer platform_ui

Pact-Python Verifier version:

/Library/Python/2.7/site-packages/pact/bin/verifier/lib/vendor/ruby/2.2.0/gems/pact-1.11.1/lib/pact/provider/

Discrepancy in encoding of JSON between Python and Ruby

I am unable to run contract tests between two python services that authenticate using HMAC keys due to the serialization differences between the actual requests and the mocked request provided by the pact-verifier.

I have a Consumer test that signs requests with an HMAC:

request = requests.Request(
  method=’POST’, url=’http://localhost’, json={‘test’: ‘a’})
prep = request.prepare() 
signature = hmac.new(‘abc123’.encode('utf-8'),
                     msg=prep.body,
                     digestmod=hashlib.sha512).hexdigest()
prep.headers['Request-Signature'] = signature
resp = requests.session().send(prep) 
return resp 

And a Provider that verifies that HMAC:

@blueprint.route(‘/’, methods=[‘POST’])
def handle():
  ...
  signature = hmac.new(
    ‘abc123’.encode(‘utf-8’),
    msg=body,
    digestmod=hashlib.sha512).hexdigest()
  # if signature != request.headers.get('Request-Signature`):
    # abort(401)

At the HTTP level, what is being sent from the Consumer is exactly:

‘{“status”: “e”}’

However, what is being received by the Provider is exactly:

‘{“status”:”e”}’

This would not be a problem under normal circumstances since the json encoder is ambivalent to whitespace. However, in the case of HMAC keys where the exact byte sequence of the request body is used it causes failures to authenticate.

The json contract spec that I get from running the Consumer unit tests is:

  "interactions": [
    {
      "description": "<test request>",
      "providerState": "<state>",
      "request": {
        "method": "post",
        "path": "/",
        "headers": {
          "Content-Type": "application/json",
          "Request-Signature": "<sig>"
        },
        "body": {
          "test": "a"
        }
      },
      "response": {
        "status": 200,
        "headers": {
        },
        "body": [
          "Success",
          200
        ]
      }
    },

  ]
}

`make test` is not running properly on Python 3.6.2

Running make test on virtualenv with Python 3.6.2 does not completely run the tests.

Output:

Process Process-8:
Traceback (most recent call last):
  File "/usr/lib64/python3.6/multiprocessing/process.py", line 249, in _bootstrap
    self.run()
  File "/usr/lib64/python3.6/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/flake8/checker.py", line 666, in _run_checks_from_queue
    checker.run_checks(results_queue, statistics_queue)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/flake8/checker.py", line 606, in run_checks
    self.run_ast_checks()
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/flake8/checker.py", line 510, in run_ast_checks
    checker = self.run_check(plugin, tree=ast)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/flake8/checker.py", line 464, in run_check
    return plugin['plugin'](**arguments)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/flake8/plugins/pyflakes.py", line 74, in __init__
    withDoctest=with_doctest)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 495, in __init__
    self.runDeferred(self._deferredFunctions)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 532, in runDeferred
    handler()
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 1160, in runFunction
    self.handleNode(stmt, node)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 863, in handleNode
    handler(node)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 816, in handleChildren
    self.handleNode(node, tree)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 863, in handleNode
    handler(node)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 816, in handleChildren
    self.handleNode(node, tree)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 863, in handleNode
    handler(node)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 1017, in GENERATOREXP
    self.handleChildren(node)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 816, in handleChildren
    self.handleNode(node, tree)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 862, in handleNode
    handler = self.getNodeHandler(node.__class__)
  File "/home/jceplaras/Projects/pact-python/virtualenv/lib/python3.6/site-packages/pyflakes/checker.py", line 696, in getNodeHandler
    self._nodeHandlers[node_class] = handler = getattr(self, nodeType)
AttributeError: 'FlakesChecker' object has no attribute 'JOINEDSTR'

Steps to replicate

  1. Create virtualenv with Python 3.6.2
  2. Run make test
  • Python version: 3.6.2
  • Flake8 version: 3.2.1 (mccabe: 0.5.2, pycodestyle: 2.2.0, pyflakes: 1.3.0) CPython 3.6.2 on Linux

RuntimeError: The Pact mock service failed to start.

** # In the wins7 system. After installing pact, run the error message. Here's the information. What's the problem?**
"D:\Program Files_Work\Tool_Test\python27\python.exe" D:/co-mall/python-pact-testing-example-master/src/testuser_consumer.py
D:\Program Files_Work\Tool_Test\python27\Lib\site-packages\pact\bin\mock-service\lib\ruby\bin..\bin.real\ruby.exe: No such file or directory -- Files_Work/Tool_Test/python27/Lib/site-packages/pact/bin/mock-service/lib/app/lib (LoadError)
Traceback (most recent call last):
File "D:/co-mall/python-pact-testing-example-master/src/testuser_consumer.py", line 9, in
pact.start_service()
File "D:\Program Files_Work\Tool_Test\python27\lib\site-packages\pact\pact.py", line 154, in start_service
raise RuntimeError('The Pact mock service failed to start.')
RuntimeError: The Pact mock service failed to start.

Mock service does not start on Windows because Windows does not implement fork

Adding this here to track the issue.

I'm working on a branch of the mock service here to implement pact-mock-service start using spawn instead of fork. I can get it to start up ok, but I can't work out how to kill the process gracefully (SIGTERM). It always needs to be killed with a SIGKILL, which means that the shutdown hook on the mock service won't execute.

`make e2e` fails on one badly indented test case

Running make e2e on 5f8257b fails by default on Python 3.6

bash -c "$E2E"
[2017-10-13 12:45:41] INFO  WEBrick 1.3.1
[2017-10-13 12:45:41] INFO  ruby 2.2.2 (2015-04-13) [x86_64-linux]
[2017-10-13 12:45:41] INFO  WEBrick::HTTPServer#start: pid=4208 port=1234
.WARN: No content type found, performing text diff on body
.WARN: No content type found, performing text diff on body
.WARN: No content type found, performing text diff on body
...E
======================================================================
ERROR: test_incorrect_number_of_arguments (test_e2e.SyntaxErrors)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/jceplaras/Projects/pact-python/e2e/contracts/test_e2e.py", line 161, in test_incorrect_number_of_arguments
    e.exception.message, 'two() takes exactly 2 arguments (1 given)')
AttributeError: 'TypeError' object has no attribute 'message'
-------------------- >> begin captured logging << --------------------
requests.packages.urllib3.connectionpool: DEBUG: Starting new HTTP connection (1): localhost
requests.packages.urllib3.connectionpool: DEBUG: http://localhost:1234 "DELETE /interactions HTTP/1.1" 200 20
requests.packages.urllib3.connectionpool: DEBUG: Starting new HTTP connection (1): localhost
requests.packages.urllib3.connectionpool: DEBUG: http://localhost:1234 "PUT /interactions HTTP/1.1" 200 16
--------------------- >> end captured logging << ---------------------

----------------------------------------------------------------------
Ran 7 tests in 0.844s

FAILED (errors=1)

Writing pact for provider to ./pacts/consumer-provider.json
[2017-10-13 12:45:41] INFO  going to shutdown ...
[2017-10-13 12:45:41] INFO  WEBrick::HTTPServer#start done.
make: *** [Makefile:56: e2e] Error 1

I would also like to fix this. :)

Unicode error in pact-verifier

Hi,

pact-verifier chokes on anything non-ASCII, see attached example. Thanks for contributing to pact btw!

` (pact
        .given('Regelwerk fuer ÄÄÄ')
        .upon_receiving('Ein Produkt mit Ä')
        .with_request('post', '/permission/', body=product, headers={'Content-Type': 'application/json'})
        .will_respond_with(200, body=expected))`

/whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/json-1.8.6/lib/json/pure/parser.rb:242:in 'rescue in parse_string': Caught Encoding::CompatibilityError at '{ (JSON::ParserError) "consumer": { ': incompatible encoding regexp match (ASCII-8BIT regexp with UTF-8 string) from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/json-1.8.6/lib/json/pure/parser.rb:213:in 'parse_string' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/json-1.8.6/lib/json/pure/parser.rb:257:in 'parse_value' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/json-1.8.6/lib/json/pure/parser.rb:121:in 'parse' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/json-1.8.6/lib/json/common.rb:155:in 'parse' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/json-1.8.6/lib/json/common.rb:334:in 'load' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-support-1.1.3/lib/pact/consumer_contract/consumer_contract.rb:42:in 'from_json' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/rspec.rb:25:in 'honour_pactfile' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:129:in 'block in initialize_specs' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:125:in 'each' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:125:in 'initialize_specs' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/provider/pact_spec_runner.rb:34:in 'run' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:60:in 'run_with_pact_uri' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:48:in 'run_specs' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:22:in 'call' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-1.14.0/lib/pact/cli/run_pact_verification.rb:14:in 'call' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:66:in 'block in verify_pacts' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in 'collect' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/app.rb:57:in 'verify_pacts' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/pact-provider-verifier-1.1.3/lib/pact/provider_verifier/cli.rb:21:in 'verify' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/command.rb:27:in 'run' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/invocation.rb:126:in 'invoke_command' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor.rb:369:in 'dispatch' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/vendor/ruby/2.2.0/gems/thor-0.19.4/lib/thor/base.rb:444:in 'start' from /whereever/lib/python3.5/site-packages/pact/bin/pact/lib/app/pact-provider-verifier.rb:2:in '<main>

Fix the json generation of SomethingLike

Hello,

There is a small issue (on pact-python==0.6.2) when we try to generate those kind of interactions:

SomethingLike({
   'username': Term('.+', 'admin'),
   'email': ''
})

This raises :

Finding files... done.
Importing test modules ... [2017-07-12 17:43:58] INFO  WEBrick 1.3.1
[2017-07-12 17:43:58] INFO  ruby 2.2.2 (2015-04-13) [x86_64-darwin13]
[2017-07-12 17:43:58] INFO  WEBrick::HTTPServer#start: pid=14167 port=1234
done.

======================================================================
ERROR: test_sign_in (__init__.UserTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/EliX/git/test/api/__init__.py", line 35, in test_sign_in
    with pact:
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/pact/pact.py", line 238, in __enter__
    self.setup()
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/pact/pact.py", line 116, in setup
    json={"interactions": self._interactions})
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/requests/api.py", line 124, in put
    return request('put', url, data=data, **kwargs)
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/requests/sessions.py", line 474, in request
    prep = self.prepare_request(req)
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/requests/sessions.py", line 407, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/requests/models.py", line 305, in prepare
    self.prepare_body(data, files, json)
  File "/Users/EliX/anaconda/lib/python2.7/site-packages/requests/models.py", line 445, in prepare_body
    body = complexjson.dumps(json)
  File "/Users/EliX/anaconda/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/Users/EliX/anaconda/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Users/EliX/anaconda/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/Users/EliX/anaconda/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <pact.matchers.Term object at 0x105931a90> is not JSON serializable

The problem is in file pact/matchers.py on line 120:

return {
  'json_class': 'Pact::SomethingLike',
  'contents': self.matcher}

https://github.com/pact-foundation/pact-python/blob/master/pact/matchers.py#L120

It should be

return {
  'json_class': 'Pact::SomethingLike',
  'contents': from_term(self.matcher)}

This fix should manage when self.matcher is a python dictionary.

Ensure PACT_DESCRIPTION and PACT_PROVIDER_STATE env vars can be passed down to pact verify to allow selected interactions to be run

I've removed the ruby specific output from the pact verify command (yay!)

What I would like to add is words to the effect of "to run just one interaction, please rerun the pact verify command with PACT_DESCRIPTION="..." and PACT_PROVIDER_STATE="..." environment variables set.

Can you please update to the ruby standalone version 1.4.0 and verify that the above environment variables are passed through? You should see the text Filtering interactions by...

Upgrade to 1.9.1 standalone

This version contains some CLI changes, and a bug fix (correcting the usage of Pact::Term headers when replaying the request.)

Changes required to python code:

  • Instead of posting the consumer name, provider name, and pact file write mode in the POST /pact they should now be passed in to the command line service call using --consumer, --provider and --pact-file-write-mode. That last POST to /pact does not need a body any more.
  • The list of pact URLs passed to the pact verify command should now be space separated arguments rather than a list of comma separated --pact-url options. Eg pact-provider-verify URL_ONE URL_TWO

These changes are backwards compatible.

See the full CLI documentation here: https://github.com/pact-foundation/pact-ruby-standalone/releases/tag/v1.9.1

Upgrade Pact Mock Service

The version of Mock Service used during the build of pact-python is currently out of date and does not include a recent change to make the pact specification version consistent across the various language implementations: pact-foundation/pact-mock_service@5b89d95

We need to upgrade to at least 2.1.0 to ensure pact-python is creating compatible pact files.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.