Skip to content

Commit 4c76ae8

Browse files
authored
test(examples): move shared fixtures to a common folder so they can b… (#280)
* test(examples): move shared fixtures to a common folder so they can be reused, remove repeated code * test(examples): move shared fixtures to a common folder so they can be reused, remove repeated code * test(examples): move shared fixtures to a common folder so they can be reused, remove repeated code
1 parent d9b2bb5 commit 4c76ae8

File tree

6 files changed

+127
-257
lines changed

6 files changed

+127
-257
lines changed

examples/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* [Overview](#overview)
66
* [broker](#broker)
7+
* [common](#common)
78
* [consumer](#consumer)
89
* [flask_provider](#flask_provider)
910
* [fastapi_provider](#fastapi_provider)
@@ -41,6 +42,13 @@ default Example App/Example API Pact.
4142
Running the [Pact Broker] outside the tests will mean you are able to then see the [Pact file]s submitted to the
4243
[Pact Broker] as the various tests are performed.
4344

45+
## common
46+
47+
To avoid needing to duplicate certain fixtures, such as starting up a docker based Pact broker (to demonstrate how the
48+
test process could work), the shared fixtures used by the pytests have all been placed into a single location.]
49+
This means it is easier to see the relevant code for the example without having to go through the boilerplate fixtures.
50+
See [Requiring/Loading plugins in a test module or conftest file] for further details of this approach.
51+
4452
## consumer
4553

4654
Pact is consumer-driven, which means first the contracts are created. These Pact contracts are generated during
@@ -205,3 +213,4 @@ without a [Pact Broker].
205213
[Virtual Environment]: https://docs.python.org/3/tutorial/venv.html
206214
[Sharing Pacts]: https://docs.pact.io/getting_started/sharing_pacts/]
207215
[How to Run a Flask Application]: https://www.twilio.com/blog/how-run-flask-application
216+
[Requiring/Loading plugins in a test module or conftest file]: https://docs.pytest.org/en/6.2.x/writing_plugins.html#requiring-loading-plugins-in-a-test-module-or-conftest-file

examples/common/sharedfixtures.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import pathlib
2+
3+
import docker
4+
import pytest
5+
from testcontainers.compose import DockerCompose
6+
7+
8+
# This fixture is to simulate a managed Pact Broker or Pactflow account.
9+
# For almost all purposes outside this example, you will want to use a real
10+
# broker. See https://github.com/pact-foundation/pact_broker for further details.
11+
@pytest.fixture(scope="session", autouse=True)
12+
def broker(request):
13+
version = request.config.getoption("--publish-pact")
14+
publish = True if version else False
15+
16+
# If the results are not going to be published to the broker, there is
17+
# nothing further to do anyway
18+
if not publish:
19+
yield
20+
return
21+
22+
run_broker = request.config.getoption("--run-broker")
23+
24+
if run_broker:
25+
# Start up the broker using docker-compose
26+
print("Starting broker")
27+
with DockerCompose("../broker", compose_file_name=["docker-compose.yml"], pull=True) as compose:
28+
stdout, stderr = compose.get_logs()
29+
if stderr:
30+
print("Errors\\n:{}".format(stderr))
31+
print("{}".format(stdout))
32+
print("Started broker")
33+
34+
yield
35+
print("Stopping broker")
36+
print("Broker stopped")
37+
else:
38+
# Assuming there is a broker available already, docker-compose has been
39+
# used manually as the --run-broker option has not been provided
40+
yield
41+
return
42+
43+
44+
@pytest.fixture(scope="session", autouse=True)
45+
def publish_existing_pact(broker):
46+
"""Publish the contents of the pacts folder to the Pact Broker.
47+
48+
In normal usage, a Consumer would publish Pacts to the Pact Broker after
49+
running tests - this fixture would NOT be needed.
50+
.
51+
Because the broker is being used standalone here, it will not contain the
52+
required Pacts, so we must first spin up the pact-cli and publish them.
53+
54+
In the Pact Broker logs, this corresponds to the following entry:
55+
PactBroker::Pacts::Service -- Creating new pact publication with params \
56+
{:consumer_name=>"UserServiceClient", :provider_name=>"UserService", \
57+
:revision_number=>nil, :consumer_version_number=>"1", :pact_version_sha=>nil, \
58+
:consumer_name_in_pact=>"UserServiceClient", :provider_name_in_pact=>"UserService"}
59+
"""
60+
source = str(pathlib.Path.cwd().joinpath("..", "pacts").resolve())
61+
pacts = [f"{source}:/pacts"]
62+
envs = {
63+
"PACT_BROKER_BASE_URL": "http://broker_app:9292",
64+
"PACT_BROKER_USERNAME": "pactbroker",
65+
"PACT_BROKER_PASSWORD": "pactbroker",
66+
}
67+
68+
client = docker.from_env()
69+
70+
print("Publishing existing Pact")
71+
client.containers.run(
72+
remove=True,
73+
network="broker_default",
74+
volumes=pacts,
75+
image="pactfoundation/pact-cli:latest",
76+
environment=envs,
77+
command="publish /pacts --consumer-app-version 1",
78+
)
79+
print("Finished publishing")
80+
81+
82+
def pytest_addoption(parser):
83+
parser.addoption(
84+
"--publish-pact", type=str, action="store", help="Upload generated pact file to pact broker with version"
85+
)
86+
87+
parser.addoption("--run-broker", type=bool, action="store", help="Whether to run broker in this test or not.")
88+
parser.addoption("--provider-url", type=str, action="store", help="The url to our provider.")

examples/consumer/conftest.py

Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,8 @@
1-
import pytest
2-
from testcontainers.compose import DockerCompose
1+
import sys
32

3+
# Load in the fixtures from common/sharedfixtures.py
4+
sys.path.append("../common")
45

5-
def pytest_addoption(parser):
6-
parser.addoption(
7-
"--publish-pact",
8-
type=str,
9-
action="store",
10-
help="Upload generated Pact file to Pact Broker with the version provided",
11-
)
12-
13-
parser.addoption("--run-broker", type=bool, action="store", help="Whether to run broker in this test or not")
14-
15-
16-
# This fixture is to simulate a managed Pact Broker or Pactflow account.
17-
# For almost all purposes outside this example, you will want to use a real
18-
# broker. See https://github.com/pact-foundation/pact_broker for further details.
19-
@pytest.fixture(scope="session", autouse=True)
20-
def broker(request):
21-
version = request.config.getoption("--publish-pact")
22-
publish = True if version else False
23-
24-
# If the results are not going to be published to the broker, there is
25-
# nothing further to do anyway
26-
if not publish:
27-
yield
28-
return
29-
30-
run_broker = request.config.getoption("--run-broker")
31-
32-
if run_broker:
33-
# Start up the broker using docker-compose
34-
print("Starting broker")
35-
with DockerCompose("../broker", compose_file_name=["docker-compose.yml"], pull=True) as compose:
36-
stdout, stderr = compose.get_logs()
37-
if stderr:
38-
print("Errors\\n:{}".format(stderr))
39-
print("{}".format(stdout))
40-
print("Started broker")
41-
42-
yield
43-
print("Stopping broker")
44-
print("Broker stopped")
45-
else:
46-
# Assuming there is a broker available already, docker-compose has been
47-
# used manually as the --run-broker option has not been provided
48-
yield
49-
return
6+
pytest_plugins = [
7+
"sharedfixtures",
8+
]
Lines changed: 12 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
import pathlib
1+
import sys
22
from multiprocessing import Process
33

4-
import docker
54
import pytest
6-
from testcontainers.compose import DockerCompose
75

86
from .pact_provider import run_server
97

8+
# Load in the fixtures from common/sharedfixtures.py
9+
sys.path.append("../common")
10+
11+
pytest_plugins = [
12+
"sharedfixtures",
13+
]
14+
1015

1116
@pytest.fixture(scope="module")
1217
def server():
@@ -15,86 +20,8 @@ def server():
1520
yield proc
1621

1722
# Cleanup after test
18-
proc.kill()
19-
20-
21-
def pytest_addoption(parser):
22-
parser.addoption(
23-
"--publish-pact", type=str, action="store", help="Upload generated pact file to pact broker with version"
24-
)
25-
26-
parser.addoption("--run-broker", type=bool, action="store", help="Whether to run broker in this test or not.")
27-
28-
29-
@pytest.fixture(scope="session", autouse=True)
30-
def publish_existing_pact(broker):
31-
"""Publish the contents of the pacts folder to the Pact Broker.
32-
33-
In normal usage, a Consumer would publish Pacts to the Pact Broker after
34-
running tests - this fixture would NOT be needed.
35-
.
36-
Because the broker is being used standalone here, it will not contain the
37-
required Pacts, so we must first spin up the pact-cli and publish them.
38-
39-
In the Pact Broker logs, this corresponds to the following entry:
40-
PactBroker::Pacts::Service -- Creating new pact publication with params \
41-
{:consumer_name=>"UserServiceClient", :provider_name=>"UserService", \
42-
:revision_number=>nil, :consumer_version_number=>"1", :pact_version_sha=>nil, \
43-
:consumer_name_in_pact=>"UserServiceClient", :provider_name_in_pact=>"UserService"}
44-
"""
45-
source = str(pathlib.Path.cwd().joinpath("..", "pacts").resolve())
46-
pacts = [f"{source}:/pacts"]
47-
envs = {
48-
"PACT_BROKER_BASE_URL": "http://broker_app:9292",
49-
"PACT_BROKER_USERNAME": "pactbroker",
50-
"PACT_BROKER_PASSWORD": "pactbroker",
51-
}
52-
53-
client = docker.from_env()
54-
55-
print("Publishing existing Pact")
56-
client.containers.run(
57-
remove=True,
58-
network="broker_default",
59-
volumes=pacts,
60-
image="pactfoundation/pact-cli:latest",
61-
environment=envs,
62-
command="publish /pacts --consumer-app-version 1",
63-
)
64-
print("Finished publishing")
65-
66-
67-
# This fixture is to simulate a managed Pact Broker or Pactflow account.
68-
# For almost all purposes outside this example, you will want to use a real
69-
# broker. See https://github.com/pact-foundation/pact_broker for further details.
70-
@pytest.fixture(scope="session", autouse=True)
71-
def broker(request):
72-
version = request.config.getoption("--publish-pact")
73-
publish = True if version else False
74-
75-
# If the results are not going to be published to the broker, there is
76-
# nothing further to do anyway
77-
if not publish:
78-
yield
79-
return
80-
81-
run_broker = request.config.getoption("--run-broker")
82-
83-
if run_broker:
84-
# Start up the broker using docker-compose
85-
print("Starting broker")
86-
with DockerCompose("../broker", compose_file_name=["docker-compose.yml"], pull=True) as compose:
87-
stdout, stderr = compose.get_logs()
88-
if stderr:
89-
print("Errors\\n:{}".format(stderr))
90-
print("{}".format(stdout))
91-
print("Started broker")
92-
93-
yield
94-
print("Stopping broker")
95-
print("Broker stopped")
23+
if sys.version_info >= (3, 7):
24+
# multiprocessing.kill is new in 3.7
25+
proc.kill()
9626
else:
97-
# Assuming there is a broker available already, docker-compose has been
98-
# used manually as the --run-broker option has not been provided
99-
yield
100-
return
27+
proc.terminate()
Lines changed: 6 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,8 @@
1-
import pathlib
1+
import sys
22

3-
import docker
4-
import pytest
5-
from testcontainers.compose import DockerCompose
3+
# Load in the fixtures from common/sharedfixtures.py
4+
sys.path.append("../common")
65

7-
8-
def pytest_addoption(parser):
9-
parser.addoption(
10-
"--publish-pact", type=str, action="store", help="Upload generated pact file to pact broker with version"
11-
)
12-
13-
parser.addoption("--run-broker", type=bool, action="store", help="Whether to run broker in this test or not.")
14-
15-
16-
@pytest.fixture(scope="session", autouse=True)
17-
def publish_existing_pact(broker):
18-
"""Publish the contents of the pacts folder to the Pact Broker.
19-
20-
In normal usage, a Consumer would publish Pacts to the Pact Broker after
21-
running tests - this fixture would NOT be needed.
22-
.
23-
Because the broker is being used standalone here, it will not contain the
24-
required Pacts, so we must first spin up the pact-cli and publish them.
25-
26-
In the Pact Broker logs, this corresponds to the following entry:
27-
PactBroker::Pacts::Service -- Creating new pact publication with params \
28-
{:consumer_name=>"UserServiceClient", :provider_name=>"UserService", \
29-
:revision_number=>nil, :consumer_version_number=>"1", :pact_version_sha=>nil, \
30-
:consumer_name_in_pact=>"UserServiceClient", :provider_name_in_pact=>"UserService"}
31-
"""
32-
source = str(pathlib.Path.cwd().joinpath("..", "pacts").resolve())
33-
pacts = [f"{source}:/pacts"]
34-
envs = {
35-
"PACT_BROKER_BASE_URL": "http://broker_app:9292",
36-
"PACT_BROKER_USERNAME": "pactbroker",
37-
"PACT_BROKER_PASSWORD": "pactbroker",
38-
}
39-
40-
client = docker.from_env()
41-
42-
print("Publishing existing Pact")
43-
client.containers.run(
44-
remove=True,
45-
network="broker_default",
46-
volumes=pacts,
47-
image="pactfoundation/pact-cli:latest",
48-
environment=envs,
49-
command="publish /pacts --consumer-app-version 1",
50-
)
51-
print("Finished publishing")
52-
53-
54-
# This fixture is to simulate a managed Pact Broker or Pactflow account.
55-
# For almost all purposes outside this example, you will want to use a real
56-
# broker. See https://github.com/pact-foundation/pact_broker for further details.
57-
@pytest.fixture(scope="session", autouse=True)
58-
def broker(request):
59-
version = request.config.getoption("--publish-pact")
60-
publish = True if version else False
61-
62-
# If the results are not going to be published to the broker, there is
63-
# nothing further to do anyway
64-
if not publish:
65-
yield
66-
return
67-
68-
run_broker = request.config.getoption("--run-broker")
69-
70-
if run_broker:
71-
# Start up the broker using docker-compose
72-
print("Starting broker")
73-
with DockerCompose("../broker", compose_file_name=["docker-compose.yml"], pull=True) as compose:
74-
stdout, stderr = compose.get_logs()
75-
if stderr:
76-
print("Errors\\n:{}".format(stderr))
77-
print("{}".format(stdout))
78-
print("Started broker")
79-
80-
yield
81-
print("Stopping broker")
82-
print("Broker stopped")
83-
else:
84-
# Assuming there is a broker available already, docker-compose has been
85-
# used manually as the --run-broker option has not been provided
86-
yield
87-
return
6+
pytest_plugins = [
7+
"sharedfixtures",
8+
]

0 commit comments

Comments
 (0)