]> git.openstreetmap.org Git - rails.git/blob - vendor/gems/rspec-1.1.2/lib/spec/matchers.rb
added RSpec and RSpec on Rails
[rails.git] / vendor / gems / rspec-1.1.2 / lib / spec / matchers.rb
1 require 'spec/matchers/simple_matcher'
2 require 'spec/matchers/be'
3 require 'spec/matchers/be_close'
4 require 'spec/matchers/change'
5 require 'spec/matchers/eql'
6 require 'spec/matchers/equal'
7 require 'spec/matchers/exist'
8 require 'spec/matchers/has'
9 require 'spec/matchers/have'
10 require 'spec/matchers/include'
11 require 'spec/matchers/match'
12 require 'spec/matchers/raise_error'
13 require 'spec/matchers/respond_to'
14 require 'spec/matchers/satisfy'
15 require 'spec/matchers/throw_symbol'
16 require 'spec/matchers/operator_matcher'
17
18 module Spec
19
20   # RSpec ships with a number of useful Expression Matchers. An Expression Matcher
21   # is any object that responds to the following methods:
22   #
23   #   matches?(actual)
24   #   failure_message
25   #   negative_failure_message #optional
26   #   description #optional
27   #
28   # See Spec::Expectations to learn how to use these as Expectation Matchers.
29   # See Spec::Mocks to learn how to use them as Mock Argument Constraints.
30   #
31   # == Predicates
32   #
33   # In addition to those Expression Matchers that are defined explicitly, RSpec will
34   # create custom Matchers on the fly for any arbitrary predicate, giving your specs
35   # a much more natural language feel. 
36   #
37   # A Ruby predicate is a method that ends with a "?" and returns true or false.
38   # Common examples are +empty?+, +nil?+, and +instance_of?+.
39   #
40   # All you need to do is write +should be_+ followed by the predicate without
41   # the question mark, and RSpec will figure it out from there. For example:
42   #
43   #   [].should be_empty => [].empty? #passes
44   #   [].should_not be_empty => [].empty? #fails
45   #
46   # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_"
47   # and "be_an_", making your specs read much more naturally:
48   #
49   #   "a string".should be_an_instance_of(String) =>"a string".instance_of?(String) #passes
50   #
51   #   3.should be_a_kind_of(Fixnum) => 3.kind_of?(Numeric) #passes
52   #   3.should be_a_kind_of(Numeric) => 3.kind_of?(Numeric) #passes
53   #   3.should be_an_instance_of(Fixnum) => 3.instance_of?(Fixnum) #passes
54   #   3.should_not be_instance_of(Numeric) => 3.instance_of?(Numeric) #fails
55   #
56   # RSpec will also create custom matchers for predicates like +has_key?+. To
57   # use this feature, just state that the object should have_key(:key) and RSpec will
58   # call has_key?(:key) on the target. For example:
59   #
60   #   {:a => "A"}.should have_key(:a) => {:a => "A"}.has_key?(:a) #passes
61   #   {:a => "A"}.should have_key(:b) => {:a => "A"}.has_key?(:b) #fails
62   #
63   # You can use this feature to invoke any predicate that begins with "has_", whether it is
64   # part of the Ruby libraries (like +Hash#has_key?+) or a method you wrote on your own class.
65   #
66   # == Custom Expectation Matchers
67   #
68   # When you find that none of the stock Expectation Matchers provide a natural
69   # feeling expectation, you can very easily write your own.
70   #
71   # For example, imagine that you are writing a game in which players can
72   # be in various zones on a virtual board. To specify that bob should
73   # be in zone 4, you could say:
74   #
75   #   bob.current_zone.should eql(Zone.new("4"))
76   #
77   # But you might find it more expressive to say:
78   #
79   #   bob.should be_in_zone("4")
80   #
81   # and/or
82   #
83   #   bob.should_not be_in_zone("3")
84   #
85   # To do this, you would need to write a class like this:
86   #
87   #   class BeInZone
88   #     def initialize(expected)
89   #       @expected = expected
90   #     end
91   #     def matches?(target)
92   #       @target = target
93   #       @target.current_zone.eql?(Zone.new(@expected))
94   #     end
95   #     def failure_message
96   #       "expected #{@target.inspect} to be in Zone #{@expected}"
97   #     end
98   #     def negative_failure_message
99   #       "expected #{@target.inspect} not to be in Zone #{@expected}"
100   #     end
101   #   end
102   #
103   # ... and a method like this:
104   #
105   #   def be_in_zone(expected)
106   #     BeInZone.new(expected)
107   #   end
108   #
109   # And then expose the method to your specs. This is normally done
110   # by including the method and the class in a module, which is then
111   # included in your spec:
112   #
113   #   module CustomGameMatchers
114   #     class BeInZone
115   #       ...
116   #     end
117   #
118   #     def be_in_zone(expected)
119   #       ...
120   #     end
121   #   end
122   #
123   #   describe "Player behaviour" do
124   #     include CustomGameMatchers
125   #     ...
126   #   end
127   #
128   # or you can include in globally in a spec_helper.rb file <tt>require</tt>d
129   # from your spec file(s):
130   #
131   #   Spec::Runner.configure do |config|
132   #     config.include(CustomGameMatchers)
133   #   end
134   #
135   module Matchers
136     module ModuleMethods
137       attr_accessor :generated_description
138
139       def clear_generated_description
140         self.generated_description = nil
141       end
142     end
143
144     extend ModuleMethods
145
146     def method_missing(sym, *args, &block) # :nodoc:
147       return Matchers::Be.new(sym, *args) if sym.starts_with?("be_")
148       return Matchers::Has.new(sym, *args) if sym.starts_with?("have_")
149       super
150     end
151
152     class MatcherError < StandardError
153     end
154     
155   end
156 end