diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d254fc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.pyc +.cache/ +.idea/ +build/ +pypact.egg-info/ +tests/__pycache__/ +.eggs/ +.coverage +*.log +*.egg +*.iml +pytest_pact.egg-info/ +pytest_pact/__pycache__ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5bfd00c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: python +python: + - 2.7 + - 3.3 + - 3.4 + - 3.5 + - 3.6 +install: + - "pip install -r requirements.txt" + - "pip install pytest pytest-cov pytest-sugar" + - "pip install coveralls" + - "pip install -e ." +script: + - py.test --cov pytest_pact --cov-report term-missing +after_success: + - coveralls diff --git a/README.md b/README.md index a678dfe..d755fb3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ -# pypact +[![Build Status](https://travis-ci.org/Kalimaha/pytest-pact.svg?branch=master)](https://travis-ci.org/Kalimaha/pytest-pact) +[![Coverage Status](https://coveralls.io/repos/github/Kalimaha/pytest-pact/badge.svg?branch=master)](https://coveralls.io/github/Kalimaha/pytest-pact?branch=master) + +# PyPact Python implementation for Pact (http://pact.io/) + +## Setup +``` +python setup.py install +``` diff --git a/dist/.keep b/dist/.keep new file mode 100644 index 0000000..e69de29 diff --git a/pytest_pact/PyPact.py b/pytest_pact/PyPact.py new file mode 100644 index 0000000..f23d6da --- /dev/null +++ b/pytest_pact/PyPact.py @@ -0,0 +1,56 @@ +import pytest + + +state = pytest.mark.state +given = pytest.mark.given +base_uri = pytest.mark.base_uri +pact_uri = pytest.mark.pact_uri +with_request = pytest.mark.with_request +has_pact_with = pytest.mark.has_pact_with +upon_receiving = pytest.mark.upon_receiving +will_respond_with = pytest.mark.will_respond_with +service_consumer = pytest.mark.service_consumer +honours_pact_with = pytest.mark.honours_pact_with + + +@pytest.hookimpl(hookwrapper=True) +def pytest_pyfunc_call(pyfuncitem): + # print(describe_consumer_pact(pyfuncitem)) + + # pypact = PyPact() + # pypact.executor(pyfuncitem) + + + + outcome = yield + # outcome.excinfo may be None or a (cls, val, tb) tuple + print(outcome) + + res = outcome.get_result() # will raise if outcome was exception + # postprocess result + print(res) + + +def consumer_or_provider(pyfuncitem): + pass + +class PyPactConsumer(object): + pass + +class PyPactProvider(object): + pass + + +def describe_consumer_pact(pyfuncitem): + s = '' + s += 'Given ' + read_marker(pyfuncitem, 'given') + ', ' + s += 'upon receiving ' + read_marker(pyfuncitem, 'upon_receiving') + ' ' + s += 'from ' + read_marker(pyfuncitem, 'service_consumer') + ' ' + s += 'with:\n\n' + read_marker(pyfuncitem, 'with_request') + '\n\n' + s += read_marker(pyfuncitem, 'has_pact_with') + ' will respond with:\n\n' + s += read_marker(pyfuncitem, 'will_respond_with') + return s + +def read_marker(pyfuncitem, marker_name): + marker = pyfuncitem.get_marker(marker_name) + return str(marker.args[0]) if marker else '' diff --git a/pytest_pact/__init__.py b/pytest_pact/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..aa815b2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +pytest>=3.0 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..b7e4789 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[aliases] +test=pytest diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..7bda334 --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +from setuptools import setup +from setuptools import find_packages + +setup( + name='pytest-pact', + version='0.1.0', + author='Guido Barbaglia', + author_email='guido.barbaglia@gmail.com', + packages=find_packages(), + license='LICENSE.txt', + long_description=open('README.md').read(), + description='Python implementation for Pact (http://pact.io/)', + install_requires=[], + setup_requires=['pytest-runner'], + tests_require=['pytest', 'pytest-sugar'], + url='https://github.com/Kalimaha/pytest-pact/', + entry_points = { + 'pytest11': [ + 'pytest-pact = pytest_pact.PyPact', + ] + } +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_books_service.py b/tests/test_books_service.py new file mode 100644 index 0000000..fc4b6ee --- /dev/null +++ b/tests/test_books_service.py @@ -0,0 +1,23 @@ +from pytest_pact.PyPact import * + + +@base_uri('localhost:1234') +@service_consumer('Library App') +@has_pact_with('Books Service') +class TestBooksService(): + + expected_response = { + 'status': 200, + 'headers': {'Content-Type': 'application/json'}, + 'body': { + 'id': '123', + 'title': 'A Fortune-Teller Told Me' + } + } + + @given('some books exist') + @upon_receiving('a request for a book') + @with_request({'method': 'get', 'path': '/books/123'}) + @will_respond_with(expected_response) + def test_get_book(self): + pass diff --git a/tests/test_pypact.py b/tests/test_pypact.py new file mode 100644 index 0000000..5046f60 --- /dev/null +++ b/tests/test_pypact.py @@ -0,0 +1,22 @@ +from pytest_pact.PyPact import * + + +def test_read_existing_marker(): + expected_marker = 'some books exist' + class FakeMarker(object): + args = [expected_marker] + class FakePyFuncItem(object): + def get_marker(self, marker_name): + return FakeMarker() + pyfuncitem = FakePyFuncItem() + marker_name = 'given' + assert read_marker(pyfuncitem, marker_name) == expected_marker + + +def test_read_non_existing_marker(): + class FakePyFuncItem(object): + def get_marker(self, marker_name): + return None + pyfuncitem = FakePyFuncItem() + marker_name = 'given' + assert read_marker(pyfuncitem, marker_name) == ''