In a project of any size, you are eventually bound to come across a series of tests that depend on external resources that are created or configured in an ad hoc fashion.
A typical example of such a use case would be a test suite that talks to a database. As the engineers working locally on the code base, we would probably spin up a local database instance with a more or less predictable endpoint and use that for testing. However, when running under CI, we might be required to use an already provisioned database instance on some cloud provider or, more often than not, the CI setup phase may need to start a database in a Docker container, a process that would yield a non-predictable endpoint to be connected to.
To support scenarios such as these, we must avoid hardcoding the location of resource endpoints to our tests and defer their discovery and configuration until the time when the test runs. To this end, one solution would be to use a set of environment variables to supply this information to our tests. Here is a simple test example from the Chapter04/db package that illustrates how this can be achieved:
func TestDBConnection(t *testing.T) { host, port, dbName, user, pass := os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_NAME"), os.Getenv("DB_USER"), os.Getenv("DB_PASS") db, err := sql.Open("postgres", makeDSN(user, pass, dbName, host, port)) if err != nil { t.Fatal(err) } _ = db.Close() t.Log("Connection to DB succeeded") }
The preceding example makes testing a breeze, regardless of whether we run the tests locally or in a CI environment. But what if our tests require a specialized DB that is not that easy to spin up locally? Maybe we need a DB that operates in a clustered configuration or one whose memory requirements exceed the memory that's available on our development machine. Wouldn't it be great if we could just skip that test when running locally?
It turns out that this is also quite easy to achieve with exactly the same mechanism that we used for configuring our DB endpoint. To be more precise, the absence of the required configuration settings could serve as a hint to the test that it needs to be skipped. In the preceding example, we can achieve this by adding a simple if block after fetching the environment values for the DB configuration:
Excellent! Now, if we don't export the DB_HOST environment variable before running our tests, this particular test will be skipped.