Implementation Aware Tests in TDD
One of the most common mistake in TDD is writing tests that are aware of the implementation details. It could be data structure used in the code. For instance, in the example below, the test is aware of the fact that the concept of color is represented as a string.
require 'minitest/autorun' class Grass attr_reader :color def initialize @color = 'green' end end describe Grass do it 'is green' do grass = Grass.new result = grass.color assert_equal 'green', result end end
The design decision of how to represent color could change to RGB values, Struct etc. In this case, the client code would like this:
grass = Grass.new if grass.color == 'green' puts "Well maintained lawn" else puts "Grass is brown" end
If we do not hide the design decisions from the clients, we will break them when we change our design decision. We can hide the design decision by rewriting our test and implementation as shown below:
require 'minitest/autorun' class Grass def initialize @color = 'green' end def green? @color == 'green' end end describe Grass do it 'is green' do grass = Grass.new result = grass.green? assert result end end
In this case, our class does not expose its internal data representation to its clients. It provides a higher level, well defined interface green? that encapsulates the data to provide a service to it’s clients. In this case, contrast the client code shown below to the previous version of the client code.
grass = Grass.new if grass.green? puts "Well maintained lawn" else puts "Grass is brown" end
The client has no knowledge about whether the color is a string, Struct or RGB values. It does not ask for data and process the data to make a decision. It uses the boolean return value of the green? method in the conditional. This makes it immune to any changes to the way the color is represented inside the Green class.
I discuss this in depth in my Test Driven Development in Ruby book published by Apress. Subscribe to my newsletter if you want to be notified about the discount coupon codes for the upcoming book.