As part of my development workflow, I usually run some integration tests. An integration test means that code interacts with some outside dependency. This could be a temporary Postgres server in a Docker container, or it could be an HTTP server. These dependencies usually take some time to start. In particular, enough time to start that our tests would fail if we ran them immediately after starting our dependencies.
To make this concrete, let’s use docker-compose to start a Postgres server in a Docker container. Our docker-compose.yml becomes
The lazy way to do step 2 is to wait a set amount of time before executing tests, typically by running the shell command sleep N. To be sure that the dependencies are indeed ready when we start our tests, we will want to set N to a safe upper bound on the depency’s startup time. If we run locally, we probably have the Docker containers cached, so docker-compose up might not take long. However, if we run our CI in Github Actions, the containers will not be cached, and so the wait time is longer and more unpredictable. This means that if we set the time to a comfortable upper bound we risk wasting time each time we run our tests.
The until shell command will run a command until it succeeds. Like a while loop but with the predicate switched. If we find a shell command that returns exit code 0 (indicating success) if the dependencies are ready, and not 0 if they are not ready, we can put this inside an until loop.