Skip to content

Commit 490d999

Browse files
committed
Implement ability to supply multiple commands for docker_setup and docker_cleanup, while maintaining backwards compatibility.
1 parent 508b82d commit 490d999

File tree

4 files changed

+136
-10
lines changed

4 files changed

+136
-10
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,13 @@ Docker Compose V1, change this fixture to return `docker-compose`.
137137

138138
### `docker_setup`
139139

140-
Get the docker_compose command to be executed for test spawn actions.
140+
Get the list of docker_compose commands to be executed for test spawn actions.
141141
Override this fixture in your tests if you need to change spawn actions.
142142
Returning anything that would evaluate to False will skip this command.
143143

144144
### `docker_cleanup`
145145

146-
Get the docker_compose command to be executed for test clean-up actions.
146+
Get the list of docker_compose commands to be executed for test clean-up actions.
147147
Override this fixture in your tests if you need to change clean-up actions.
148148
Returning anything that would evaluate to False will skip this command.
149149

src/pytest_docker/plugin.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,7 @@ def docker_compose_project_name():
155155

156156

157157
def get_cleanup_command():
158-
159-
return "down -v"
158+
return ["down -v"]
160159

161160

162161
@pytest.fixture(scope="session")
@@ -169,8 +168,7 @@ def docker_cleanup():
169168

170169

171170
def get_setup_command():
172-
173-
return "up --build -d"
171+
return ["up --build -d"]
174172

175173

176174
@pytest.fixture(scope="session")
@@ -196,15 +194,23 @@ def get_docker_services(
196194

197195
# setup containers.
198196
if docker_setup:
199-
docker_compose.execute(docker_setup)
197+
# Maintain backwards compatibility with the string format.
198+
if isinstance(docker_setup, str):
199+
docker_setup = [docker_setup]
200+
for command in docker_setup:
201+
docker_compose.execute(command)
200202

201203
try:
202204
# Let test(s) run.
203205
yield Services(docker_compose)
204206
finally:
205207
# Clean up.
206208
if docker_cleanup:
207-
docker_compose.execute(docker_cleanup)
209+
# Maintain backwards compatibility with the string format.
210+
if isinstance(docker_cleanup, str):
211+
docker_cleanup = [docker_cleanup]
212+
for command in docker_cleanup:
213+
docker_compose.execute(command)
208214

209215

210216
@pytest.fixture(scope="session")

tests/test_docker_services.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,121 @@ def test_wait_until_responsive_timeout():
174174
)
175175
assert sleep.call_args_list == [mock.call(1.0), mock.call(1.0), mock.call(1.0)]
176176
assert str(exc.value) == ("Timeout reached while waiting on service!")
177+
178+
179+
def test_single_commands():
180+
"""Ensures backwards compatibility with single command strings for setup and cleanup."""
181+
182+
with mock.patch("subprocess.check_output") as check_output:
183+
check_output.returncode = 0
184+
185+
assert check_output.call_count == 0
186+
187+
# The fixture is a context-manager.
188+
with get_docker_services(
189+
"docker compose",
190+
"docker-compose.yml",
191+
docker_compose_project_name="pytest123",
192+
docker_setup="up --build -d",
193+
docker_cleanup="down -v",
194+
) as services:
195+
assert isinstance(services, Services)
196+
197+
assert check_output.call_count == 1
198+
199+
# Can request port for services.
200+
port = services.port_for("hello", 80)
201+
assert port == 1
202+
203+
assert check_output.call_count == 2
204+
205+
# 2nd request for same service should hit the cache.
206+
port = services.port_for("hello", 80)
207+
assert port == 1
208+
209+
assert check_output.call_count == 2
210+
211+
assert check_output.call_count == 3
212+
213+
# Both should have been called.
214+
assert check_output.call_args_list == [
215+
mock.call(
216+
'docker compose -f "docker-compose.yml" -p "pytest123" up --build -d',
217+
stderr=subprocess.STDOUT,
218+
shell=True,
219+
),
220+
mock.call(
221+
'docker compose -f "docker-compose.yml" -p "pytest123" port hello 80',
222+
stderr=subprocess.STDOUT,
223+
shell=True,
224+
),
225+
mock.call(
226+
'docker compose -f "docker-compose.yml" -p "pytest123" down -v',
227+
stderr=subprocess.STDOUT,
228+
shell=True,
229+
),
230+
]
231+
232+
233+
def test_multiple_commands():
234+
"""Multiple startup and cleanup commands should be executed."""
235+
236+
with mock.patch("subprocess.check_output") as check_output:
237+
check_output.returncode = 0
238+
239+
assert check_output.call_count == 0
240+
241+
# The fixture is a context-manager.
242+
with get_docker_services(
243+
"docker compose",
244+
"docker-compose.yml",
245+
docker_compose_project_name="pytest123",
246+
docker_setup=["ps", "up --build -d"],
247+
docker_cleanup=["down -v", "ps"],
248+
) as services:
249+
assert isinstance(services, Services)
250+
251+
assert check_output.call_count == 2
252+
253+
# Can request port for services.
254+
port = services.port_for("hello", 80)
255+
assert port == 1
256+
257+
assert check_output.call_count == 3
258+
259+
# 2nd request for same service should hit the cache.
260+
port = services.port_for("hello", 80)
261+
assert port == 1
262+
263+
assert check_output.call_count == 3
264+
265+
assert check_output.call_count == 5
266+
267+
# Both should have been called.
268+
assert check_output.call_args_list == [
269+
mock.call(
270+
'docker compose -f "docker-compose.yml" -p "pytest123" ps',
271+
stderr=subprocess.STDOUT,
272+
shell=True,
273+
),
274+
mock.call(
275+
'docker compose -f "docker-compose.yml" -p "pytest123" up --build -d',
276+
stderr=subprocess.STDOUT,
277+
shell=True,
278+
),
279+
mock.call(
280+
'docker compose -f "docker-compose.yml" -p "pytest123" port hello 80',
281+
stderr=subprocess.STDOUT,
282+
shell=True,
283+
),
284+
mock.call(
285+
'docker compose -f "docker-compose.yml" -p "pytest123" down -v',
286+
stderr=subprocess.STDOUT,
287+
shell=True,
288+
),
289+
mock.call(
290+
'docker compose -f "docker-compose.yml" -p "pytest123" ps',
291+
stderr=subprocess.STDOUT,
292+
shell=True,
293+
),
294+
]

tests/test_fixtures.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ def test_docker_compose_project(docker_compose_project_name):
1313

1414

1515
def test_docker_cleanup(docker_cleanup):
16-
assert docker_cleanup == "down -v"
16+
assert docker_cleanup == ["down -v"]
17+
1718

1819
def test_docker_setup(docker_setup):
19-
assert docker_setup == "up --build -d"
20+
assert docker_setup == ["up --build -d"]
21+
2022

2123
def test_docker_compose_comand(docker_compose_command):
2224
assert docker_compose_command == "docker compose"

0 commit comments

Comments
 (0)