Anatomy of a Test
Recently, I wrote a test case for a bookmark app I've been working on recently. The app scrapes links, tags them, indexes the content for later full-text search, and archives it. The test is for a specific function in the src/bookmarker/store.gleam file. This function, store.start_job(conn, job), is responsible for marking a job as started and removing it from the pending jobs list.
The context here is that the project is written in Gleam, a functional programming language. Gleam has a convention of placing tests alongside the file being tested, but this isn't possible in Gleam, so I use a test/ directory with the same path/folder structure as the src/ directory. The name of the test file is an artifact of how Gleam's standard testing library works, and I prefer writing test names as strings for easier readability.
When writing test names, I aim to indicate the goal of the test, which may change over time, but the test name should remain fairly constant. This approach is inspired by a comment in Matklad's article about testing, though I can't confirm that.
In this test, I encapsulate the boilerplate code required to create dependencies like an SQLite connection, a mock clock, and some teardown logic. I prefer tests that manipulate the dependencies directly because they tend to be more brittle when tests are manipulating the mocks or dependencies.
In this test, I'm asserting that calling store.start_job(conn, job) will mark the job as started and remove it from the pending jobs list. The "arrange, act, assert" model of testing is a good rule of thumb, and most of my tests naturally fall into this pattern. The lines of code in the test are the "arrange" part.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.