Truth Tables help writing readable tests that are easy to maintain.

Here is an example:

describe "#to_dollars" do
  [
    [      nil,         nil],
    [        0,     "$0.00"],
    [       12,     "$0.12"],
    [     4_10,     "$4.10"],
    [   -23_00,   "$-23.00"],
    [  1230_00, "$1,230.00"]
  ].each do |amount, dollars|
    it "converts #{amount.inspect} to #{dollars.inspect}" do
      expect(to_dollars(amount)).to eq dollars
    end
  end
end

You can also use a hash if you like hash rockets:

describe EnterprisePlan, "#cost" do
  { # emails      cost
           0  =>  0_00, # free up to 200 emails
         100  =>  0_00,
         200  =>  0_00,
         250  =>  1_00, # 2 cts per email up to 400
         400  =>  4_00,
         500  =>  5_00, # 1 cts per email for 400+
        1000  => 10_00
  }.each do |emails, cost|
    it "charges #{cost} for #{emails} emails" do
      expect(EnterprisePlan.new.cost(emails)).to eq cost
    end
  end
end

And you can go crazy with multiple inputs and outputs:

describe Money do
  [ # currency  amount       human    with currency
    [    "USD",     10,     "0.10",       "$0.10" ],
    [    "EUR",     10,     "0.10",       "€0.10" ],
    # ...
  ].each do |currency, amount, human, human_with_currency|
    context "for #{currency} #{amount}" do
      it "displays #{human} by default" do
        expect(Money.new(amount, currency).human).to eq(human)
      end

      it "displays #{human_with_currency} with currency" do
        expect(Money.new(amount, currency).human(with_currency: true).to eq(human_with_currency)
      end
    end
  end
end

In my opinion, Truth Tables are really easy to read and they are also great to maintain. Adding a new test case takes a couple of seconds and does not impact readability. Here are a few more examples:

{ # ip              country   region   city
  "13.34.22.22"  => ["us"   , "or"   , "Portland"],
  "133.54.22.22" => ["ca"   , "bc"   , "Vancouver"],
  "127.0.0.1"    => [nil    , nil    , "local" ]
}


{
  "Mozilla/5.0 (Macintosh; Intel Mac OS 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36" =>
  { browser: "Chrome", platform: "Mac", device_type: "Computer", bot: false },

  "Mozilla/5.0 (Macintosh; Intel Mac OS 10_9_4) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/7.0.6 Safari/537.78.2" =>
  { browser: "Safari", platform: "Mac", device_type: "Computer", bot: false },
}


[                                                                     # alert?
  [ { last_notification_at: nil,        threshold: 1000, value: 1200 }, true ],
  [ { last_notification_at: 1.hour.ago, threshold: 1000, value: 1200 }, false ],
  [ { last_notification_at: 1.hour.ago, threshold: 1000, value: 2000 }, true ],
]

Alright, what do you think about all this? Are Truth Tables easy to read? Did I convince you to write tests with Truth Tables? Or maybe you already use Truth Tables and I missed something… And yes, I can write another sentence with Truth Tables, and in bold this time! :) Leave a comment below, I’m always happy to discuss it!

Comments disabled