Skip to content

Commit dd78a70

Browse files
authored
feat: ability to supply multiple commands for docker_setup and docker_cleanup (#99)
1 parent e608205 commit dd78a70

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
@@ -150,13 +150,13 @@ Docker Compose V1, change this fixture to return `docker-compose`.
150150

151151
### `docker_setup`
152152

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

157157
### `docker_cleanup`
158158

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

src/pytest_docker/plugin.py

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

163163

164164
def get_cleanup_command():
165-
166-
return "down -v"
165+
return ["down -v"]
167166

168167

169168
@pytest.fixture(scope=containers_scope)
@@ -176,8 +175,7 @@ def docker_cleanup():
176175

177176

178177
def get_setup_command():
179-
180-
return "up --build -d"
178+
return ["up --build -d"]
181179

182180

183181
@pytest.fixture(scope=containers_scope)
@@ -203,15 +201,23 @@ def get_docker_services(
203201

204202
# setup containers.
205203
if docker_setup:
206-
docker_compose.execute(docker_setup)
204+
# Maintain backwards compatibility with the string format.
205+
if isinstance(docker_setup, str):
206+
docker_setup = [docker_setup]
207+
for command in docker_setup:
208+
docker_compose.execute(command)
207209

208210
try:
209211
# Let test(s) run.
210212
yield Services(docker_compose)
211213
finally:
212214
# Clean up.
213215
if docker_cleanup:
214-
docker_compose.execute(docker_cleanup)
216+
# Maintain backwards compatibility with the string format.
217+
if isinstance(docker_cleanup, str):
218+
docker_cleanup = [docker_cleanup]
219+
for command in docker_cleanup:
220+
docker_compose.execute(command)
215221

216222

217223
@pytest.fixture(scope=containers_scope)

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,11 +13,13 @@ 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

1920
def test_docker_setup(docker_setup):
20-
assert docker_setup == "up --build -d"
21+
assert docker_setup == ["up --build -d"]
22+
2123

2224

2325
def test_docker_compose_command(docker_compose_command):

0 commit comments

Comments
 (0)