Skip to content

Commit 08f0dc0

Browse files
authored
feat: added support for message provider using pact broker (#257)
* feat: added support for message provider using pact broker * fix: added new line * fix: update tests to support pact-broker runs fix: updated message_pact to wait writing contract process to finish * fix: removed time from import
1 parent 43fedd1 commit 08f0dc0

File tree

12 files changed

+206
-14
lines changed

12 files changed

+206
-14
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ define messaging
4545
cd examples/message
4646
pip install -r requirements.txt
4747
pip install -e ../../
48-
pytest
48+
./run_pytest.sh
4949
endef
5050
export messaging
5151

examples/message/README.md

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,6 @@ def test_throw_exception_handler(pact):
9999

100100
## Provider
101101

102-
Note: The current example only tests the consumer side.
103-
In the future, provider tests will also be included.
104-
105102
```
106103
+-------------------+ +-----------+
107104
|(Message Provider) | message | (Pact) |
@@ -110,10 +107,82 @@ In the future, provider tests will also be included.
110107
+-------------------+ +-----------+
111108
```
112109

113-
## E2E Messaging
110+
```python
111+
import pytest
112+
from pact import MessageProvider
113+
114+
def document_created_handler():
115+
return {
116+
"event": "ObjectCreated:Put",
117+
"documentName": "document.doc",
118+
"creator": "TP",
119+
"documentType": "microsoft-word"
120+
}
121+
122+
123+
def test_verify_success():
124+
provider = MessageProvider(
125+
message_providers={
126+
'A document created successfully': document_created_handler
127+
},
128+
provider='ContentProvider',
129+
consumer='DetectContentLambda',
130+
pact_dir='pacts'
131+
132+
)
133+
with provider:
134+
provider.verify()
135+
```
136+
137+
138+
### Provider with pact broker
139+
```python
140+
import pytest
141+
from pact import MessageProvider
142+
143+
144+
PACT_BROKER_URL = "http://localhost"
145+
PACT_BROKER_USERNAME = "pactbroker"
146+
PACT_BROKER_PASSWORD = "pactbroker"
147+
PACT_DIR = "pacts"
148+
149+
150+
@pytest.fixture
151+
def default_opts():
152+
return {
153+
'broker_username': PACT_BROKER_USERNAME,
154+
'broker_password': PACT_BROKER_PASSWORD,
155+
'broker_url': PACT_BROKER_URL,
156+
'publish_version': '3',
157+
'publish_verification_results': False
158+
}
159+
160+
def document_created_handler():
161+
return {
162+
"event": "ObjectCreated:Put",
163+
"documentName": "document.doc",
164+
"creator": "TP",
165+
"documentType": "microsoft-word"
166+
}
114167

115-
Note: The current example only tests the consumer side.
116-
In the future, provider tests will also be included.
168+
def test_verify_from_broker(default_opts):
169+
provider = MessageProvider(
170+
message_providers={
171+
'A document created successfully': document_created_handler,
172+
},
173+
provider='ContentProvider',
174+
consumer='DetectContentLambda',
175+
pact_dir='pacts'
176+
177+
)
178+
179+
with pytest.raises(AssertionError):
180+
with provider:
181+
provider.verify_with_broker(**default_opts)
182+
183+
```
184+
185+
## E2E Messaging
117186

118187
```
119188
+-------------------+ +-----------+ +-------------------+

examples/message/conftest.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
2+
from testcontainers.compose import DockerCompose
3+
4+
import pytest
5+
6+
7+
def pytest_addoption(parser):
8+
parser.addoption(
9+
"--publish-pact", type=str, action="store",
10+
help="Upload generated pact file to pact broker with version"
11+
)
12+
13+
parser.addoption(
14+
"--provider-url", type=str, action="store",
15+
help="The url to our provider."
16+
)
17+
18+
parser.addoption(
19+
"--run-broker", type=bool, action="store",
20+
help="Whether to run broker in this test or not."
21+
)
22+
23+
24+
# This fixture is to simulate a managed Pact Broker or Pactflow account
25+
# Do not do this yourself but setup one of the above
26+
# https://github.com/pact-foundation/pact_broker
27+
@pytest.fixture(scope='session', autouse=True)
28+
def broker(request):
29+
version = request.config.getoption('--publish-pact')
30+
publish = True if version else False
31+
32+
# yield
33+
if not publish:
34+
yield
35+
return
36+
37+
run_broker = request.config.getoption('--run-broker')
38+
39+
if not run_broker:
40+
yield
41+
return
42+
else:
43+
print('Starting broker')
44+
with DockerCompose("../broker",
45+
compose_file_name=["docker-compose.yml"],
46+
pull=True) as compose:
47+
48+
stdout, stderr = compose.get_logs()
49+
if stderr:
50+
print("Errors\\n:{}".format(stderr))
51+
print(stdout)
52+
yield

examples/message/run_pytest.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/bash
22
set -o pipefail
33

4-
pytest
4+
pytest --run-broker True --publish-pact 2
55

66
# publish to broker assuming broker is active
77
# pytest tests/consumer/test_message_consumer.py::test_publish_to_broker --publish-pact 2

examples/message/tests/conftest.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

examples/message/tests/consumer/test_message_consumer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ def test_publish_to_broker(pact):
123123
124124
`pytest tests/consumer/test_message_consumer.py::test_publish_pact_to_broker --publish-pact 2`
125125
"""
126+
cleanup_json(PACT_FILE)
127+
126128
expected_event = {
127129
"event": "ObjectCreated:Delete",
128130
"documentName": "document.doc",

examples/message/tests/provider/test_message_provider.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
import pytest
22
from pact import MessageProvider
33

4+
PACT_BROKER_URL = "http://localhost"
5+
PACT_BROKER_USERNAME = "pactbroker"
6+
PACT_BROKER_PASSWORD = "pactbroker"
7+
PACT_DIR = "pacts"
8+
9+
10+
@pytest.fixture
11+
def default_opts():
12+
return {
13+
'broker_username': PACT_BROKER_USERNAME,
14+
'broker_password': PACT_BROKER_PASSWORD,
15+
'broker_url': PACT_BROKER_URL,
16+
'publish_version': '3',
17+
'publish_verification_results': False
18+
}
19+
420

521
def document_created_handler():
622
return {
@@ -49,3 +65,19 @@ def test_verify_failure_when_a_provider_missing():
4965
with pytest.raises(AssertionError):
5066
with provider:
5167
provider.verify()
68+
69+
70+
def test_verify_from_broker(default_opts):
71+
provider = MessageProvider(
72+
message_providers={
73+
'A document created successfully': document_created_handler,
74+
'A document deleted successfully': document_deleted_handler
75+
},
76+
provider='ContentProvider',
77+
consumer='DetectContentLambda',
78+
pact_dir='pacts'
79+
80+
)
81+
82+
with provider:
83+
provider.verify_with_broker(**default_opts)

pact/message_pact.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ def write_to_pact_file(self):
171171
]
172172

173173
self._message_process = Popen(command)
174+
self._message_process.wait()
174175

175176
def _insert_message_if_complete(self):
176177
"""

pact/message_provider.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,25 @@ def verify(self):
115115
return_code, _ = verifier.verify_pacts(pact_files, verbose=False)
116116
assert (return_code == 0), f'Expected returned_code = 0, actual = {return_code}'
117117

118+
def verify_with_broker(self, enable_pending=False, include_wip_pacts_since=None, **kwargs):
119+
"""Use Broker to verify.
120+
121+
Args:
122+
broker_username ([String]): broker username
123+
broker_password ([String]): broker password
124+
broker_url ([String]): url of broker
125+
enable_pending ([Boolean])
126+
include_wip_pacts_since ([String])
127+
publish_version ([String])
128+
129+
"""
130+
verifier = Verifier(provider=self.provider,
131+
provider_base_url=self._proxy_url())
132+
133+
return_code, _ = verifier.verify_with_broker(enable_pending, include_wip_pacts_since, **kwargs)
134+
135+
assert (return_code == 0), f'Expected returned_code = 0, actual = {return_code}'
136+
118137
def __enter__(self):
119138
"""
120139
Enter a Python context.

pact/verifier.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from pact.verify_wrapper import VerifyWrapper, path_exists, expand_directories
55

6+
67
class Verifier(object):
78
"""A Pact Verifier."""
89

0 commit comments

Comments
 (0)