]> git.openstreetmap.org Git - rails.git/blob - vendor/gems/rspec-1.1.2/lib/spec/example/example_group_methods.rb
Show whether a trace is public or private in the trace list, so that a user can easil...
[rails.git] / vendor / gems / rspec-1.1.2 / lib / spec / example / example_group_methods.rb
1 module Spec
2   module Example
3
4     module ExampleGroupMethods
5       class << self
6         def description_text(*args)
7           args.inject("") do |result, arg|
8             result << " " unless (result == "" || arg.to_s =~ /^(\s|\.|#)/)
9             result << arg.to_s
10           end
11         end
12       end
13
14       attr_reader :description_text, :description_args, :description_options, :spec_path
15
16       def inherited(klass)
17         super
18         klass.register
19       end
20
21       # Makes the describe/it syntax available from a class. For example:
22       #
23       #   class StackSpec < Spec::ExampleGroup
24       #     describe Stack, "with no elements"
25       #
26       #     before
27       #       @stack = Stack.new
28       #     end
29       #
30       #     it "should raise on pop" do
31       #       lambda{ @stack.pop }.should raise_error
32       #     end
33       #   end
34       #
35       def describe(*args, &example_group_block)
36         if example_group_block
37           self.subclass("Subclass") do
38             describe(*args)
39             module_eval(&example_group_block)
40           end
41         else
42           set_description(*args)
43           before_eval
44           self
45         end
46       end
47
48       # Use this to pull in examples from shared example groups.
49       # See Spec::Runner for information about shared example groups.
50       def it_should_behave_like(shared_example_group)
51         case shared_example_group
52         when SharedExampleGroup
53           include shared_example_group
54         else
55           example_group = SharedExampleGroup.find_shared_example_group(shared_example_group)
56           unless example_group
57             raise RuntimeError.new("Shared Example Group '#{shared_example_group}' can not be found")
58           end
59           include(example_group)
60         end
61       end
62
63       # :call-seq:
64       #   predicate_matchers[matcher_name] = method_on_object
65       #   predicate_matchers[matcher_name] = [method1_on_object, method2_on_object]
66       #
67       # Dynamically generates a custom matcher that will match
68       # a predicate on your class. RSpec provides a couple of these
69       # out of the box:
70       #
71       #   exist (or state expectations)
72       #     File.should exist("path/to/file")
73       #
74       #   an_instance_of (for mock argument constraints)
75       #     mock.should_receive(:message).with(an_instance_of(String))
76       #
77       # == Examples
78       #
79       #   class Fish
80       #     def can_swim?
81       #       true
82       #     end
83       #   end
84       #
85       #   describe Fish do
86       #     predicate_matchers[:swim] = :can_swim?
87       #     it "should swim" do
88       #       Fish.new.should swim
89       #     end
90       #   end
91       def predicate_matchers
92         @predicate_matchers ||= {:an_instance_of => :is_a?}
93       end
94
95       # Creates an instance of Spec::Example::Example and adds
96       # it to a collection of examples of the current example group.
97       def it(description=nil, &implementation)
98         e = new(description, &implementation)
99         example_objects << e
100         e
101       end
102
103       alias_method :specify, :it
104
105       # Use this to temporarily disable an example.
106       def xit(description=nil, opts={}, &block)
107         Kernel.warn("Example disabled: #{description}")
108       end
109
110       def run
111         examples = examples_to_run
112         return true if examples.empty?
113         reporter.add_example_group(self)
114         return dry_run(examples) if dry_run?
115
116         plugin_mock_framework
117         define_methods_from_predicate_matchers
118
119         success, before_all_instance_variables = run_before_all
120         success, after_all_instance_variables  = execute_examples(success, before_all_instance_variables, examples)
121         success                                = run_after_all(success, after_all_instance_variables)
122       end
123
124       def description
125         result = ExampleGroupMethods.description_text(*description_parts)
126         if result.nil? || result == ""
127           return to_s
128         else
129           result
130         end
131       end
132
133       def described_type
134         description_parts.find {|part| part.is_a?(Module)}
135       end
136
137       def description_parts #:nodoc:
138         parts = []
139         execute_in_class_hierarchy do |example_group|
140           parts << example_group.description_args
141         end
142         parts.flatten.compact
143       end
144
145       def set_description(*args)
146         args, options = args_and_options(*args)
147         @description_args = args
148         @description_options = options
149         @description_text = ExampleGroupMethods.description_text(*args)
150         @spec_path = File.expand_path(options[:spec_path]) if options[:spec_path]
151         if described_type.class == Module
152           include described_type
153         end
154         self
155       end
156
157       def examples #:nodoc:
158         examples = example_objects.dup
159         add_method_examples(examples)
160         rspec_options.reverse ? examples.reverse : examples
161       end
162
163       def number_of_examples #:nodoc:
164         examples.length
165       end
166
167       # Registers a block to be executed before each example.
168       # This method prepends +block+ to existing before blocks.
169       def prepend_before(*args, &block)
170         scope, options = scope_and_options(*args)
171         parts = before_parts_from_scope(scope)
172         parts.unshift(block)
173       end
174
175       # Registers a block to be executed before each example.
176       # This method appends +block+ to existing before blocks.
177       def append_before(*args, &block)
178         scope, options = scope_and_options(*args)
179         parts = before_parts_from_scope(scope)
180         parts << block
181       end
182       alias_method :before, :append_before
183
184       # Registers a block to be executed after each example.
185       # This method prepends +block+ to existing after blocks.
186       def prepend_after(*args, &block)
187         scope, options = scope_and_options(*args)
188         parts = after_parts_from_scope(scope)
189         parts.unshift(block)
190       end
191       alias_method :after, :prepend_after
192
193       # Registers a block to be executed after each example.
194       # This method appends +block+ to existing after blocks.
195       def append_after(*args, &block)
196         scope, options = scope_and_options(*args)
197         parts = after_parts_from_scope(scope)
198         parts << block
199       end
200
201       def remove_after(scope, &block)
202         after_each_parts.delete(block)
203       end
204
205       # Deprecated. Use before(:each)
206       def setup(&block)
207         before(:each, &block)
208       end
209
210       # Deprecated. Use after(:each)
211       def teardown(&block)
212         after(:each, &block)
213       end
214
215       def before_all_parts # :nodoc:
216         @before_all_parts ||= []
217       end
218
219       def after_all_parts # :nodoc:
220         @after_all_parts ||= []
221       end
222
223       def before_each_parts # :nodoc:
224         @before_each_parts ||= []
225       end
226
227       def after_each_parts # :nodoc:
228         @after_each_parts ||= []
229       end
230
231       # Only used from RSpec's own examples
232       def reset # :nodoc:
233         @before_all_parts = nil
234         @after_all_parts = nil
235         @before_each_parts = nil
236         @after_each_parts = nil
237       end
238
239       def register
240         rspec_options.add_example_group self
241       end
242
243       def unregister #:nodoc:
244         rspec_options.remove_example_group self
245       end
246
247       def run_before_each(example)
248         execute_in_class_hierarchy do |example_group|
249           example.eval_each_fail_fast(example_group.before_each_parts)
250         end
251       end
252
253       def run_after_each(example)
254         execute_in_class_hierarchy(:superclass_first) do |example_group|
255           example.eval_each_fail_slow(example_group.after_each_parts)
256         end
257       end
258
259     private
260       def dry_run(examples)
261         examples.each do |example|
262           rspec_options.reporter.example_started(example)
263           rspec_options.reporter.example_finished(example)
264         end
265         return true
266       end
267
268       def run_before_all
269         before_all = new("before(:all)")
270         begin
271           execute_in_class_hierarchy do |example_group|
272             before_all.eval_each_fail_fast(example_group.before_all_parts)
273           end
274           return [true, before_all.instance_variable_hash]
275         rescue Exception => e
276           reporter.failure(before_all, e)
277           return [false, before_all.instance_variable_hash]
278         end
279       end
280
281       def execute_examples(success, instance_variables, examples)
282         return [success, instance_variables] unless success
283
284         after_all_instance_variables = instance_variables
285         examples.each do |example_group_instance|
286           success &= example_group_instance.execute(rspec_options, instance_variables)
287           after_all_instance_variables = example_group_instance.instance_variable_hash
288         end
289         return [success, after_all_instance_variables]
290       end
291
292       def run_after_all(success, instance_variables)
293         after_all = new("after(:all)")
294         after_all.set_instance_variables_from_hash(instance_variables)
295         execute_in_class_hierarchy(:superclass_first) do |example_group|
296           after_all.eval_each_fail_slow(example_group.after_all_parts)
297         end
298         return success
299       rescue Exception => e
300         reporter.failure(after_all, e)
301         return false
302       end
303
304       def examples_to_run
305         all_examples = examples
306         return all_examples unless specified_examples?
307         all_examples.reject do |example|
308           matcher = ExampleMatcher.new(description.to_s, example.description)
309           !matcher.matches?(specified_examples)
310         end
311       end
312
313       def specified_examples?
314         specified_examples && !specified_examples.empty?
315       end
316
317       def specified_examples
318         rspec_options.examples
319       end
320
321       def reporter
322         rspec_options.reporter
323       end
324
325       def dry_run?
326         rspec_options.dry_run
327       end
328
329       def example_objects
330         @example_objects ||= []
331       end
332
333       def execute_in_class_hierarchy(superclass_last=false)
334         classes = []
335         current_class = self
336         while is_example_group?(current_class)
337           superclass_last ? classes << current_class : classes.unshift(current_class)
338           current_class = current_class.superclass
339         end
340         superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods)
341
342         classes.each do |example_group|
343           yield example_group
344         end
345       end
346
347       def is_example_group?(klass)
348         Module === klass && klass.kind_of?(ExampleGroupMethods)
349       end
350
351       def plugin_mock_framework
352         case mock_framework = Spec::Runner.configuration.mock_framework
353         when Module
354           include mock_framework
355         else
356           require Spec::Runner.configuration.mock_framework
357           include Spec::Plugins::MockFramework
358         end
359       end
360
361       def define_methods_from_predicate_matchers # :nodoc:
362         all_predicate_matchers = predicate_matchers.merge(
363           Spec::Runner.configuration.predicate_matchers
364         )
365         all_predicate_matchers.each_pair do |matcher_method, method_on_object|
366           define_method matcher_method do |*args|
367             eval("be_#{method_on_object.to_s.gsub('?','')}(*args)")
368           end
369         end
370       end
371
372       def scope_and_options(*args)
373         args, options = args_and_options(*args)
374         scope = (args[0] || :each), options
375       end
376
377       def before_parts_from_scope(scope)
378         case scope
379         when :each; before_each_parts
380         when :all; before_all_parts
381         end
382       end
383
384       def after_parts_from_scope(scope)
385         case scope
386         when :each; after_each_parts
387         when :all; after_all_parts
388         end
389       end
390
391       def before_eval
392       end
393
394       def add_method_examples(examples)
395         instance_methods.sort.each do |method_name|
396           if example_method?(method_name)
397             examples << new(method_name) do
398               __send__(method_name)
399             end
400           end
401         end
402       end
403
404       def example_method?(method_name)
405         should_method?(method_name)
406       end
407
408       def should_method?(method_name)
409         !(method_name =~ /^should(_not)?$/) &&
410         method_name =~ /^should/ && (
411           instance_method(method_name).arity == 0 ||
412           instance_method(method_name).arity == -1
413         )
414       end
415     end
416
417   end
418 end