Testing

Don't test your code by running the exact same code


Test Driven Development and Unit Testing are great. There’s an issue I see every now and then that’s sometimes very subtle. The problem is testing code by executing the exact same code. This leads to a false sense of test coverage, if the underlying implementation changes your test will still be green.

Instead, write tests that test the actual expected output. This probably means hard coding your test data bit more, and writing more explicit tests.

Take this example class that multiplies two values:

class Multiplier
  def self.multiply(a, b)
    a * b
  end
end

A simple test can look something like this:

RSpec.describe Multiplier do
  it "multiplies" do
    expect(Multiplier.multiply(2, 2)).to eq(2*2)
  end
end

The problem is that it’s duplicating the exact same code as in the class. If the underlying implementation of * changes (which is a stretch, but totally doable in Ruby), the test still passes.

A better test would check against the actual output you expect. This tests that the code actually does what you’d expect in real life.

RSpec.describe Multiplier do
  it "multiplies" do
    expect(Multiplier.multiply(2, 2)).to eq(4)
  end
end

One more greatly simplified example:

RSpec.describe Event do
  it "includes the name in the decorated name" do
    event = Event.create!(name: "Meeting")

    # `full_name` includes some other data as well
    expect(event.full_name).to include event.name
  end
end

If something happens that changes the name, the test will never fail because it will run the exact same code and compare against the changed value. A better test would test against the actual value:

RSpec.describe Event do
  it "includes the name in the decorated name" do
    event = Event.create!(name: "Meeting")

    # `full_name` includes some other data as well
    expect(event.full_name).to include "Meeting"
  end
end

These examples are simplified, usually it’s less obvious when this is happening. A great red flag to notice this pattern is when the right side of the expectation runs code.