From df96c6a4ed4653af19b3363248ba36d87be1bff9 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 3 Jun 2026 08:33:10 -0400 Subject: [PATCH] test(docker): add Docker Desktop auto-start and detection --- tests/test_docker_build.py | 90 +++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/tests/test_docker_build.py b/tests/test_docker_build.py index bc788c74..b964a247 100644 --- a/tests/test_docker_build.py +++ b/tests/test_docker_build.py @@ -2,6 +2,7 @@ import os import shutil import subprocess +import sys import time import pytest @@ -14,14 +15,82 @@ WEB_PORT = 18080 HOOK_PORT = 18999 -@pytest.mark.docker -def test_docker_image_builds(tmp_path): - """Build the Docker image. Slow; opt-in.""" +def _docker_daemon_ready() -> bool: + result = subprocess.run( + ["docker", "info"], + capture_output=True, + text=True, + timeout=10, + ) + return result.returncode == 0 + + +def _start_docker_desktop() -> bool: + if sys.platform != "win32": + return False + docker_paths = [ + os.path.expandvars(r"%ProgramFiles%\Docker\Docker\Docker Desktop.exe"), + os.path.expandvars(r"%LOCALAPPDATA%\Docker\Docker Desktop.exe"), + r"C:\Program Files\Docker\Docker\Docker Desktop.exe", + r"C:\Users\Ed\AppData\Local\Docker\Docker Desktop.exe", + ] + for path in docker_paths: + if os.path.exists(path): + try: + subprocess.Popen([path], shell=False) + return True + except Exception: + pass + service_result = subprocess.run( + ["net", "start", "com.docker.service"], + capture_output=True, + text=True, + timeout=10, + ) + if service_result.returncode == 0: + return True + return False + + +def _wait_for_docker(timeout: int = 60) -> bool: + start = time.time() + while time.time() - start < timeout: + if _docker_daemon_ready(): + return True + time.sleep(2) + return False + + +@pytest.fixture(scope="module") +def ensure_docker(): + """Ensure Docker daemon is running before running tests.""" if os.environ.get("RUN_DOCKER_TEST") != "1": pytest.skip("Set RUN_DOCKER_TEST=1 to enable") - if not _docker_available(): - pytest.skip("Docker not available in this environment") + if not shutil.which("docker"): + pytest.skip("Docker CLI not installed") + + if _docker_daemon_ready(): + yield + return + + started = _start_docker_desktop() + if not started: + pytest.skip( + "Docker daemon not running and Docker Desktop not found/installed. " + "Please install Docker Desktop on this system." + ) + + ready = _wait_for_docker() + if not ready: + pytest.skip("Docker daemon did not become ready within 60s") + + yield + + +@pytest.mark.docker +def test_docker_image_builds(ensure_docker, tmp_path): + """Build the Docker image. Slow; opt-in.""" repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) result = subprocess.run( ["docker", "build", "-t", IMAGE_NAME, "."], @@ -32,13 +101,8 @@ def test_docker_image_builds(tmp_path): @pytest.mark.docker -def test_docker_container_starts_and_responds(): +def test_docker_container_starts_and_responds(ensure_docker): """Run the container, verify web and hook endpoints respond.""" - if os.environ.get("RUN_DOCKER_TEST") != "1": - pytest.skip("Set RUN_DOCKER_TEST=1 to enable") - if not _docker_available(): - pytest.skip("Docker not available in this environment") - _cleanup_container() repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -78,10 +142,6 @@ def test_docker_container_starts_and_responds(): _cleanup_container() -def _docker_available() -> bool: - return shutil.which("docker") is not None - - def _cleanup_container() -> None: subprocess.run( ["docker", "rm", "-f", CONTAINER_NAME],