Makers Academy Day 5

This week we were introduced to using Test doubles, and Method stubs. Being a twin, I immediately liked the idea of having a double. Doubles enable you to not break all your tests when you have dependencies in code by isolating your tests. They also save a lot of typing, allowing you to be able to create one fake instance as opposed to typing out multiple instances in the unit tests.

Your double is the simplest possible version of the object you need, and therefore you can create your own doubles in our languages like Javascript for example. Having been introduced to ruby’s Rspec double method, as our coach pointed out it’s very easy to feel as though the code is somehow magically happening behind the scenes. To demystify this, we built a basic Struct double of an object to show that if you wanted to you could create your own doubles, and that under the hood Rspec is basically creating a cardboard box version of your object. Here’s an example of a double created by one of our cohort:

After Day 5, for the weekend Airport challenge I got the opportunity to explore these concepts a bit more using the Rspec built in doubles and method stubs. I’ve drawn out a few examples of how I used them, and what I learnt in the process.

Airport Challenge

For my Airport challenge I had three classes: a plane; an airport; and a weather station. An important point to note was that as soon as I had a dependency of the Airport on the Plane class, I tried to use doubles. However, I soon got stuck and realised that for the first two User stories I didn’t actually need doubles. As I still hadn’t quite grasped how and when to use them, I found them a blocker in cracking on with the features. It was helpful to start my unit tests not using them, and then refactor the code once I got to a story where they definitely did add value. Manually writing out each instance of a plane in the airport, was an important process in helping me better understand how the objects were interacting with one another.

The first interesting use of a doubles and method stubs came when I had to create my weather station. The challenge with this station was that it used a random number generator to generate mostly sunny, but sometimes stormy weather. The value of using a double here was clear, I needed a fake instance of the weather station, that would enable me to predetermine the weather. However what was tricky about doing this was that in order to determine the weather I needed to also have a double for the random number generator:

Weather Station class and test snapshot

To tackle this problem I set up an instance variable of the number generator in the initialize method, and set it to default to a new instance of Random. This meant that I could create a fake_number that would be passed to the new instance of WeatherStation in my test, that I could then set to a number of my choice. As you can see above the fake_number double from line 4 was then used with the method stubs on lines 8 & 13, allow my fake_number to be called on the random method and give a number of my choice. Perfect!

The next step was translating my fake weather station to my Airport class because I now couldn’t land or take off planes if the weather was stormy. What I struggled with initially was understanding how the weather station could be added to my Airport. Talking it over with a friend, it clicked that the station was now a necessary part of the Airport and so needed to be initialized as an attribute. Following a similar pattern to the WeatherStation, I added the station as an instance variable. This then allowed me to use a fake_station double set to be sunny weather that I passed to my Airport instance.

Weather Station class and test snapshot.

At this point the beauty of the double and method stub really clicked. I could now use this fake_station to have the weather set to sunny across my tests, without manually changing them all and ensure consistency in my unit tests. It also meant that checking for stormy weather was much easier, as I could now just amend the method stubs of my fake_station to be stormy instead of sunny.

Doubles are really good for asking questions, and can provide canned responses that you can use for your tests.

I’d like to become more comfortable at identifying appropriate contexts in which to use doubles and method stubs, as well as experiment with creating my non-Rspec homemade ruby doubles and method stubs in the future!