def postgres_engine(docker_ip: str, docker_services: Services) -> Engine: """Create a container running postgres and wait for it to start.""" # `port_for` takes a container port and returns the corresponding host port port = docker_services.port_for("database", 5432) docker_services.wait_until_responsive( timeout=30.0, pause=0.1, check=lambda: is_postgress_running( host=docker_ip, database=TEST_DATABASE, user=TEST_DB_USER, password=TEST_DB_PWD, port=port, ), ) return create_engine( f"postgresql://{TEST_DB_USER}:{TEST_DB_PWD}@{docker_ip}:{port}/{TEST_DATABASE}" )
def test_wait_until_responsive_timeout(): clock = mock.MagicMock() clock.side_effect = [0.0, 1.0, 2.0, 3.0] with mock.patch("time.sleep") as sleep: docker_compose = DockerComposeExecutor( compose_files="docker-compose.yml", compose_project_name="pytest123") services = Services(docker_compose) with pytest.raises(Exception) as exc: print( services.wait_until_responsive(check=lambda: False, timeout=3.0, pause=1.0, clock=clock)) 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 docker_services(docker_compose_file, docker_compose_project_name, tmp_path_factory): # overriding `docker_services` fixture from `pytest_docker` plugin to # only launch docker images once. from filelock import FileLock from pytest_docker.plugin import DockerComposeExecutor, Services executor = DockerComposeExecutor(docker_compose_file, docker_compose_project_name) # making sure we don't accidentally launch docker-compose in parallel, # as it might result in network conflicts. Inspired by: # https://github.com/pytest-dev/pytest-xdist#making-session-scoped-fixtures-execute-only-once lockfile = tmp_path_factory.getbasetemp().parent / "docker-compose.lock" with FileLock(str(lockfile)): # pylint:disable=abstract-class-instantiated executor.execute("up --build -d") return Services(executor)