Skip to content

Commit

Permalink
Resolves #58: Update to pact-ruby-standalone 1.9.0
Browse files Browse the repository at this point in the history
- Pinned to pact-ruby-standalone 1.9.0
- Removed the payload to `/pact` of the pact-mock-service as its no longer required
- Added the option to specify pact URIs as arguments to be consistent with the Ruby verifier
- Added deprecation notices to `--pact-url` and `--pact-urls`
- Added `file_write_mode` to the Pact class to control how the mock service
  writes files when tests are run in parallel
  • Loading branch information
matthewbalvanz-wf committed Feb 4, 2018
1 parent 730ead7 commit 475703c
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 36 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ define E2E
done
pact-verifier \
--provider-base-url=http://localhost:5000 \
--pact-urls=./pacts/consumer-provider.json \
--provider-states-url=http://localhost:5000/_pact/provider-states \
--provider-states-setup-url=http://localhost:5000/_pact/provider-states/active
--provider-states-setup-url=http://localhost:5000/_pact/provider-states/active \
./pacts/consumer-provider.json
endef


Expand Down
2 changes: 1 addition & 1 deletion e2e/contracts/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def test_sparse(self):
(pact
.given('the user `bob` exists')
.upon_receiving('a request for the user object of `bob`')
.with_request('get', '/users/bob')
.with_request('get', Term('/users/[a-z]+', '/users/bob'))
.will_respond_with(200, body={
'username': SomethingLike('bob'),
'id': Term('\d+', '123')}))
Expand Down
19 changes: 12 additions & 7 deletions pact/pact.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class Pact(object):

def __init__(self, consumer, provider, host_name='localhost', port=1234,
log_dir=None, ssl=False, sslcert=None, sslkey=None,
cors=False, pact_dir=None, version='2.0.0'):
cors=False, pact_dir=None, version='2.0.0',
file_write_mode='overwrite'):
"""
Constructor for Pact.
Expand Down Expand Up @@ -74,13 +75,21 @@ def __init__(self, consumer, provider, host_name='localhost', port=1234,
:param version: The Pact Specification version to use, defaults to
'2.0.0'.
:type version: str
:param file_write_mode: `overwrite` or `merge`. Use `merge` when
running multiple mock service instances in parallel for the same
consumer/provider pair. Ensure the pact file is deleted before
running tests when using this option so that interactions deleted
from the code are not maintained in the file. Defaults to
`overwrite`.
:type file_write_mode: str
"""
scheme = 'https' if ssl else 'http'
self.uri = '{scheme}://{host_name}:{port}'.format(
host_name=host_name, port=port, scheme=scheme)

self.consumer = consumer
self.cors = cors
self.file_write_mode = file_write_mode
self.host_name = host_name
self.log_dir = log_dir or os.getcwd()
self.pact_dir = pact_dir or os.getcwd()
Expand Down Expand Up @@ -137,6 +146,7 @@ def start_service(self):
'--port={}'.format(self.port),
'--log', '{}/pact-mock-service.log'.format(self.log_dir),
'--pact-dir', self.pact_dir,
'--pact-file-write-mode', self.file_write_mode,
'--pact-specification-version={}'.format(self.version),
'--consumer', self.consumer.name,
'--provider', self.provider.name]
Expand Down Expand Up @@ -192,13 +202,8 @@ def verify(self):
self.uri + '/interactions/verification',
headers=self.HEADERS)
assert resp.status_code == 200, resp.text
payload = {
'consumer': {'name': self.consumer.name},
'provider': {'name': self.provider.name},
'pact_dir': self.pact_dir
}
resp = requests.post(
self.uri + '/pact', headers=self.HEADERS, json=payload)
self.uri + '/pact', headers=self.HEADERS)
assert resp.status_code == 200, resp.text

def with_request(self, method, path, body=None, headers=None, query=None):
Expand Down
11 changes: 7 additions & 4 deletions pact/test/test_pact.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def test_init_custom_mock_service(self):
target = Pact(
self.consumer, self.provider, host_name='192.168.1.1', port=8000,
log_dir='/logs', ssl=True, sslcert='/ssl.cert', sslkey='/ssl.pem',
cors=True, pact_dir='/pacts', version='3.0.0')
cors=True, pact_dir='/pacts', version='3.0.0',
file_write_mode='merge')

self.assertIs(target.consumer, self.consumer)
self.assertIs(target.cors, True)
Expand All @@ -49,6 +50,7 @@ def test_init_custom_mock_service(self):
self.assertEqual(target.sslkey, '/ssl.pem')
self.assertEqual(target.uri, 'https://192.168.1.1:8000')
self.assertEqual(target.version, '3.0.0')
self.assertEqual(target.file_write_mode, 'merge')
self.assertEqual(len(target._interactions), 0)

def test_definition_sparse(self):
Expand Down Expand Up @@ -232,6 +234,7 @@ def test_start_fails(self):
'--port=1234',
'--log', '/logs/pact-mock-service.log',
'--pact-dir', '/pacts',
'--pact-file-write-mode', 'overwrite',
'--pact-specification-version=2.0.0',
'--consumer', 'consumer',
'--provider', 'provider'])
Expand All @@ -247,6 +250,7 @@ def test_start_no_ssl(self):
'--port=1234',
'--log', '/logs/pact-mock-service.log',
'--pact-dir', '/pacts',
'--pact-file-write-mode', 'overwrite',
'--pact-specification-version=2.0.0',
'--consumer', 'consumer',
'--provider', 'provider'])
Expand All @@ -263,6 +267,7 @@ def test_start_with_ssl(self):
'--port=1234',
'--log', '/logs/pact-mock-service.log',
'--pact-dir', '/pacts',
'--pact-file-write-mode', 'overwrite',
'--pact-specification-version=2.0.0',
'--consumer', 'consumer',
'--provider', 'provider',
Expand Down Expand Up @@ -373,9 +378,7 @@ def setUp(self):
'post', 'http://localhost:1234/pact',
data=None,
headers={'X-Pact-Mock-Service': 'true'},
json={'pact_dir': os.getcwd(),
'consumer': {'name': 'TestConsumer'},
'provider': {'name': 'TestProvider'}})
json=None)

def test_success(self):
self.mock_requests.side_effect = iter([Mock(status_code=200)] * 2)
Expand Down
26 changes: 15 additions & 11 deletions pact/test/test_verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ def setUp(self):

self.runner = CliRunner()
self.default_call = [
'--provider-base-url=http://localhost',
'--pact-urls=./pacts/consumer-provider.json,'
'./pacts/consumer-provider2.json,./pacts/consumer-provider3.json']
'./pacts/consumer-provider.json',
'./pacts/consumer-provider2.json',
'./pacts/consumer-provider3.json',
'--provider-base-url=http://localhost']

self.default_opts = [
'--provider-base-url=http://localhost',
Expand Down Expand Up @@ -74,7 +75,7 @@ def test_pact_urls_are_required(self):
verify.main, ['--provider-base-url=http://localhost'])

self.assertEqual(result.exit_code, 1)
self.assertIn(b'--pact-url or --pact-urls', result.output_bytes)
self.assertIn(b'at least one', result.output_bytes)
self.assertFalse(self.mock_Popen.called)

def test_local_pact_urls_must_exist(self):
Expand Down Expand Up @@ -123,6 +124,7 @@ def test_password_from_env_var(self):
def test_all_options(self):
self.mock_Popen.return_value.returncode = 0
result = self.runner.invoke(verify.main, [
'./pacts/consumer-provider5.json',
'--provider-base-url=http://localhost',
'--pact-urls=./pacts/consumer-provider.json,'
'./pacts/consumer-provider2.json',
Expand All @@ -135,13 +137,15 @@ def test_all_options(self):
'--provider-app-version=1.2.3',
'--timeout=60'
])
self.assertEqual(result.exit_code, 0)
self.assertEqual(result.exit_code, 0, result.output)
self.assertEqual(self.mock_Popen.call_count, 1)
self.assertProcess(
'./pacts/consumer-provider5.json',
'./pacts/consumer-provider3.json',
'./pacts/consumer-provider4.json',
'./pacts/consumer-provider.json',
'./pacts/consumer-provider2.json',
'--provider-base-url=http://localhost',
'--pact-urls=./pacts/consumer-provider3.json,'
'./pacts/consumer-provider4.json,'
'./pacts/consumer-provider.json,./pacts/consumer-provider2.json',
'--provider-states-setup-url=http://localhost/provider-states/set',
'--broker-username=user',
'--broker-password=pass',
Expand All @@ -163,9 +167,9 @@ def test_deprecated_pact_urls(self):
result.output_bytes)
self.assertEqual(self.mock_Popen.call_count, 1)
self.assertProcess(
'--provider-base-url=http://localhost',
'--pact-urls=./pacts/consumer-provider.json,'
'./pacts/consumer-provider2.json')
'./pacts/consumer-provider.json',
'./pacts/consumer-provider2.json',
'--provider-base-url=http://localhost')
self.mock_Popen.return_value.communicate.assert_called_once_with(
timeout=30)

Expand Down
23 changes: 13 additions & 10 deletions pact/verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,23 @@


@click.command()
@click.argument('pacts', nargs=-1)
@click.option(
'base_url', '--provider-base-url',
help='Base URL of the provider to verify against.',
required=True)
@click.option(
'pact_url', '--pact-url',
help='The URI of the pact to verify.'
help='DEPRECATED: specify pacts as arguments instead.\n'
'The URI of the pact to verify.'
' Can be an HTTP URI, a local file or directory path. '
' It can be specified multiple times to verify several pacts.',
multiple=True)
multiple=True) # Remove in major version 1.0.0
@click.option(
'pact_urls', '--pact-urls',
default='',
help='The URI(s) of the pact to verify.'
help='DEPRECATED: specify pacts as arguments instead.\n'
'The URI(s) of the pact to verify.'
' Can be an HTTP URI(s) or local file path(s).'
' Provide multiple URI separated by a comma.',
multiple=True) # Remove in major version 1.0.0
Expand Down Expand Up @@ -64,19 +67,19 @@
default=False,
help='Publish verification results to the broker',
is_flag=True)
def main(base_url, pact_url, pact_urls, states_url,
def main(pacts, base_url, pact_url, pact_urls, states_url,
states_setup_url, username, password, timeout, provider_app_version,
publish_verification_results):
"""
Verify one or more contracts against a provider service.
Minimal example:
pact-verifier --provider-base-url=http://localhost:8080 --pact-url=./pact
pact-verifier --provider-base-url=http://localhost:8080 ./pacts
""" # NOQA
error = click.style('Error:', fg='red')
warning = click.style('Warning:', fg='yellow')
all_pact_urls = list(pact_url)
all_pact_urls = list(pacts) + list(pact_url)
for urls in pact_urls: # Remove in major version 1.0.0
all_pact_urls.extend(p for p in urls.split(',') if p)

Expand All @@ -90,7 +93,7 @@ def main(base_url, pact_url, pact_urls, states_url,
if not all_pact_urls:
click.echo(
error
+ ' At least one of --pact-url or --pact-urls is required.')
+ ' You must supply at least one pact file or directory to verify')
raise click.Abort()

all_pact_urls = expand_directories(all_pact_urls)
Expand All @@ -104,13 +107,13 @@ def main(base_url, pact_url, pact_urls, states_url,

options = {
'--provider-base-url': base_url,
'--pact-urls': ','.join(all_pact_urls),
'--provider-states-setup-url': states_setup_url,
'--broker-username': username,
'--broker-password': password
}
command = [VERIFIER_PATH] + [
'{}={}'.format(k, v) for k, v in options.items() if v]
command = [VERIFIER_PATH]
command.extend(all_pact_urls)
command.extend(['{}={}'.format(k, v) for k, v in options.items() if v])

if publish_verification_results:
if not provider_app_version:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@


IS_64 = sys.maxsize > 2 ** 32
PACT_STANDALONE_VERSION = '1.8.0'
PACT_STANDALONE_VERSION = '1.9.0'


here = os.path.abspath(os.path.dirname(__file__))
Expand Down

0 comments on commit 475703c

Please sign in to comment.