(Read part 1 and part 2 of this blog series)
The lack of testing nagged at me throughout the buildout of the GiphyScraper. I’m a fan of test-driven development, especially when you know what you’re building; a test-first approach helps you think more clearly about your APIs, the inputs and the outputs, and the overall scaffolding of your application. Composition and decoupling are paramount to clean code, and tests are an awesome guide post in this regard.
That said, TDD can get a bit muddled when you’re not super settled on the direction of your project, especially one in a new language. Althought I’ve written a fair number of unit tests in Elixir for other similar small applications (including my initial stab at the Ray Tracer Challenge, which I’ll be writing about soon), I haven’t had to do much in the way of mocking, something that I think will be necessary for some of the http requests involved. So I’ve left the tests for last in this project, and will be using this as an opportunity to dive deeper into the world of Elixir testing. Let’s go.
My initial unit tests
I’ll start with the simplest test available - parse_response_data_into_image_data
. It takes a dictionary and returns a GiphyImage
. This test is almost trivial, but I want to include it because it reinforces the contract I have with the data that comes in from the Giphy API. If at any point the payload returned from Giphy changes, the pipeline will break, and the passing test will be a reminder of what the data used to look like. Here it is:
test "parse_response_data_into_image_data" do
title = "Sample GIF"
url = "https://www.giphy.com/sample-image"
username = "leofofeo"
id = "1235"
data = %{
"title" => title,
"url" => url,
"user" => %{"username" => username},
"id" => id
}
expected_giphy_image = %GiphyImage{
id: id,
title: title,
username: username,
url: url,
}
actual_image = Fetcher.parse_response_data_into_image_data(data)
assert expected_giphy_image == actual_image
end
This actually ended being a pretty useful exercise because of the nuance of Elixir maps. The Giphy data is returned as a set of key value pairs like so: %{"title" => "some title", "id" => "1234" ...}
. However, I had originally set up my tests by using :
in between key-value pairs instead of =>
, which led to warnings from the compiler that the quotes were unnecessary because all keys are atoms. Taking the compiler’s advice, I removed the quotes, but then ran into a failing test where every value of the struct was nil
. This makes sense, since in my actual function I’m accessing the map’s attributes using data["title"]
, and "title" != :title
. So this test reinforced the idea that :
is a shorthand for creating atoms
as keys in your map, wheras =>
preserves the string
type for the key.