seangeo / rspec forked from dchelimsky/rspec

Behaviour Driven Development framework for Ruby

rspec / rspec / spec / spec / runner / option_parser_spec.rb
100644 402 lines (338 sloc) 14.532 kb
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
require File.dirname(__FILE__) + '/../../spec_helper.rb'
require 'fileutils'
 
describe "OptionParser" do
  before(:each) do
    @out = StringIO.new
    @err = StringIO.new
    @parser = Spec::Runner::OptionParser.new(@err, @out)
  end
 
  def parse(args)
    @parser.parse(args)
    @parser.options
  end
  
  it "should accept files to include" do
    options = parse(["--pattern", "foo"])
    options.filename_pattern.should == "foo"
  end
  
  it "should accept dry run option" do
    options = parse(["--dry-run"])
    options.dry_run.should be_true
  end
  
  it "should eval and use custom formatter when none of the builtins" do
    options = parse(["--format", "Custom::Formatter"])
    options.formatters[0].class.should be(Custom::Formatter)
  end
  
  it "should support formatters with relative and absolute paths, even on windows" do
    options = parse([
      "--format", "Custom::Formatter:C:\\foo\\bar",
      "--format", "Custom::Formatter:foo/bar",
      "--format", "Custom::Formatter:foo\\bar",
      "--format", "Custom::Formatter:/foo/bar"
    ])
    options.formatters[0].where.should eql("C:\\foo\\bar")
    options.formatters[1].where.should eql("foo/bar")
    options.formatters[2].where.should eql("foo\\bar")
    options.formatters[3].where.should eql("/foo/bar")
  end
  
  it "should not be verbose by default" do
    options = parse([])
    options.verbose.should be_nil
  end
  
  it "should not use colour by default" do
    options = parse([])
    options.colour.should == false
  end
  
  it "should print help to stdout if no args" do
    pending 'A regression since 1.0.8' do
      options = parse([])
      @out.rewind
      @out.read.should match(/Usage: spec \(FILE\|DIRECTORY\|GLOB\)\+ \[options\]/m)
    end
  end
  
  it "should print help to stdout" do
    options = parse(["--help"])
    @out.rewind
    @out.read.should match(/Usage: spec \(FILE\|DIRECTORY\|GLOB\)\+ \[options\]/m)
  end
  
  it "should print instructions about how to require missing formatter" do
    lambda do
      options = parse(["--format", "Custom::MissingFormatter"])
      options.formatters
    end.should raise_error(NameError)
    @err.string.should match(/Couldn't find formatter class Custom::MissingFormatter/n)
  end
  
  it "should print version to stdout" do
    options = parse(["--version"])
    @out.rewind
    @out.read.should match(/RSpec-\d+\.\d+\.\d+.*\(build \d+\) - BDD for Ruby\nhttp:\/\/rspec.rubyforge.org\/\n/n)
  end
  
  it "should require file when require specified" do
    lambda do
      parse(["--require", "whatever"])
    end.should raise_error(LoadError)
  end
  
  it "should support c option" do
    options = parse(["-c"])
    options.colour.should be_true
  end
  
  it "should support queens colour option" do
    options = parse(["--colour"])
    options.colour.should be_true
  end
  
  it "should support us color option" do
    options = parse(["--color"])
    options.colour.should be_true
  end
  
  it "should support single example with -e option" do
    options = parse(["-e", "something or other"])
    options.examples.should eql(["something or other"])
  end
  
  it "should support single example with -s option (will be removed when autotest supports -e)" do
    options = parse(["-s", "something or other"])
    options.examples.should eql(["something or other"])
  end
  
  it "should support single example with --example option" do
    options = parse(["--example", "something or other"])
    options.examples.should eql(["something or other"])
  end
  
  it "should read several example names from file if --example is given an existing file name" do
    options = parse(["--example", File.dirname(__FILE__) + '/examples.txt'])
    options.examples.should eql([
      "Sir, if you were my husband, I would poison your drink.",
      "Madam, if you were my wife, I would drink it."])
  end
  
  it "should read no examples if given an empty file" do
    options = parse(["--example", File.dirname(__FILE__) + '/empty_file.txt'])
    options.examples.should eql([])
  end
  
  it "should use html formatter when format is h" do
    options = parse(["--format", "h"])
    options.formatters[0].class.should equal(Spec::Runner::Formatter::HtmlFormatter)
  end
  
  it "should use html story formatter when format is h" do
    options = parse(["--format", "h"])
    options.story_formatters[0].class.should equal(Spec::Runner::Formatter::Story::HtmlFormatter)
  end
  
  it "should use html formatter when format is html" do
    options = parse(["--format", "html"])
    options.formatters[0].class.should equal(Spec::Runner::Formatter::HtmlFormatter)
  end
  
  it "should use html story formatter when format is html" do
    options = parse(["--format", "html"])
    options.story_formatters[0].class.should equal(Spec::Runner::Formatter::Story::HtmlFormatter)
  end
  
  it "should use html formatter with explicit output when format is html:test.html" do
    FileUtils.rm 'test.html' if File.exist?('test.html')
    options = parse(["--format", "html:test.html"])
    options.formatters # creates the file
    File.should be_exist('test.html')
    options.formatters[0].class.should equal(Spec::Runner::Formatter::HtmlFormatter)
    options.formatters[0].close
    FileUtils.rm 'test.html'
  end
  
  it "should use noisy backtrace tweaker with b option" do
    options = parse(["-b"])
    options.backtrace_tweaker.should be_instance_of(Spec::Runner::NoisyBacktraceTweaker)
  end
  
  it "should use noisy backtrace tweaker with backtrace option" do
    options = parse(["--backtrace"])
    options.backtrace_tweaker.should be_instance_of(Spec::Runner::NoisyBacktraceTweaker)
  end
  
  it "should use quiet backtrace tweaker by default" do
    options = parse([])
    options.backtrace_tweaker.should be_instance_of(Spec::Runner::QuietBacktraceTweaker)
  end
  
  it "should use progress bar formatter by default" do
    options = parse([])
    options.formatters[0].class.should equal(Spec::Runner::Formatter::ProgressBarFormatter)
  end
  
  it "should use specdoc formatter when format is s" do
    options = parse(["--format", "s"])
    options.formatters[0].class.should equal(Spec::Runner::Formatter::SpecdocFormatter)
  end
  
  it "should use specdoc formatter when format is specdoc" do
    options = parse(["--format", "specdoc"])
    options.formatters[0].class.should equal(Spec::Runner::Formatter::SpecdocFormatter)
  end
  
  it "should support diff option when format is not specified" do
    options = parse(["--diff"])
    options.diff_format.should == :unified
  end
  
  it "should use unified diff format option when format is unified" do
    options = parse(["--diff", "unified"])
    options.diff_format.should == :unified
    options.differ_class.should equal(Spec::Expectations::Differs::Default)
  end
  
  it "should use context diff format option when format is context" do
    options = parse(["--diff", "context"])
    options.diff_format.should == :context
    options.differ_class.should == Spec::Expectations::Differs::Default
  end
  
  it "should use custom diff format option when format is a custom format" do
    Spec::Expectations.differ.should_not be_instance_of(Custom::Differ)
  
    options = parse(["--diff", "Custom::Differ"])
    options.parse_diff "Custom::Differ"
    options.diff_format.should == :custom
    options.differ_class.should == Custom::Differ
    Spec::Expectations.differ.should be_instance_of(Custom::Differ)
  end
  
  it "should print instructions about how to fix missing differ" do
    lambda { parse(["--diff", "Custom::MissingFormatter"]) }.should raise_error(NameError)
    @err.string.should match(/Couldn't find differ class Custom::MissingFormatter/n)
  end
  
  describe "when attempting a focussed spec" do
    attr_reader :file, :dir
    before do
      @original_rspec_options = $rspec_options
      @file = "#{File.dirname(__FILE__)}/spec_parser/spec_parser_fixture.rb"
      @dir = File.dirname(file)
    end
  
    after do
      $rspec_options = @original_rspec_options
    end
  
    def parse(args)
      options = super
      $rspec_options = options
      options.filename_pattern = "*_fixture.rb"
      options
    end
  
    it "should support --line to identify spec" do
      options = parse([file, "--line", "13"])
      options.line_number.should == 13
      options.examples.should be_empty
      options.run_examples
      options.examples.should eql(["d"])
    end
  
    it "should fail with error message if file is dir along with --line" do
      options = parse([dir, "--line", "169"])
      options.line_number.should == 169
      options.run_examples
      @err.string.should match(/You must specify one file, not a directory when using the --line option/n)
    end
  
    it "should fail with error message if file does not exist along with --line" do
      options = parse(["some file", "--line", "169"])
      proc do
        options.run_examples
      end.should raise_error
    end
  
    it "should fail with error message if more than one files are specified along with --line" do
      options = parse([file, file, "--line", "169"])
      options.run_examples
      @err.string.should match(/Only one file can be specified when using the --line option/n)
    end
  
    it "should fail with error message if --example and --line are used simultaneously" do
      options = parse([file, "--example", "some example", "--line", "169"])
      options.run_examples
      @err.string.should match(/You cannot use both --line and --example/n)
    end
  end
  
  if [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM}
    it "should barf when --heckle is specified (and platform is windows)" do
      lambda do
        options = parse(["--heckle", "Spec"])
      end.should raise_error(StandardError, "Heckle not supported on Windows")
    end
  else
    it "should heckle when --heckle is specified (and platform is not windows)" do
      options = parse(["--heckle", "Spec"])
      options.heckle_runner.should be_instance_of(Spec::Runner::HeckleRunner)
    end
  end
  
  it "should read options from file when --options is specified" do
    options = parse(["--options", File.dirname(__FILE__) + "/spec.opts"])
    options.diff_format.should_not be_nil
    options.colour.should be_true
  end
  
  it "should default the formatter to ProgressBarFormatter when using options file" do
    options = parse(["--options", File.dirname(__FILE__) + "/spec.opts"])
    options.formatters.first.should be_instance_of(::Spec::Runner::Formatter::ProgressBarFormatter)
  end
 
  it "should run parse drb after parsing options" do
    @parser.stub!(:parse_drb)
    @parser.should_receive(:parse_drb).with(["--drb"]).and_return(true)
    options = parse(["--options", File.dirname(__FILE__) + "/spec_drb.opts"])
  end
 
  it "should read spaced and multi-line options from file when --options is specified" do
    options = parse(["--options", File.dirname(__FILE__) + "/spec_spaced.opts"])
    options.diff_format.should_not be_nil
    options.colour.should be_true
    options.formatters.first.should be_instance_of(::Spec::Runner::Formatter::SpecdocFormatter)
  end
   
  it "should save config to file when --generate-options is specified" do
    FileUtils.rm 'test.spec.opts' if File.exist?('test.spec.opts')
    options = parse(["--colour", "--generate-options", "test.spec.opts", "--diff"])
    IO.read('test.spec.opts').should == "--colour\n--diff\n"
    FileUtils.rm 'test.spec.opts'
  end
  
  it "should save config to file when -G is specified" do
    FileUtils.rm 'test.spec.opts' if File.exist?('test.spec.opts')
    options = parse(["--colour", "-G", "test.spec.opts", "--diff"])
    IO.read('test.spec.opts').should == "--colour\n--diff\n"
    FileUtils.rm 'test.spec.opts'
  end
  
  it "when --drb is specified, calls DrbCommandLine all of the other ARGV arguments" do
    options = Spec::Runner::OptionParser.parse([
      "some/spec.rb", "--diff", "--colour"
    ], @err, @out)
    Spec::Runner::DrbCommandLine.should_receive(:run).and_return do |options|
      options.argv.should == ["some/spec.rb", "--diff", "--colour"]
    end
    parse(["some/spec.rb", "--diff", "--drb", "--colour"])
  end
  
  it "should reverse spec order when --reverse is specified" do
    options = parse(["some/spec.rb", "--reverse"])
  end
  
  it "should set an mtime comparator when --loadby mtime" do
    options = parse(["--loadby", 'mtime'])
    runner = Spec::Runner::ExampleGroupRunner.new(options)
    Spec::Runner::ExampleGroupRunner.should_receive(:new).
      with(options).
      and_return(runner)
    runner.should_receive(:load_files).with(["most_recent_spec.rb", "command_line_spec.rb"])
  
    Dir.chdir(File.dirname(__FILE__)) do
      options.files << 'command_line_spec.rb'
      options.files << 'most_recent_spec.rb'
      FileUtils.touch "most_recent_spec.rb"
      options.run_examples
      FileUtils.rm "most_recent_spec.rb"
    end
  end
  
  it "should accept the random comparator when --loadby random" do
    options = parse(["--loadby", "random"])
    options.class.should_receive(:rand).and_return(0.2, 0.1)
 
    runner = Spec::Runner::ExampleGroupRunner.new(options)
    Spec::Runner::ExampleGroupRunner.should_receive(:new).
      with(options).
      and_return(runner)
    runner.should_receive(:load_files).with(["option_parser_spec.rb", "command_line_spec.rb"])
    
    Dir.chdir(File.dirname(__FILE__)) do
      options.files << 'command_line_spec.rb'
      options.files << 'option_parser_spec.rb'
      options.run_examples
    end
  end
  
  it "should use the standard runner by default" do
    runner = ::Spec::Runner::ExampleGroupRunner.new(@parser.options)
    ::Spec::Runner::ExampleGroupRunner.should_receive(:new).
      with(@parser.options).
      and_return(runner)
    options = parse([])
    options.run_examples
  end
  
  it "should use a custom runner when given" do
    runner = Custom::ExampleGroupRunner.new(@parser.options, nil)
    Custom::ExampleGroupRunner.should_receive(:new).
      with(@parser.options, nil).
      and_return(runner)
    options = parse(["--runner", "Custom::ExampleGroupRunner"])
    options.run_examples
  end
  
  it "should use a custom runner with extra options" do
    runner = Custom::ExampleGroupRunner.new(@parser.options, 'something')
    Custom::ExampleGroupRunner.should_receive(:new).
      with(@parser.options, 'something').
      and_return(runner)
    options = parse(["--runner", "Custom::ExampleGroupRunner:something"])
    options.run_examples
  end
end