Skip to content

Commit

Permalink
Merge pull request #20 from Kalimaha/pact-helper
Browse files Browse the repository at this point in the history
Validation and setup of service consumer tests.
  • Loading branch information
Kalimaha committed May 27, 2017
2 parents ae545e2 + 770cbb0 commit 651281b
Show file tree
Hide file tree
Showing 29 changed files with 402 additions and 41 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ __pycache__
pytest_pact.egg-info/
dist/
.tox
.idea/
*.iml
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ language: python
sudo: false

python:
- 2.7
- 3.3
- 3.4
- 3.5
- 3.6

Expand Down
17 changes: 12 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
.. image:: https://travis-ci.org/Kalimaha/pytest-pact.svg?branch=master
:target: https://travis-ci.org/Kalimaha/pytest-pact
.. image:: https://travis-ci.org/Kalimaha/pact-test.svg?branch=master
:target: https://travis-ci.org/Kalimaha/pact-test
.. image:: https://coveralls.io/repos/github/Kalimaha/pact-test/badge.svg?branch=development
:target: https://coveralls.io/github/Kalimaha/pact-test?branch=development
.. image:: https://img.shields.io/badge/python-2.7-blue.svg
:target: https://travis-ci.org/Kalimaha/pact-test
.. image:: https://img.shields.io/badge/python-3.3-blue.svg
:target: https://travis-ci.org/Kalimaha/pact-test
.. image:: https://img.shields.io/badge/python-3.4-blue.svg
:target: https://travis-ci.org/Kalimaha/pact-test
.. image:: https://img.shields.io/badge/python-3.5-blue.svg
:target: https://travis-ci.org/Kalimaha/pytest-pact
:target: https://travis-ci.org/Kalimaha/pact-test
.. image:: https://img.shields.io/badge/python-3.6-blue.svg
:target: https://travis-ci.org/Kalimaha/pytest-pact
:target: https://travis-ci.org/Kalimaha/pact-test

Pact for PyTest
Pact Test for Python
===============

Python implementation for Pact (http://pact.io/)

Setup
Expand Down
41 changes: 26 additions & 15 deletions bin/pact-test
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
#!/usr/bin/env python
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from pact_test.runners.pact_tests_runner import verify


def print_help():
print(' ')
print('================================')
print('Welcome to Pact Test for Python!')
print('--------------------------------')
print(' Available Commands ')
print(' ')
print('verify..........Verify Pact test')
print('================================')
print(' ')


def verify():
pass
print(' ')
print('========================================================')
print(' Welcome to Pact Test for Python! ')
print('--------------------------------------------------------')
print(' Available Commands ')
print(' ')
print('help..............................Display this help page')
print('verify.............................Verify all Pact tests')
print('verify consumers..............Verify Consumer Pact tests')
print('verify providers..............Verify Provider Pact tests')
print('========================================================')
print(' ')


if len(sys.argv) is 1:
print_help()
else:
if sys.argv[1] == 'verify':
verify()
if sys.argv[1].lower() == 'verify':
if len(sys.argv) is 2:
verify(verify_consumers=True, verify_providers=True)
elif sys.argv[2].lower() == 'consumers':
verify(verify_consumers=True, verify_providers=False)
elif sys.argv[2].lower() == 'providers':
verify(verify_consumers=False, verify_providers=True)
else:
print_help()
elif sys.argv[1].lower() == 'help':
print_help()
else:
print_help()
15 changes: 0 additions & 15 deletions pact.py

This file was deleted.

Empty file added pact_test/config/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions pact_test/config/config_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
import json


class Config(object):
pact_broker_uri = None
consumer_tests_path = 'tests/service_consumers'
provider_tests_path = 'tests/service_providers'
CONFIGURATION_FILE = '.pact.json'

def __init__(self):
user_config_file = self.path_to_user_config_file()
if os.path.isfile(user_config_file):
with open(user_config_file) as f:
self.load_user_settings(f)

def load_user_settings(self, user_settings_file):
settings = json.loads(user_settings_file.read())
[self.custom_or_default(settings, key) for key in settings.keys()]

def path_to_user_config_file(self):
return os.path.join(os.getcwd(), self.CONFIGURATION_FILE)

def custom_or_default(self, user_settings, key):
setattr(self, key, user_settings.get(key, getattr(self, key)))
2 changes: 2 additions & 0 deletions pact_test/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class PactTestException(Exception):
pass
15 changes: 13 additions & 2 deletions pact_test/models/service_consumer_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from pact_test.exceptions import PactTestException


class ServiceConsumerTest(object):
pact_uri = None
has_pact_with = None
Expand All @@ -9,10 +12,17 @@ def states(self):
if callable(obj) and hasattr(obj, 'state'):
yield obj

def is_valid(self):
if self.pact_uri is None:
raise PactTestException('Missing setup for "pact_uri".')
if self.has_pact_with is None:
raise PactTestException('Missing setup for "has_pact_with".')


def pact_uri(pact_uri_value):
def wrapper(calling_class):
setattr(calling_class, 'set_pact_uri', eval('set_pact_uri(calling_class, "' + pact_uri_value + '")'))
setattr(calling_class, 'set_pact_uri',
eval('set_pact_uri(calling_class, "' + pact_uri_value + '")'))
return calling_class
return wrapper

Expand All @@ -23,7 +33,8 @@ def set_pact_uri(self, pact_uri_value):

def has_pact_with(has_pact_with_value):
def wrapper(calling_class):
setattr(calling_class, 'set_has_pact_with', eval('set_has_pact_with(calling_class, "' + has_pact_with_value + '")'))
setattr(calling_class, 'set_has_pact_with',
eval('set_has_pact_with(calling_class, "' + has_pact_with_value + '")'))
return calling_class
return wrapper

Expand Down
6 changes: 4 additions & 2 deletions pact_test/models/service_provider_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def decorated_methods(self):

def service_consumer(service_consumer_value):
def wrapper(calling_class):
setattr(calling_class, 'set_service_consumer', eval('set_service_consumer(calling_class, "' + service_consumer_value + '")'))
setattr(calling_class, 'set_service_consumer',
eval('set_service_consumer(calling_class, "' + service_consumer_value + '")'))
return calling_class
return wrapper

Expand All @@ -30,7 +31,8 @@ def set_service_consumer(self, service_consumer_value):

def has_pact_with(has_pact_with_value):
def wrapper(calling_class):
setattr(calling_class, 'set_has_pact_with', eval('set_has_pact_with(calling_class, "' + has_pact_with_value + '")'))
setattr(calling_class, 'set_has_pact_with',
eval('set_has_pact_with(calling_class, "' + has_pact_with_value + '")'))
return calling_class
return wrapper

Expand Down
Empty file added pact_test/runners/__init__.py
Empty file.
54 changes: 54 additions & 0 deletions pact_test/runners/consumer_tests_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import os
import imp
import inspect
from pact_test.exceptions import PactTestException


class ConsumerTestsRunner(object):
pact_helper = None

def __init__(self, config):
self.config = config

def verify(self):
pass

def collect_tests(self):
root = self.config.consumer_tests_path
files = list(filter(filter_rule, self.all_files()))
files = list(map(lambda f: os.path.join(root, f), files))
tests = []
for idx, filename in enumerate(files):
test = imp.load_source('test' + str(idx), filename)
for name, obj in inspect.getmembers(test):
if inspect.isclass(obj) and len(inspect.getmro(obj)) > 2:
test_parent = inspect.getmro(obj)[1].__name__
if test_parent == 'ServiceConsumerTest':
tests.append(obj)

if not files:
raise PactTestException('There are no consumer tests to verify.')
return tests

def all_files(self):
return os.listdir(self.config.consumer_tests_path)

def load_pact_helper(self):
self.pact_helper = imp.load_source('pact_helper', self.path_to_pact_helper())
if hasattr(self.pact_helper, 'setup') is False:
raise PactTestException('Missing "setup" method in "pact_helper.py".')
if hasattr(self.pact_helper, 'tear_down') is False:
raise PactTestException('Missing "tear_down" method in "pact_helper.py".')

def path_to_pact_helper(self):
path = os.path.join(self.config.consumer_tests_path, 'pact_helper.py')
if os.path.isfile(path) is False:
msg = 'Missing "pact_helper.py" at "' + self.config.consumer_tests_path + '".'
raise PactTestException(msg)
return path


def filter_rule(filename):
return (filename != '__init__.py' and
filename.endswith('.py') and
filename.endswith('pact_helper.py') is False)
19 changes: 19 additions & 0 deletions pact_test/runners/pact_tests_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from pact_test.config.config_builder import Config
from pact_test.runners.consumer_tests_runner import ConsumerTestsRunner
from pact_test.runners.provider_tests_runner import ProviderTestsRunner


def verify(verify_consumers=False, verify_providers=False):
config = Config()
if verify_consumers:
run_consumer_tests(config)
if verify_providers:
run_provider_tests(config)


def run_consumer_tests(config):
ConsumerTestsRunner(config).verify()


def run_provider_tests(config):
ProviderTestsRunner(config).verify()
6 changes: 6 additions & 0 deletions pact_test/runners/provider_tests_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class ProviderTestsRunner(object):
def __init__(self, config):
self.config = config

def verify(self):
pass
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ universal=1
test=pytest

[tool:pytest]
addopts = --pep8
addopts=--pep8
testpaths=tests
python_files=*.py
norecursedirs=tests/resources
69 changes: 69 additions & 0 deletions tests/config/test_config_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import os
from pact_test.config.config_builder import Config


def test_default_consumer_tests_path():
config = Config()
assert config.consumer_tests_path == 'tests/service_consumers'


def test_default_provider_tests_path():
config = Config()
assert config.provider_tests_path == 'tests/service_providers'


def test_default_pact_broker_uri():
config = Config()
assert config.pact_broker_uri is None


def test_custom_consumer_tests_path():
class TestConfig(Config):
def path_to_user_config_file(self):
return os.path.join(os.getcwd(), 'tests',
'resources', 'config',
'consumer_only.json')

config = TestConfig()
assert config.pact_broker_uri is None
assert config.consumer_tests_path == 'mypath/mytests'
assert config.provider_tests_path == 'tests/service_providers'


def test_custom_provider_tests_path():
class TestConfig(Config):
def path_to_user_config_file(self):
return os.path.join(os.getcwd(), 'tests',
'resources', 'config',
'provider_only.json')

config = TestConfig()
assert config.pact_broker_uri is None
assert config.provider_tests_path == 'mypath/mytests'
assert config.consumer_tests_path == 'tests/service_consumers'


def test_custom_pact_broker_uri():
class TestConfig(Config):
def path_to_user_config_file(self):
return os.path.join(os.getcwd(), 'tests',
'resources', 'config',
'pact_broker_only.json')

config = TestConfig()
assert config.pact_broker_uri == 'mypath/mytests'
assert config.provider_tests_path == 'tests/service_providers'
assert config.consumer_tests_path == 'tests/service_consumers'


def test_user_settings():
class TestConfig(Config):
def path_to_user_config_file(self):
return os.path.join(os.getcwd(), 'tests',
'resources', 'config',
'.pact.json')

config = TestConfig()
assert config.pact_broker_uri == 'mypath/mybroker'
assert config.provider_tests_path == 'mypath/myprovider'
assert config.consumer_tests_path == 'mypath/myconsumer'
8 changes: 8 additions & 0 deletions tests/exceptions/test_pact_exception.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pact_test.exceptions import PactTestException


def test_message():
try:
raise PactTestException('Pact Error')
except PactTestException as e:
assert str(e) == 'Pact Error'
Loading

0 comments on commit 651281b

Please sign in to comment.