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.
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.
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:
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.
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!