ruby expectation_matchers_spec.rb

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby expectation_matchers_spec.rb相关的知识,希望对你有一定的参考价值。

describe 'Expectation Matchers' do
  
  describe 'equivalence matchers' do

    it 'will match loose equality with #eq' do
      a = "2 cats"
      b = "2 cats"
      expect(a).to eq(b)
      expect(a).to be == b      # synonym for #eq

      c = 17
      d = 17.0
      expect(c).to eq(d)        # different types, but "close enough"
    end
    
    it 'will match value equality with #eql' do
      a = "2 cats"
      b = "2 cats"
      expect(a).to eql(b)       # just a little stricter

      c = 17
      d = 17.0
      expect(c).not_to eql(d)   # not the same, close doesn't count
    end

    it 'will match identity equality with #equal' do
      a = "2 cats"
      b = "2 cats"
      expect(a).not_to equal(b) # same value, but different object

      c = b
      expect(b).to equal(c)     # same object
      expect(b).to be(c)        # synonym for #equal
    end
    
  end
  
  describe 'truthiness matchers' do

    it 'will match true/false' do
      expect(1 < 2).to be(true)       # do not use 'be_true'
      expect(1 > 2).to be(false)      # do not use 'be_false'

      expect('foo').not_to be(true)   # the string is not exactly true
      expect(nil).not_to be(false)    # nil is not exactly false
      expect(0).not_to be(false)      # 0 is not exactly false
    end
    
    it 'will match truthy/falsey' do
      expect(1 < 2).to be_truthy
      expect(1 > 2).to be_falsey

      expect('foo').to be_truthy      # any value counts as true
      expect(nil).to be_falsey        # nil counts as false
      expect(0).not_to be_falsey      # but 0 is still not falsey enough
    end
    
    it 'will match nil' do
      expect(nil).to be_nil
      expect(nil).to be(nil)          # either way works
      
      expect(false).not_to be_nil     # nil only, just like #nil?
      expect(0).not_to be_nil         # nil only, just like #nil?
    end

  end
  
  describe 'numeric comparison matchers' do
  
    it 'will match less than/greater than' do
      expect(10).to be > 9
      expect(10).to be >= 10
      expect(10).to be <= 10
      expect(9).to be < 10
    end

    it 'will match numeric ranges' do
      expect(10).to be_between(5, 10).inclusive
      expect(10).not_to be_between(5, 10).exclusive
      expect(10).to be_within(1).of(11)
      expect(5..10).to cover(9)
    end

  end
  
  describe 'collection matchers' do
    
    it 'will match arrays' do
      array = [1,2,3]
      
      expect(array).to include(3)
      expect(array).to include(1,3)

      expect(array).to start_with(1)
      expect(array).to end_with(3)
      
      expect(array).to match_array([3,2,1])
      expect(array).not_to match_array([1,2])

      expect(array).to contain_exactly(3,2,1)   # similar to match_array
      expect(array).not_to contain_exactly(1,2) # but use individual args
    end

    it 'will match strings' do
      string = 'some string'
      
      expect(string).to include('ring')
      expect(string).to include('so', 'ring')
      
      expect(string).to start_with('so')
      expect(string).to end_with('ring')
    end
    
    it 'will match hashes' do
      hash = {:a => 1, :b => 2, :c => 3}
      
      expect(hash).to include(:a)
      expect(hash).to include(:a => 1)
      
      expect(hash).to include(:a => 1, :c => 3)
      expect(hash).to include({:a => 1, :c => 3})
      
      expect(hash).not_to include({'a' => 1, 'c' => 3})
    end
    
  end
  
  describe 'other useful matchers' do
  
    it 'will match strings with a regex' do
      # This matcher is a good way to "spot check" strings
      string = 'The order has been received.'
      expect(string).to match(/order(.+)received/)

      expect('123').to match(/\d{3}/)
      expect(123).not_to match(/\d{3}/) # only works with strings

      email = 'someone@somewhere.com'
      expect(email).to match(/\A\w+@\w+\.\w{3}\Z/)
    end

    it 'will match object types' do
      expect('test').to be_instance_of(String)
      expect('test').to be_an_instance_of(String) # alias of #be_instance_of

      expect('test').to be_kind_of(String)
      expect('test').to be_a_kind_of(String)  # alias of #be_kind_of
      expect('test').to be_a(String)          # alias of #be_kind_of
      expect([1,2,3]).to be_an(Array)         # alias of #be_kind_of
    end
    
    it 'will match objects with #respond_to' do
      string = 'test'
      expect(string).to respond_to(:length)
      expect(string).not_to respond_to(:sort)
    end

    it 'will match class instances with #have_attributes' do
      class Car
        attr_accessor :make, :year, :color
      end
      car = Car.new
      car.make = 'Dodge'
      car.year = 2010
      car.color = 'green'

      expect(car).to have_attributes(:color => 'green')
      expect(car).to have_attributes(
        :make => 'Dodge', :year => 2010, :color => 'green'
      )
    end
    
    it 'will match anything with #satisfy' do
      # This is the most flexible matcher
      expect(10).to satisfy do |value|
        (value >= 5) && (value <=10) && (value % 2 == 0)
      end
    end

  end
  
  describe 'predicate matchers' do
    
    it 'will match be_* to custom methods ending in ?' do
      # drops "be_", adds "?" to end, calls method on object
      # Can use these when methods end in "?", require no arguments, 
      # and return true/false.

      # with built-in methods
      expect([]).to be_empty                # [].empty?
      expect(1).to be_integer               # 1.integer?
      expect(0).to be_zero                  # 0.zero?
      expect(1).to be_nonzero               # 1.nonzero?
      expect(1).to be_odd                   # 1.odd?
      expect(2).to be_even                  # 1.even?
      
      # be_nil is actually an example of this too
      
      # with custom methods
      class Product
        def visible?; true; end
      end
      product = Product.new

      expect(product).to be_visible         # product.visible?
      expect(product.visible?).to be true   # exactly the same as this
    end

    it 'will match have_* to custom methods like has_*?' do
      # changes "have_" to "has_", adds "?" to end, calls method on object
      # Can use these when methods start with "has_", end in "?", 
      # and return true/false. Can have arguments, but not required.

      # with built-in methods
      hash = {:a => 1, :b => 2}
      expect(hash).to have_key(:a)          # hash.has_key?
      expect(hash).to have_value(2)         # hash.has_value?

      # with custom methods
      class Customer
        def has_pending_order?; true; end
      end
      customer = Customer.new

      expect(customer).to have_pending_order  # customer.has_pending_order?
      expect(customer.has_pending_order?).to be true  # same as this
    end
    
  end
  
  describe 'observation matchers' do
    # Note that all of these use "expect {}", not "expect()".
    # It is a special block format that allows a 
    # process to take place inside of the expectation.
    
    it 'will match when events change object attributes' do
      # calls the test before the block, 
      # then again after the block
      array = []
      expect { array << 1 }.to change(array, :empty?).from(true).to(false)

      class WebsiteHits
        attr_accessor :count
        def initialize; @count = 0; end
        def increment; @count += 1; end
      end
      hits = WebsiteHits.new
      expect { hits.increment }.to change(hits, :count).from(0).to(1)
    end
    
    it 'will match when events change any values' do
      # calls the test before the block, 
      # then again after the block

      # notice the "{}" after "change", 
      # can be used on simple variables
      x = 10
      expect { x += 1 }.to change {x}.from(10).to(11)
      expect { x += 1 }.to change {x}.by(1)
      expect { x += 1 }.to change {x}.by_at_least(1)
      expect { x += 1 }.to change {x}.by_at_most(1)
      
      # notice the "{}" after "change", 
      # can contain any block of code
      z = 11
      expect { z += 1 }.to change { z % 3 }.from(2).to(0)

      # Must have a value before the block
      # Must change the value inside the block
    end
    
    it 'will match when errors are raised' do
      # observes any errors raised by the block
      
      expect { raise StandardError }.to raise_error
      expect { raise StandardError }.to raise_exception

      expect { 1 / 0 }.to raise_error(ZeroDivisionError)
      expect { 1 / 0 }.to raise_error.with_message("divided by 0")
      expect { 1 / 0 }.to raise_error.with_message(/divided/)
      
      # Note that the negative form does 
      # not accept arguments
      expect { 1 / 1 }.not_to raise_error
    end
    
    it 'will match when output is generated' do
      # observes output sent to $stdout or $stderr

      expect { print('hello') }.to output.to_stdout
      expect { print('hello') }.to output('hello').to_stdout
      expect { print('hello') }.to output(/ll/).to_stdout

      expect { warn('problem') }.to output(/problem/).to_stderr
    end
    
  end
  
  describe 'compound expectations' do
    
    it 'will match using: and, or, &, |' do
      expect([1,2,3,4]).to start_with(1).and end_with(4)
      
      expect([1,2,3,4]).to start_with(1) & include(2)

      expect(10 * 10).to be_odd.or be > 50
      
      array = ['hello', 'goodbye'].shuffle
      expect(array.first).to eq("hello") | eq("goodbye")
    end
    
  end
  
  describe 'composing matchers' do
    # some matchers accept matchers as arguments. (new in rspec3)
    
    it 'will match all collection elements using a matcher' do
      array = [1,2,3]
      expect(array).to all( be < 5 )
    end
    
    it 'will match by sending matchers as arguments to matchers' do
      string = "hello"
      expect { string = "goodbye" }.to change { string }.
        from( match(/ll/) ).to( match(/oo/) )

      hash = {:a => 1, :b => 2, :c => 3}
      expect(hash).to include(:a => be_odd, :b => be_even, :c => be_odd)
      expect(hash).to include(:a => be > 0, :b => be_within(2).of(4))
    end
    
    it 'will match using noun-phrase aliases for matchers' do
      # These are built-in aliases that make 
      # specs read better by using noun-based 
      # phrases instead of verb-based phrases.
      
      # valid but awkward example
      fruits = ['apple', 'banana', 'cherry']
      expect(fruits).to start_with( start_with('a') ) & 
        include( match(/a.a.a/) ) & 
        end_with( end_with('y') )
      
      # improved version of the previous example
      # "start_with" becomes "a_string_starting_with"
      # "end_with" becomes "a_string_ending_with"
      # "match" becomes "a_string_matching"
      fruits = ['apple', 'banana', 'cherry']
      expect(fruits).to start_with( a_string_starting_with('a') ) & 
        include( a_string_matching(/a.a.a/) ) & 
        end_with( a_string_ending_with('y') )


      # valid but awkward example
      array = [1,2,3,4]
      expect(array).to start_with( be <= 2 ) |
        end_with( be_within(1).of(5) )

      # improved version of the previous example
      # "be <= 2" becomes "a_value <= 2"
      # "be_within" becomes "a_value_within"
      array = [1,2,3,4]
      expect(array).to start_with( a_value <= 2 ) |
        end_with( a_value_within(1).of(5) )
    end
    
  end

end
  

以上是关于ruby expectation_matchers_spec.rb的主要内容,如果未能解决你的问题,请参考以下文章

Ruby 25 岁了!Ruby 之父说 Ruby 3 有望 3 倍提速

如何学习ruby?Ruby学习技巧分享

ruby Ruby脚本,看看是否用openssl编译了ruby

什么是ruby?

ruby和ruby ee

ruby入门知识:了解ruby历史及特性