1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
Feature: predicate matchers
Ruby objects commonly provide predicate methods:
```ruby
7.zero? # => false
0.zero? # => true
[1].empty? # => false
[].empty? # => true
{ :a => 5 }.has_key?(:b) # => false
{ :b => 5 }.has_key?(:b) # => true
```
You could use a basic equality matcher to set expectations on these:
```ruby
7.zero?.should == true # fails with "expected true, got false (using ==)"
```
...but RSpec provides dynamic predicate matchers that are more readable and
provide better failure output.
For any predicate method, RSpec gives you a corresponding matcher. Simply
prefix the method with `be_` and remove the question mark. Examples:
```ruby
7.should_not be_zero # calls 7.zero?
[].should be_empty # calls [].empty?
x.should be_multiple_of(3) # calls x.multiple_of?(3)
```
Alternately, for a predicate method that begins with `has_` like
`Hash#has_key?`, RSpec allows you to use an alternate form since `be_has_key`
makes no sense.
```ruby
hash.should have_key(:foo) # calls hash.has_key?(:foo)
array.should_not have_odd_values # calls array.has_odd_values?
```
In either case, RSpec provides nice, clear error messages, such as:
`expected zero? to return true, got false`
Any arguments passed to the matcher will be passed on to the predicate method.
Scenario: should be_zero (based on Fixnum#zero?)
Given a file named "should_be_zero_spec.rb" with:
"""ruby
describe 0 do
it { should be_zero }
end
describe 7 do
it { should be_zero } # deliberate failure
end
"""
When I run `rspec should_be_zero_spec.rb`
Then the output should contain "2 examples, 1 failure"
And the output should contain "expected zero? to return true, got false"
Scenario: should_not be_empty (based on Array#empty?)
Given a file named "should_not_be_empty_spec.rb" with:
"""ruby
describe [1, 2, 3] do
it { should_not be_empty }
end
describe [] do
it { should_not be_empty } # deliberate failure
end
"""
When I run `rspec should_not_be_empty_spec.rb`
Then the output should contain "2 examples, 1 failure"
And the output should contain "expected empty? to return false, got true"
Scenario: should have_key (based on Hash#has_key?)
Given a file named "should_have_key_spec.rb" with:
"""ruby
describe Hash do
subject { { :foo => 7 } }
it { should have_key(:foo) }
it { should have_key(:bar) } # deliberate failure
end
"""
When I run `rspec should_have_key_spec.rb`
Then the output should contain "2 examples, 1 failure"
And the output should contain "expected #has_key?(:bar) to return true, got false"
Scenario: should_not have_all_string_keys (based on custom #has_all_string_keys? method)
Given a file named "should_not_have_all_string_keys_spec.rb" with:
"""ruby
class Hash
def has_all_string_keys?
keys.all? { |k| String === k }
end
end
describe Hash do
context 'with symbol keys' do
subject { { :foo => 7, :bar => 5 } }
it { should_not have_all_string_keys }
end
context 'with string keys' do
subject { { 'foo' => 7, 'bar' => 5 } }
it { should_not have_all_string_keys } # deliberate failure
end
end
"""
When I run `rspec should_not_have_all_string_keys_spec.rb`
Then the output should contain "2 examples, 1 failure"
And the output should contain "expected #has_all_string_keys? to return false, got true"
Scenario: matcher arguments are passed on to the predicate method
Given a file named "predicate_matcher_argument_spec.rb" with:
"""ruby
class Fixnum
def multiple_of?(x)
(self % x).zero?
end
end
describe 12 do
it { should be_multiple_of(3) }
it { should_not be_multiple_of(7) }
# deliberate failures
it { should_not be_multiple_of(4) }
it { should be_multiple_of(5) }
end
"""
When I run `rspec predicate_matcher_argument_spec.rb`
Then the output should contain "4 examples, 2 failures"
And the output should contain "expected multiple_of?(4) to return false, got true"
And the output should contain "expected multiple_of?(5) to return true, got false"
|