]> git.openstreetmap.org Git - rails.git/blob - vendor/gems/rspec-1.1.2/lib/spec/runner/options.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 / runner / options.rb
1 module Spec
2   module Runner
3     class Options
4       FILE_SORTERS = {
5         'mtime' => lambda {|file_a, file_b| File.mtime(file_b) <=> File.mtime(file_a)}
6       }
7
8       EXAMPLE_FORMATTERS = { # Load these lazily for better speed
9                'specdoc' => ['spec/runner/formatter/specdoc_formatter',                'Formatter::SpecdocFormatter'],
10                      's' => ['spec/runner/formatter/specdoc_formatter',                'Formatter::SpecdocFormatter'],
11                   'html' => ['spec/runner/formatter/html_formatter',                   'Formatter::HtmlFormatter'],
12                      'h' => ['spec/runner/formatter/html_formatter',                   'Formatter::HtmlFormatter'],
13               'progress' => ['spec/runner/formatter/progress_bar_formatter',           'Formatter::ProgressBarFormatter'],
14                      'p' => ['spec/runner/formatter/progress_bar_formatter',           'Formatter::ProgressBarFormatter'],
15       'failing_examples' => ['spec/runner/formatter/failing_examples_formatter',       'Formatter::FailingExamplesFormatter'],
16                      'e' => ['spec/runner/formatter/failing_examples_formatter',       'Formatter::FailingExamplesFormatter'],
17 'failing_example_groups' => ['spec/runner/formatter/failing_example_groups_formatter', 'Formatter::FailingExampleGroupsFormatter'],
18                      'g' => ['spec/runner/formatter/failing_example_groups_formatter', 'Formatter::FailingExampleGroupsFormatter'],
19                'profile' => ['spec/runner/formatter/profile_formatter',                'Formatter::ProfileFormatter'],
20                      'o' => ['spec/runner/formatter/profile_formatter',                'Formatter::ProfileFormatter'],
21               'textmate' => ['spec/runner/formatter/text_mate_formatter',              'Formatter::TextMateFormatter']
22       }
23
24       STORY_FORMATTERS = {
25         'plain' => ['spec/runner/formatter/story/plain_text_formatter', 'Formatter::Story::PlainTextFormatter'],
26             'p' => ['spec/runner/formatter/story/plain_text_formatter', 'Formatter::Story::PlainTextFormatter'],
27          'html' => ['spec/runner/formatter/story/html_formatter',       'Formatter::Story::HtmlFormatter'],
28             'h' => ['spec/runner/formatter/story/html_formatter',       'Formatter::Story::HtmlFormatter']
29       }
30
31       attr_accessor(
32         :backtrace_tweaker,
33         :context_lines,
34         :diff_format,
35         :dry_run,
36         :profile,
37         :examples,
38         :heckle_runner,
39         :line_number,
40         :loadby,
41         :reporter,
42         :reverse,
43         :timeout,
44         :verbose,
45         :user_input_for_runner,
46         :error_stream,
47         :output_stream,
48         # TODO: BT - Figure out a better name
49         :argv
50       )
51       attr_reader :colour, :differ_class, :files, :example_groups
52
53       def initialize(error_stream, output_stream)
54         @error_stream = error_stream
55         @output_stream = output_stream
56         @backtrace_tweaker = QuietBacktraceTweaker.new
57         @examples = []
58         @colour = false
59         @profile = false
60         @dry_run = false
61         @reporter = Reporter.new(self)
62         @context_lines = 3
63         @diff_format  = :unified
64         @files = []
65         @example_groups = []
66         @examples_run = false
67         @examples_should_be_run = nil
68         @user_input_for_runner = nil
69       end
70
71       def add_example_group(example_group)
72         @example_groups << example_group
73       end
74
75       def remove_example_group(example_group)
76         @example_groups.delete(example_group)
77       end
78
79       def run_examples
80         return true unless examples_should_be_run?
81         runner = custom_runner || ExampleGroupRunner.new(self)
82
83         runner.load_files(files_to_load)
84         if example_groups.empty?
85           true
86         else
87           success = runner.run
88           @examples_run = true
89           heckle if heckle_runner
90           success
91         end
92       end
93
94       def examples_run?
95         @examples_run
96       end
97
98       def examples_should_not_be_run
99         @examples_should_be_run = false
100       end      
101
102       def colour=(colour)
103         @colour = colour
104         begin; \
105           require 'Win32/Console/ANSI' if @colour && PLATFORM =~ /win32/; \
106         rescue LoadError ; \
107           raise "You must gem install win32console to use colour on Windows" ; \
108         end
109       end
110
111       def parse_diff(format)
112         case format
113         when :context, 'context', 'c'
114           @diff_format  = :context
115           default_differ
116         when :unified, 'unified', 'u', '', nil
117           @diff_format  = :unified
118           default_differ
119         else
120           @diff_format  = :custom
121           self.differ_class = load_class(format, 'differ', '--diff')
122         end
123       end
124
125       def parse_example(example)
126         if(File.file?(example))
127           @examples = File.open(example).read.split("\n")
128         else
129           @examples = [example]
130         end
131       end
132
133       def parse_format(format_arg)
134         format, where = ClassAndArgumentsParser.parse(format_arg)
135         unless where
136           raise "When using several --format options only one of them can be without a file" if @out_used
137           where = @output_stream
138           @out_used = true
139         end
140         @format_options ||= []
141         @format_options << [format, where]
142       end
143       
144       def formatters
145         @format_options ||= [['progress', @output_stream]]
146         @formatters ||= load_formatters(@format_options, EXAMPLE_FORMATTERS)
147       end
148
149       def story_formatters
150         @format_options ||= [['plain', @output_stream]]
151         @formatters ||= load_formatters(@format_options, STORY_FORMATTERS)
152       end
153       
154       def load_formatters(format_options, formatters)
155         format_options.map do |format, where|
156           formatter_type = if formatters[format]
157             require formatters[format][0]
158             eval(formatters[format][1], binding, __FILE__, __LINE__)
159           else
160             load_class(format, 'formatter', '--format')
161           end
162           formatter_type.new(self, where)
163         end
164       end
165
166       def load_heckle_runner(heckle)
167         suffix = [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} ? '_unsupported' : ''
168         require "spec/runner/heckle_runner#{suffix}"
169         @heckle_runner = HeckleRunner.new(heckle)
170       end
171
172       def number_of_examples
173         @example_groups.inject(0) do |sum, example_group|
174           sum + example_group.number_of_examples
175         end
176       end
177
178       protected
179       def examples_should_be_run?
180         return @examples_should_be_run unless @examples_should_be_run.nil?
181         @examples_should_be_run = true
182       end
183       
184       def differ_class=(klass)
185         return unless klass
186         @differ_class = klass
187         Spec::Expectations.differ = self.differ_class.new(self)
188       end
189
190       def load_class(name, kind, option)
191         if name =~ /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/
192           arg = $2 == "" ? nil : $2
193           [$1, arg]
194         else
195           m = "#{name.inspect} is not a valid class name"
196           @error_stream.puts m
197           raise m
198         end
199         begin
200           eval(name, binding, __FILE__, __LINE__)
201         rescue NameError => e
202           @error_stream.puts "Couldn't find #{kind} class #{name}"
203           @error_stream.puts "Make sure the --require option is specified *before* #{option}"
204           if $_spec_spec ; raise e ; else exit(1) ; end
205         end
206       end
207       
208       def files_to_load
209         result = []
210         sorted_files.each do |file|
211           if test ?d, file
212             result += Dir[File.expand_path("#{file}/**/*.rb")]
213           elsif test ?f, file
214             result << file
215           else
216             raise "File or directory not found: #{file}"
217           end
218         end
219         result
220       end
221       
222       def custom_runner
223         return nil unless custom_runner?
224         klass_name, arg = ClassAndArgumentsParser.parse(user_input_for_runner)
225         runner_type = load_class(klass_name, 'behaviour runner', '--runner')
226         return runner_type.new(self, arg)
227       end
228
229       def custom_runner?
230         return user_input_for_runner ? true : false
231       end
232       
233       def heckle
234         returns = self.heckle_runner.heckle_with
235         self.heckle_runner = nil
236         returns
237       end
238       
239       def sorted_files
240         return sorter ? files.sort(&sorter) : files
241       end
242
243       def sorter
244         FILE_SORTERS[loadby]
245       end
246
247       def default_differ
248         require 'spec/expectations/differs/default'
249         self.differ_class = Spec::Expectations::Differs::Default
250       end
251     end
252   end
253 end