Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tests for security; Test for design

Tests for security; Test for design

Many people come to the world of test driven development because of the security it provides. However, when done correctly TDD provides loads of other benefits; specifically it can help us design better software.

In this talk we'll discuss tools and techniques to drive better designs with tests. Specifically we'll talk about test isolation with mocks and stubs, test speed, designing apis, and more. Everyone will leave with a better understanding of how to utilize TDD and BDD to create not just safer code, but better code.

Chris Keathley

October 10, 2015
Tweet

More Decks by Chris Keathley

Other Decks in Programming

Transcript

  1. Zen

  2. “Any sufficiently complicated test suite contains an ad hoc, informally-

    specified, bug-ridden, slow implementation of half of Erlang” - also me (also just now)
  3. describe Platypus do it "can drink" do platypus = Platypus.new

    coffee = Coffee.new(grams: 400) platypus.drink(coffee) expect(platypus.stomach).to include coffee end end
  4. describe Platypus do it "can drink" do platypus = Platypus.new

    coffee = Coffee.new(grams: 400) platypus.drink(coffee) expect(platypus.stomach).to include coffee end end Exposes Data
  5. describe Platypus do it "can drink" do platypus = Platypus.new

    coffee = Coffee.new(grams: 400) platypus.drink(coffee) expect(platypus.drank?(coffee)).to eql(true) end end
  6. class Platypus def initialize @stomach = [] end def drink(coffee)

    @stomach << coffee end def drank?(coffee) @stomach.include?(coffee) end end
  7. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do expect(platypus.energized?).to eql(true) end end end
  8. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do expect(platypus.energized?).to eql(true) end end end
  9. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do platypus = Platypus.new expect(platypus.energized?).to eql(true) end end end
  10. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do platypus = Platypus.new platypus.drink(Coffee.new(grams: 400)) expect(platypus.energized?).to eql(true) end end end
  11. class Platypus def initialize @stomach = [] end def drink(coffee)

    @stomach << coffee end def energized? @stomach.any? end end
  12. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do platypus = Platypus.new platypus.drink(Coffee.new(grams: 400)) expect(platypus.energized?).to eql(true) end end end
  13. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do platypus = Platypus.new platypus.drink(Coffee.new(grams: 400)) expect(platypus.energized?).to eql(true) end end end Query
  14. describe Platypus do describe "when it drinks coffee" do it

    "becomes energized" do platypus = Platypus.new platypus.drink(Coffee.new(grams: 400)) expect(platypus.energized?).to eql(true) end end end Command Query
  15. describe Platypus do describe "when it drinks coffee" do it

    "gains energy" do expect(platypus.energy).to eql(45) end end end
  16. describe Platypus do describe "when it drinks coffee" do it

    "gains energy" do platypus = Platypus.new expect(platypus.energy).to eql(45) end end end
  17. describe Platypus do describe "when it drinks coffee" do it

    "gains energy" do platypus = Platypus.new platypus.drink(coffee) expect(platypus.energy).to eql(45) end end end
  18. describe Platypus do describe "when it drinks coffee" do it

    "gains energy" do platypus = Platypus.new coffee = double(energy: 50) platypus.drink(coffee) expect(platypus.energy).to eql(45) end end end
  19. describe Platypus do describe "when it drinks coffee" do it

    "gains energy" do platypus = Platypus.new coffee = double(energy: 50) platypus.drink(coffee) expect(platypus.energy).to eql(45) end end end Assert the result
  20. class Platypus def initialize @stomach = [] end def drink(coffee)

    @stomach << coffee end def energy @stomach .map { |item| item.energy } .reduce { |acc, i| acc + i } end end
  21. class Platypus def initialize @stomach = [] end def drink(coffee)

    @stomach << coffee end def energy @stomach.map(&:energy).reduce(:+) * 0.90 end end
  22. describe Coffee do describe "#energy" do it "calculates the energy

    per gram" do coffee = Coffee.new(grams: 400) expect(coffee.energy).to eql(115) end end end
  23. describe Platypus do describe "when it waddles" do it "wears

    out its shoes" do expect(shoes).to receive(:wear) end end end
  24. describe Platypus do describe "when it waddles" do it "wears

    out its shoes" do shoes = Shoes.new expect(shoes).to receive(:wear) end end end
  25. describe Platypus do describe "when it waddles" do it "wears

    out its shoes" do shoes = Shoes.new expect(shoes).to receive(:wear) platypus.waddle! end end end
  26. describe Platypus do describe "when it waddles" do it "wears

    out its shoes" do shoes = Shoes.new platypus = Platypus.new(shoes: shoes) expect(shoes).to receive(:wear) platypus.waddle! end end end
  27. describe Platypus do describe "when it waddles" do it "wears

    out its shoes" do shoes = Shoes.new platypus = Platypus.new(shoes: shoes) expect(shoes).to receive(:wear) platypus.waddle! end end end Outgoing Command
  28. class Platypus def initialize(shoes:) @shoes = shoes @stomach = []

    end def waddle! @shoes.wear end end Dependency Injection
  29. describe Platypus do describe "when it waddles" do it "wears

    out its shoes" do shoes = Shoes.new platypus = Platypus.new(shoes: shoes) expect(shoes).to receive(:wear) platypus.waddle! expect(platypus.shod?).to eql(false) end end end
  30. class Platypus def initialize(shoes:) @shoes = shoes @stomach = []

    end def waddle! @shoes.wear end def shod? @shoes.good_condition? end end
  31. class Shoes def initialize @worn = false end def wear

    @word = true end def good_condition? !@worn end end