Skip to content

Allow multiple setup/cleanup commands #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,13 @@ Docker Compose V1, change this fixture to return `docker-compose`.

### `docker_setup`

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

### `docker_cleanup`

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

Expand Down
18 changes: 12 additions & 6 deletions src/pytest_docker/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ def docker_compose_project_name():


def get_cleanup_command():

return "down -v"
return ["down -v"]


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


def get_setup_command():

return "up --build -d"
return ["up --build -d"]


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

# setup containers.
if docker_setup:
docker_compose.execute(docker_setup)
# Maintain backwards compatibility with the string format.
if isinstance(docker_setup, str):
docker_setup = [docker_setup]
for command in docker_setup:
docker_compose.execute(command)

try:
# Let test(s) run.
yield Services(docker_compose)
finally:
# Clean up.
if docker_cleanup:
docker_compose.execute(docker_cleanup)
# Maintain backwards compatibility with the string format.
if isinstance(docker_cleanup, str):
docker_cleanup = [docker_cleanup]
for command in docker_cleanup:
docker_compose.execute(command)


@pytest.fixture(scope=containers_scope)
Expand Down
118 changes: 118 additions & 0 deletions tests/test_docker_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,121 @@ def test_wait_until_responsive_timeout():
)
assert sleep.call_args_list == [mock.call(1.0), mock.call(1.0), mock.call(1.0)]
assert str(exc.value) == ("Timeout reached while waiting on service!")


def test_single_commands():
"""Ensures backwards compatibility with single command strings for setup and cleanup."""

with mock.patch("subprocess.check_output") as check_output:
check_output.returncode = 0

assert check_output.call_count == 0

# The fixture is a context-manager.
with get_docker_services(
"docker compose",
"docker-compose.yml",
docker_compose_project_name="pytest123",
docker_setup="up --build -d",
docker_cleanup="down -v",
) as services:
assert isinstance(services, Services)

assert check_output.call_count == 1

# Can request port for services.
port = services.port_for("hello", 80)
assert port == 1

assert check_output.call_count == 2

# 2nd request for same service should hit the cache.
port = services.port_for("hello", 80)
assert port == 1

assert check_output.call_count == 2

assert check_output.call_count == 3

# Both should have been called.
assert check_output.call_args_list == [
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" up --build -d',
stderr=subprocess.STDOUT,
shell=True,
),
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" port hello 80',
stderr=subprocess.STDOUT,
shell=True,
),
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" down -v',
stderr=subprocess.STDOUT,
shell=True,
),
]


def test_multiple_commands():
"""Multiple startup and cleanup commands should be executed."""

with mock.patch("subprocess.check_output") as check_output:
check_output.returncode = 0

assert check_output.call_count == 0

# The fixture is a context-manager.
with get_docker_services(
"docker compose",
"docker-compose.yml",
docker_compose_project_name="pytest123",
docker_setup=["ps", "up --build -d"],
docker_cleanup=["down -v", "ps"],
) as services:
assert isinstance(services, Services)

assert check_output.call_count == 2

# Can request port for services.
port = services.port_for("hello", 80)
assert port == 1

assert check_output.call_count == 3

# 2nd request for same service should hit the cache.
port = services.port_for("hello", 80)
assert port == 1

assert check_output.call_count == 3

assert check_output.call_count == 5

# Both should have been called.
assert check_output.call_args_list == [
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" ps',
stderr=subprocess.STDOUT,
shell=True,
),
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" up --build -d',
stderr=subprocess.STDOUT,
shell=True,
),
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" port hello 80',
stderr=subprocess.STDOUT,
shell=True,
),
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" down -v',
stderr=subprocess.STDOUT,
shell=True,
),
mock.call(
'docker compose -f "docker-compose.yml" -p "pytest123" ps',
stderr=subprocess.STDOUT,
shell=True,
),
]
6 changes: 4 additions & 2 deletions tests/test_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ def test_docker_compose_project(docker_compose_project_name):


def test_docker_cleanup(docker_cleanup):
assert docker_cleanup == "down -v"
assert docker_cleanup == ["down -v"]



def test_docker_setup(docker_setup):
assert docker_setup == "up --build -d"
assert docker_setup == ["up --build -d"]



def test_docker_compose_command(docker_compose_command):
Expand Down