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

How RSpec Works

How RSpec Works

Penelope Phippen

April 19, 2019
Tweet

More Decks by Penelope Phippen

Other Decks in Technology

Transcript

  1. Sam Phippen Any code (except code from RSpec itself) in

    this talk is copyright Google under Apache V2
  2. Sam Phippen specs: diff-lcs (1.3) rspec (3.8.0) rspec-core (~> 3.8.0)

    rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0)
  3. Sam Phippen RSpec.describe "eg1" do it "e1" it "e2" context

    "eg1_1" do it "e3" end context "eg2_1" do it "e3" end end
  4. Sam Phippen class Match < BaseMatcher def match(expected, actual) return

    true if values_match?( expected, actual) actual.match(expected) end end
  5. Sam Phippen class Match < BaseMatcher def match(expected, actual) return

    true if values_match?( expected, actual) actual.match(expected) end end
  6. Sam Phippen def self.values_match?(expected, actual) if Hash === actual return

    hashes_match?(expected, actual) if Hash === expected elsif Array === expected && Enumerable === actual && !(Struct === actual) return arrays_match?(expected, actual.to_a) end return true if expected == actual begin expected === actual rescue ArgumentError # Some objects, like 0-arg lambdas on 1.9+, raise # ArgumentError for `expected === actual`. false end end
  7. Sam Phippen def self.values_match?(e, a) if Hash === a return

    hashes_match?(e, a) if Hash === e elsif Array === e && Enumerable === a && !(Struct === a) return arrays_match?( e, a) end
  8. Sam Phippen def self.values_match?(e, a) if Hash === a return

    hashes_match?(e, a) if Hash === e elsif Array === e && Enumerable === a && !(Struct === a) return arrays_match?( e, a) end
  9. Sam Phippen def self.hashes_match?( expected_hash, actual_hash) return false if expected_hash.size

    != actual_hash.size expected_hash.all? do |e_k, e_v| actual_value = actual_hash.fetch(e_k) { return false } values_match?(e_v, actual_value) end end
  10. Sam Phippen def self.hashes_match?( expected_hash, actual_hash) return false if expected_hash.size

    != actual_hash.size expected_hash.all? do |e_k, e_v| actual_value = actual_hash.fetch(e_k) { return false } values_match?(e_v, actual_value) end end
  11. Sam Phippen def self.hashes_match?( expected_hash, actual_hash) return false if expected_hash.size

    != actual_hash.size expected_hash.all? do |e_k, e_v| actual_value = actual_hash.fetch(e_k) { return false } values_match?(e_v, actual_value) end end
  12. Sam Phippen def self.hashes_match?( expected_hash, actual_hash) return false if expected_hash.size

    != actual_hash.size expected_hash.all? do |e_k, e_v| actual_value = actual_hash.fetch(e_k) { return false } values_match?(e_v, actual_value) end end
  13. Sam Phippen def self.hashes_match?( expected_hash, actual_hash) return false if expected_hash.size

    != actual_hash.size expected_hash.all? do |e_k, e_v| actual_value = actual_hash.fetch(e_k) { return false } values_match?(e_v, actual_value) end end
  14. Sam Phippen def self.values_match?(e, a) if Hash === a return

    hashes_match?(e, a) if Hash === e elsif Array === e && Enumerable === a && !(Struct === a) return arrays_match?( e, a) end
  15. Sam Phippen def self.arrays_match?( expected_list, actual_list) return false if expected_list.size!=actual_list.size

    expected_list.zip(actual_list).all? do |expected, actual| values_match?(expected, actual) end end
  16. Sam Phippen def self.arrays_match?( expected_list, actual_list) return false if expected_list.size!=actual_list.size

    expected_list.zip(actual_list).all? do |expected, actual| values_match?(expected, actual) end end
  17. Sam Phippen def self.arrays_match?( expected_list, actual_list) return false if expected_list.size!=actual_list.size

    expected_list.zip(actual_list).all? do |expected, actual| values_match?(expected, actual) end end
  18. Sam Phippen def values_match(expected, actual) … (the code we saw

    earlier) return true if expected == actual begin expected === actual rescue ArgumentError # Some objects, like 0-arg lambdas on # 1.9+, raise # ArgumentError for `expected === actual`. false end end
  19. Sam Phippen def values_match(expected, actual) … (the code we saw

    earlier) return true if expected == actual begin expected === actual rescue ArgumentError # Some objects, like 0-arg lambdas on # 1.9+, raise # ArgumentError for `expected === actual`. false end end
  20. Sam Phippen def values_match(expected, actual) … (the code we saw

    earlier) return true if expected == actual begin expected === actual rescue ArgumentError # Some objects, like 0-arg lambdas on # 1.9+, raise # ArgumentError for `expected === actual`. false end end
  21. Sam Phippen /a/ === “a” lambda { |x| x ==

    1 } === 1 Any Rspec matcher === a value it matches
  22. Sam Phippen RSpec.describe "mocking" do it “adds a foo method"

    do allow(foo).to receive(:bees) expect(foo.bees).to eq(nil) end end
  23. Sam Phippen RSpec.describe "mocking" do it “adds a foo method"

    do allow(foo).to receive(:bees) expect(foo.bees).to eq(nil) end end
  24. Sam Phippen RSpec.describe "mocking" do it “adds a foo method"

    do allow(foo).to receive(:bees) expect(foo.bees).to eq(nil) end end
  25. Sam Phippen RSpec.describe "mocking" do it “adds a foo method"

    do allow(foo).to receive(:bees) expect(foo.bees).to eq(nil) end end
  26. Sam Phippen RSpec.describe "mocking" do it “adds a foo method"

    do allow(foo).to receive(:bees) expect(foo.bees).to eq(nil) end end
  27. Sam Phippen At the end of the test, the MethodDouble

    puts the original method back on the object
  28. Sam Phippen RSpec.describe "mocking" do it “adds a foo method"

    do expect(foo).to receive(:bees) expect(foo.bees).to eq(nil) end end