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

RSpec 3 and why I `expect(you).to care`

RSpec 3 and why I `expect(you).to care`

Red Dot Ruby Conf 2014 talk about the decisions taken to create RSpec 3

Jon Rowe

June 27, 2014
Tweet

More Decks by Jon Rowe

Other Decks in Programming

Transcript

  1. class MyCustomObject def fuzzy? true end end ! describe do

    specify do my_model = MyCustomObject.new expect(my_model).to be_fuzzy end end
  2. class MyCustomObject def fuzzy? true end end ! describe do

    specify do my_model = MyCustomObject.new my_model.should be_fuzzy end end
  3. class MyCustomObject def fuzzy? true end end ! describe do

    specify do my_model = MyCustomObject.new expect(my_model).to be_fuzzy end end
  4. describe do specify do expect { fail }.to raise_error !

    x = 1 expect { x += 1 }.to( change { x }.from(1).to(2) ) end end
  5. class FuzzyProxy < BasicObject def initialize(target) @target = target end

    ! def fuzzy? true end ! def method_missing(*args, &block) @target.__send__(*args, &block) end end
  6. describe FuzzyProxy do ! it 'is fuzzy' do instance =

    FuzzyProxy.new(:some_object) instance.should be_fuzzy end ! end
  7. describe "SomeClass" do ! context "in some situation" do !

    it "will do something" do # ... end ! end ! end
  8. RSpec.describe "SomeClass" do ! context "in some situation" do !

    it "will do something" do # ... end ! end ! end
  9. class CustomFormatter # This registers the notifications this formatter #

    supports, and tells RSpec::Core::Formatters.register self, :example_sta ! def initialize(output) @output = output end ! def example_started(notification) @output << "example: “ @output << notification.example.description end ! end
  10. require ‘rspec/its' ! describe do ! person = Struct.new(:first, :last)

    do def name [first, last].join(' ') end end ! subject(:bob) { person.new('Bob', 'Jones') } ! its(:name) { is_expected.to eq 'Bob Jones' } ! end
  11. examples$ rspec lies_spec.rb --format doc ! ! name should eq

    "Bob Jones" ! Finished in 0.00094 seconds (files took 0.09512 1 example, 0 failures examples$
  12. require ‘rspec/its' ! describe "#name" do ! person = Struct.new(:first,

    :last) do def name [first, last].join(' ') end end ! it "combines first and last" do bob = person.new('Bob', 'Jones') expect(bob.name).to eq 'Bob Jones' end ! end
  13. examples$ rspec refactor_spec.rb --format doc ! ! name combines first

    and last ! Finished in 0.00084 seconds (files took 0.0084 1 example, 0 failures examples$
  14. describe "verified doubles" do ! it "does something" do my_obj

    = instance_double( "MyObject", does: "cool things” ) expect(my_obj.does).to eq "cool things" end ! end
  15. describe "verified doubles" do ! class MyObject end ! it

    "does something" do my_obj = instance_double( "MyObject", does: "cool things” ) expect(my_obj.does).to eq "cool things" end end
  16. examples$ rspec verified_doubles_in_situ_spe F ! Failures: ! 1) verified doubles

    does something Failure/Error: my_obj = instance_double("M MyObject does not implement: does # ./verified_doubles_in_situ_spec.rb:7:in ! Finished in 0.00046 seconds (files took 0.07 1 example, 1 failure
  17. describe "verified doubles" do ! class MyObject def does; true;

    end end ! it "does something" do my_obj = instance_double( "MyObject", does: "cool things” ) expect(my_obj.does).to eq "cool things" end end
  18. describe "verified doubles" do ! class MyObject def does; true;

    end end ! it "does something" do my_obj = MyObject.new allow(my_obj).to receive(:other) { "things" } expect(my_obj.other).to eq "things" end end
  19. describe "verified doubles" do ! class MyObject def does; true;

    end end ! RSpec.configuration.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end ! it "does something" do my_obj = MyObject.new allow(my_obj).to receive(:other) { "things" } expect(my_obj.other).to eq "things" end end
  20. examples$ rspec verify_partial_doubles_spec. F ! Failures: ! 1) verified doubles

    does something Failure/Error: allow(my_obj).to receive(:o #<MyObject:0x00000101820288> does not implement: other # ./verify_partial_doubles_spec.rb:13:in ! Finished in 0.00562 seconds (files took 0.08 1 example, 1 failure
  21. examples$ rspec broken_let_spec.rb F ! Failures: ! 1) Failure/Error: thing

    RuntimeError: let declaration `thing` accessed in a `before(:context)` hook at: examples/brok `let` and `subject` declarations are not intended to be called in a `before(:conte hook, as they exist to define state that is reset between each example, while
  22. examples$ rspec before_all_stubs_broken_spec F ! Failures: ! 1) Failure/Error: allow(Object).to

    receive The use of doubles or partial doubles from rspec-mocks outside of the per-test lifecycle is not supported. # ./before_all_stubs_broken_spec.rb:4:in ! Finished in 0.00504 seconds (files took 0.07 1 example, 1 failure
  23. describe do ! subject(:string) { "a string" } ! it

    { should be_a String } its(:length) { should == 8 } ! specify do string.should == "a string" end ! end
  24. examples$ transpec Gathering the spec suite data... ! Converting examples/upgrade_spec.rb

    ! Summary: ! 2 conversions from: it { should ... } to: it { is_expected.to ... } 1 conversion from: obj.should to: expect(obj).to ! 6 conversions, 0 incompletes, 0 warnings, 0
  25. describe do ! subject(:string) { "a string" } ! it

    { is_expected.to be_a String } ! describe '#length' do subject { super().length } it { is_expected.to eq(8) } end ! specify do expect(string).to eq("a string") end ! end