rspec-core 2.7.1 → 2.8.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.md +1 -1
  2. data/features/command_line/order.feature +29 -0
  3. data/features/command_line/tag.feature +10 -9
  4. data/features/configuration/default_path.feature +2 -2
  5. data/features/filtering/exclusion_filters.feature +1 -1
  6. data/features/filtering/run_all_when_everything_filtered.feature +1 -1
  7. data/features/subject/attribute_of_subject.feature +1 -1
  8. data/lib/rspec/core.rb +148 -12
  9. data/lib/rspec/core/command_line.rb +2 -2
  10. data/lib/rspec/core/configuration.rb +300 -155
  11. data/lib/rspec/core/configuration_options.rb +34 -53
  12. data/lib/rspec/core/deprecation.rb +4 -0
  13. data/lib/rspec/core/drb_options.rb +72 -0
  14. data/lib/rspec/core/example.rb +58 -24
  15. data/lib/rspec/core/example_group.rb +10 -5
  16. data/lib/rspec/core/extensions.rb +1 -0
  17. data/lib/rspec/core/extensions/ordered.rb +16 -0
  18. data/lib/rspec/core/filter_manager.rb +170 -0
  19. data/lib/rspec/core/formatters/base_formatter.rb +3 -1
  20. data/lib/rspec/core/formatters/base_text_formatter.rb +6 -0
  21. data/lib/rspec/core/formatters/snippet_extractor.rb +1 -1
  22. data/lib/rspec/core/hooks.rb +197 -1
  23. data/lib/rspec/core/let.rb +3 -2
  24. data/lib/rspec/core/metadata.rb +25 -4
  25. data/lib/rspec/core/option_parser.rb +89 -54
  26. data/lib/rspec/core/pending.rb +41 -0
  27. data/lib/rspec/core/rake_task.rb +9 -25
  28. data/lib/rspec/core/reporter.rb +43 -19
  29. data/lib/rspec/core/shared_context.rb +35 -0
  30. data/lib/rspec/core/shared_example_group.rb +0 -1
  31. data/lib/rspec/core/subject.rb +4 -4
  32. data/lib/rspec/core/version.rb +1 -1
  33. data/lib/rspec/core/world.rb +34 -52
  34. data/spec/autotest/failed_results_re_spec.rb +2 -2
  35. data/spec/command_line/order_spec.rb +131 -0
  36. data/spec/rspec/core/command_line_spec.rb +2 -1
  37. data/spec/rspec/core/configuration_options_spec.rb +83 -163
  38. data/spec/rspec/core/configuration_spec.rb +311 -139
  39. data/spec/rspec/core/drb_options_spec.rb +131 -0
  40. data/spec/rspec/core/example_group_spec.rb +22 -11
  41. data/spec/rspec/core/example_spec.rb +1 -2
  42. data/spec/rspec/core/filter_manager_spec.rb +175 -0
  43. data/spec/rspec/core/formatters/helpers_spec.rb +1 -1
  44. data/spec/rspec/core/formatters/html_formatter_spec.rb +3 -2
  45. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -1
  46. data/spec/rspec/core/metadata_spec.rb +21 -6
  47. data/spec/rspec/core/option_parser_spec.rb +74 -0
  48. data/spec/rspec/core/reporter_spec.rb +18 -1
  49. data/spec/rspec/core/shared_context_spec.rb +54 -17
  50. data/spec/rspec/core/subject_spec.rb +1 -1
  51. data/spec/rspec/core/world_spec.rb +7 -188
  52. data/spec/spec_helper.rb +47 -43
  53. data/spec/support/config_options_helper.rb +27 -0
  54. metadata +28 -12
  55. data/lib/rspec/core/expecting/with_rspec.rb +0 -9
  56. data/lib/rspec/core/expecting/with_stdlib.rb +0 -9
@@ -95,6 +95,9 @@ module RSpec
95
95
  def dump_pending
96
96
  end
97
97
 
98
+ def seed(number)
99
+ end
100
+
98
101
  # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
99
102
  def close
100
103
  restore_sync_output
@@ -142,7 +145,6 @@ module RSpec
142
145
  match = line.match(/(.+?):(\d+)(|:\d+)/)
143
146
  match && match[1].downcase == path.downcase
144
147
  }
145
-
146
148
  end
147
149
 
148
150
  def start_sync_output
@@ -86,6 +86,12 @@ module RSpec
86
86
  end
87
87
  end
88
88
 
89
+ def seed(number)
90
+ output.puts
91
+ output.puts "Randomized with seed #{number}"
92
+ output.puts
93
+ end
94
+
89
95
  def close
90
96
  output.close if IO === output && output != $stdout
91
97
  end
@@ -8,7 +8,7 @@ module RSpec
8
8
  begin
9
9
  require 'syntax/convertors/html'
10
10
  @@converter = Syntax::Convertors::HTML.for_syntax "ruby"
11
- rescue LoadError => e
11
+ rescue LoadError
12
12
  @@converter = NullConverter.new
13
13
  end
14
14
 
@@ -77,7 +77,7 @@ module RSpec
77
77
 
78
78
  class AfterHooks < HookCollection
79
79
  def run_all(example_group_instance)
80
- reverse.each {|h| h.run_in(example_group_instance) }
80
+ reverse.each {|h| h.run_in(example_group_instance) }
81
81
  end
82
82
 
83
83
  def run_all!(example_group_instance)
@@ -87,6 +87,7 @@ module RSpec
87
87
 
88
88
  class AroundHooks < HookCollection; end
89
89
 
90
+ # @api private
90
91
  def hooks
91
92
  @hooks ||= {
92
93
  :around => { :each => AroundHooks.new },
@@ -95,37 +96,232 @@ module RSpec
95
96
  }
96
97
  end
97
98
 
99
+ # @api public
100
+ # @overload before(&block)
101
+ # @overload before(scope, &block)
102
+ # @overload before(scope, tags, &block)
103
+ # @overload before(tags, &block)
104
+ # @param [Symbol] scope `:each`, `:all`, or `:suite` (defaults to `:each`)
105
+ # @param [Hash] tags
106
+ # @see #after
107
+ # @see #around
108
+ # @see ExampleGroup
109
+ # @see SharedContext
110
+ # @see SharedExampleGroup
111
+ # @see Configuration
112
+ #
113
+ # Declare a block of code to be run before each example (using `:each`)
114
+ # or once before any example (using `:all`). These are usually declared
115
+ # directly in the [ExampleGroup](ExampleGroup) to which they apply, but
116
+ # they can also be shared across multiple groups.
117
+ #
118
+ # You can also use `before(:suite)` to run a block of code before any
119
+ # example groups are run. This should be declared in
120
+ # [RSpec.configure](../../RSpec#configure-class_method)
121
+ #
122
+ # Instance variables declared in `before(:each)` or `before(:all)` are
123
+ # accessible within each example.
124
+ #
125
+ # ### Exceptions
126
+ #
127
+ # When an exception is raised in a `before` block, RSpec skips any
128
+ # subsequent `before` blocks and the example, but runs all of the
129
+ # `after(:each)` and `after(:all)` hooks.
130
+ #
131
+ # ### Order
132
+ #
133
+ # `before` hooks are stored in three scopes, which are run in order:
134
+ # `:suite`, `:all`, and `:each`. They can also be declared in several
135
+ # different places: `RSpec.configure`, a parent group, the current group.
136
+ # They are run in the following order:
137
+ #
138
+ # before(:all) declared in RSpec.configure
139
+ # before(:all) declared in a parent group
140
+ # before(:all) declared in the current group
141
+ # before(:each) declared in RSpec.configure
142
+ # before(:each) declared in a parent group
143
+ # before(:each) declared in the current group
144
+ #
145
+ # If more than one `before` is declared within any one scope, they are run
146
+ # in the order in which they are declared.
147
+ #
148
+ # ### Warning: implicit before blocks
149
+ #
150
+ # `before` hooks can also be declared in shared contexts which get
151
+ # included implicitly either by you or by extension libraries. Since
152
+ # RSpec runs these in the order in which they are declared within each
153
+ # scope, load order matters, and can lead to confusing results when one
154
+ # before block depends on state that is prepared in another before block
155
+ # that gets run later.
156
+ #
157
+ # ### Warning: `before(:all)`
158
+ #
159
+ # It is very tempting to use `before(:all)` to speed things up, but we
160
+ # recommend that you avoid this as there are a number of gotchas, as well
161
+ # as things that simply don't work.
162
+ #
163
+ # #### context
164
+ #
165
+ # `before(:all)` is run in an example that is generated to provide group
166
+ # context for the block.
167
+ #
168
+ # #### instance variables
169
+ #
170
+ # Instance variables declared in `before(:all)` are shared across all the
171
+ # examples in the group. This means that each example can change the
172
+ # state of a shared object, resulting in an ordering dependency that can
173
+ # make it difficult to reason about failures.
174
+ #
175
+ # ### other frameworks
176
+ #
177
+ # Mock object frameworks and database transaction managers (like
178
+ # ActiveRecord) are typically designed around the idea of setting up
179
+ # before an example, running that one example, and then tearing down.
180
+ # This means that mocks and stubs can (sometimes) be declared in
181
+ # `before(:all)`, but get torn down before the first real example is ever
182
+ # run.
183
+ #
184
+ # You _can_ create database-backed model objects in a `before(:all)` in
185
+ # rspec-rails, but it will not be wrapped in a transaction for you, so
186
+ # you are on your own to clean up in an `after(:all)` block.
187
+ #
188
+ # @example before(:each) declared in an [ExampleGroup](ExampleGroup)
189
+ #
190
+ # describe Thing do
191
+ # before(:each) do
192
+ # @thing = Thing.new
193
+ # end
194
+ #
195
+ # it "does something" do
196
+ # # here you can access @thing
197
+ # end
198
+ # end
199
+ #
200
+ # @example before(:all) declared in an [ExampleGroup](ExampleGroup)
201
+ #
202
+ # describe Parser do
203
+ # before(:all) do
204
+ # File.open(file_to_parse, 'w') do |f|
205
+ # f.write <<-CONTENT
206
+ # Stuff in the file
207
+ # end
208
+ # end
209
+ # end
210
+ #
211
+ # it "parses the file" do
212
+ # Parser.parse(file_to_parse)
213
+ # end
214
+ #
215
+ # after(:all) do
216
+ # File.delete(file_to_parse)
217
+ # end
218
+ # end
98
219
  def before(*args, &block)
99
220
  scope, options = scope_and_options_from(*args)
100
221
  hooks[:before][scope] << BeforeHook.new(options, &block)
101
222
  end
102
223
 
224
+ # @api public
225
+ # @overload after(&block)
226
+ # @overload after(scope, &block)
227
+ # @overload after(scope, tags, &block)
228
+ # @overload after(tags, &block)
229
+ # @param [Symbol] scope `:each`, `:all`, or `:suite` (defaults to `:each`)
230
+ # @param [Hash] tags
231
+ # @see #before
232
+ # @see #around
233
+ # @see ExampleGroup
234
+ # @see SharedContext
235
+ # @see SharedExampleGroup
236
+ # @see Configuration
237
+ #
238
+ # Declare a block of code to be run after each example (using `:each`) or
239
+ # once after all examples (using `:all`). See
240
+ # [#before](Hooks#before-instance_method) for more information about
241
+ # ordering.
242
+ #
243
+ # ### Exceptions
244
+ #
245
+ # `after` hooks are guaranteed to run even when there are exceptions in
246
+ # `before` hooks or examples. When an exception is raised in an after
247
+ # block, the exception is captured for later reporting, and subsequent
248
+ # `after` blocks are run.
249
+ #
250
+ # ### Order
251
+ #
252
+ # `after` hooks are stored in three scopes, which are run in order:
253
+ # `:each`, `:all`, and `:suite`. They can also be declared in several
254
+ # different places: `RSpec.configure`, a parent group, the current group.
255
+ # They are run in the following order:
256
+ #
257
+ # after(:each) declared in the current group
258
+ # after(:each) declared in a parent group
259
+ # after(:each) declared in RSpec.configure
260
+ # after(:all) declared in the current group
261
+ # after(:all) declared in a parent group
262
+ # after(:all) declared in RSpec.configure
263
+ #
264
+ # This is the reverse of the order in which `before` hooks are run.
265
+ # Similarly, if more than one `after` is declared within any one scope,
266
+ # they are run in reverse order of that in which they are declared.
103
267
  def after(*args, &block)
104
268
  scope, options = scope_and_options_from(*args)
105
269
  hooks[:after][scope] << AfterHook.new(options, &block)
106
270
  end
107
271
 
272
+ # @api public
273
+ # @overload around(&block)
274
+ # @overload around(scope, &block)
275
+ # @overload around(scope, tags, &block)
276
+ # @overload around(tags, &block)
277
+ # @param [Symbol] scope `:each` (defaults to `:each`)
278
+ # @param [Hash] tags
279
+ # @yield [Example] the example to run
280
+ #
281
+ # @note `:each` is the only supported scope.
282
+ #
283
+ # Declare a block of code, parts of which will be run before and parts
284
+ # after the example. It is your responsibility to run the example:
285
+ #
286
+ # around(:each) do |ex|
287
+ # # do some stuff before
288
+ # ex.run
289
+ # # do some stuff after
290
+ # end
291
+ #
292
+ # The yielded example aliases `run` with `call`, which lets you treat it
293
+ # like a `Proc`. This is especially handy when working with libaries
294
+ # that manage their own setup and teardown using a block or proc syntax,
295
+ # e.g.
296
+ #
297
+ # around(:each) {|ex| Database.transaction(&ex)}
298
+ # around(:each) {|ex| FakeFS(&ex)}
299
+ #
108
300
  def around(*args, &block)
109
301
  scope, options = scope_and_options_from(*args)
110
302
  hooks[:around][scope] << AroundHook.new(options, &block)
111
303
  end
112
304
 
305
+ # @api private
113
306
  # Runs all of the blocks stored with the hook in the context of the
114
307
  # example. If no example is provided, just calls the hook directly.
115
308
  def run_hook(hook, scope, example_group_instance=nil)
116
309
  hooks[hook][scope].run_all(example_group_instance)
117
310
  end
118
311
 
312
+ # @api private
119
313
  # Just like run_hook, except it removes the blocks as it evalutes them,
120
314
  # ensuring that they will only be run once.
121
315
  def run_hook!(hook, scope, example_group_instance)
122
316
  hooks[hook][scope].run_all!(example_group_instance)
123
317
  end
124
318
 
319
+ # @api private
125
320
  def run_hook_filtered(hook, scope, group, example_group_instance, example = nil)
126
321
  find_hook(hook, scope, group, example).run_all(example_group_instance)
127
322
  end
128
323
 
324
+ # @api private
129
325
  def find_hook(hook, scope, example_group_class, example = nil)
130
326
  found_hooks = hooks[hook][scope].find_hooks_for(example || example_group_class)
131
327
 
@@ -6,7 +6,7 @@ module RSpec
6
6
  # Generates a method whose return value is memoized
7
7
  # after the first call.
8
8
  #
9
- # == Examples
9
+ # @example
10
10
  #
11
11
  # describe Thing do
12
12
  # let(:thing) { Thing.new }
@@ -30,7 +30,7 @@ module RSpec
30
30
  # purpose of setting up state and providing a memoized
31
31
  # reference to that state.
32
32
  #
33
- # == Examples
33
+ # @example
34
34
  #
35
35
  # class Thing
36
36
  # def self.count
@@ -86,6 +86,7 @@ module RSpec
86
86
  end
87
87
 
88
88
  module InstanceMethods
89
+ private
89
90
  def __memoized
90
91
  @__memoized ||= {}
91
92
  end
@@ -1,10 +1,16 @@
1
1
  module RSpec
2
2
  module Core
3
+ # Each ExampleGroup class and Example instance ...
4
+ #
5
+ # @see Example#metadata
6
+ # @see ExampleGroup.metadata
3
7
  class Metadata < Hash
4
8
 
5
- # Used to extend metadata Hashes to support lazy evaluation of locations
6
- # and descriptions.
7
9
  module MetadataHash
10
+
11
+ # Supports lazy evaluation of some values. Extended by
12
+ # ExampleMetadataHash and GroupMetadataHash, which get mixed in to
13
+ # Metadata for ExampleGroups and Examples (respectively).
8
14
  def [](key)
9
15
  return super if has_key?(key)
10
16
  case key
@@ -58,9 +64,19 @@ module RSpec
58
64
  end
59
65
  end
60
66
 
67
+ # Mixed in to Metadata for an Example (extends MetadataHash) to support
68
+ # lazy evaluation of some values.
69
+ module ExampleMetadataHash
70
+ include MetadataHash
71
+ end
72
+
73
+ # Mixed in to Metadata for an ExampleGroup (extends MetadataHash) to
74
+ # support lazy evaluation of some values.
61
75
  module GroupMetadataHash
62
76
  include MetadataHash
63
77
 
78
+ private
79
+
64
80
  def described_class_for(*)
65
81
  ancestors.each do |g|
66
82
  return g[:describes] if g.has_key?(:describes)
@@ -76,7 +92,7 @@ module RSpec
76
92
 
77
93
  def full_description_for(*)
78
94
  build_description_from(*ancestors.reverse.map do |a|
79
- a.has_key?(:full_description) ? a[:full_description] : a[:description_args]
95
+ a[:description_args]
80
96
  end.flatten)
81
97
  end
82
98
 
@@ -105,6 +121,7 @@ module RSpec
105
121
  yield self if block_given?
106
122
  end
107
123
 
124
+ # @api private
108
125
  def process(*args)
109
126
  user_metadata = args.last.is_a?(Hash) ? args.pop : {}
110
127
  ensure_valid_keys(user_metadata)
@@ -115,18 +132,22 @@ module RSpec
115
132
  update(user_metadata)
116
133
  end
117
134
 
135
+ # @api private
118
136
  def for_example(description, user_metadata)
119
- dup.extend(MetadataHash).configure_for_example(description, user_metadata)
137
+ dup.extend(ExampleMetadataHash).configure_for_example(description, user_metadata)
120
138
  end
121
139
 
140
+ # @api private
122
141
  def any_apply?(filters)
123
142
  filters.any? {|k,v| filter_applies?(k,v)}
124
143
  end
125
144
 
145
+ # @api private
126
146
  def all_apply?(filters)
127
147
  filters.all? {|k,v| filter_applies?(k,v)}
128
148
  end
129
149
 
150
+ # @api private
130
151
  def filter_applies?(key, value, metadata=self)
131
152
  case value
132
153
  when Hash
@@ -28,22 +28,62 @@ module RSpec::Core
28
28
  OptionParser.new do |parser|
29
29
  parser.banner = "Usage: rspec [options] [files or directories]\n\n"
30
30
 
31
- parser.on('-b', '--backtrace', 'Enable full backtrace') do |o|
32
- options[:full_backtrace] = true
31
+ parser.on('-I DIRECTORY', 'specify $LOAD_PATH directory (may be used more than once)') do |dir|
32
+ options[:libs] ||= []
33
+ options[:libs] << dir
33
34
  end
34
35
 
35
- parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output') do |o|
36
- options[:color_enabled] = o
36
+ parser.on('-r', '--require PATH', 'Require a file') do |path|
37
+ options[:requires] ||= []
38
+ options[:requires] << path
39
+ end
40
+
41
+ parser.on('-O', '--options PATH', 'Specify the path to a custom options file') do |path|
42
+ options[:custom_options_file] = path
43
+ end
44
+
45
+ parser.on('--order TYPE', 'Run examples by the specified order type',
46
+ ' [rand] randomized',
47
+ ' [random] alias for rand',
48
+ ' [random:SEED] e.g. --order random:123') do |o|
49
+ options[:order] = o
50
+ end
51
+
52
+ parser.on('--seed SEED', "Equivalent of --order rand:SEED") do |seed|
53
+ options[:order] = "rand:#{seed}"
37
54
  end
38
55
 
39
56
  parser.on('-d', '--debugger', 'Enable debugging') do |o|
40
57
  options[:debug] = true
41
58
  end
42
59
 
43
- parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING") do |o|
44
- options[:full_description] = Regexp.compile(Regexp.escape(o))
60
+ parser.on('--fail-fast', 'Abort the run on first failure') do |o|
61
+ options[:fail_fast] = true
62
+ end
63
+
64
+ parser.on('--failure-exit-code CODE', 'Override the exit code used when there are failing specs') do |o|
65
+ options[:failure_exit_code] = o.to_i
45
66
  end
46
67
 
68
+ parser.on('-X', '--[no-]drb', 'Run examples via DRb') do |o|
69
+ options[:drb] = o
70
+ end
71
+
72
+ parser.on('--drb-port [PORT]', 'Port to connect to on the DRb server') do |o|
73
+ options[:drb_port] = o.to_i
74
+ end
75
+
76
+ parser.on('--configure COMMAND', 'Generate configuration files') do |cmd|
77
+ CommandLineConfiguration.new(cmd).run
78
+ exit
79
+ end
80
+
81
+ parser.on("--tty", "Used internally by rspec when sending commands to other processes") do |o|
82
+ options[:tty] = true
83
+ end
84
+
85
+ parser.separator("\n **** Output formatting ****\n\n")
86
+
47
87
  parser.on('-f', '--format FORMATTER', 'Choose a formatter',
48
88
  ' [p]rogress (default - dots)',
49
89
  ' [d]ocumentation (group and example names)',
@@ -63,84 +103,79 @@ module RSpec::Core
63
103
  options[:formatters].last << o
64
104
  end
65
105
 
66
- parser.on_tail('-h', '--help', "You're looking at it.") do
67
- puts parser
68
- exit
69
- end
70
-
71
- parser.on('-I DIRECTORY', 'specify $LOAD_PATH directory (may be used more than once)') do |dir|
72
- options[:libs] ||= []
73
- options[:libs] << dir
74
- end
75
-
76
- parser.on('-l', '--line_number LINE', 'Specify the line number of an example to run. May be specified multiple times.') do |o|
77
- (options[:line_numbers] ||= []) << o
106
+ parser.on('-b', '--backtrace', 'Enable full backtrace') do |o|
107
+ options[:full_backtrace] = true
78
108
  end
79
109
 
80
- parser.on('-O', '--options PATH', 'Specify the path to an options file') do |path|
81
- options[:custom_options_file] = path
110
+ parser.on('-c', '--[no-]color', '--[no-]colour', 'Enable color in the output') do |o|
111
+ options[:color] = o
82
112
  end
83
113
 
84
114
  parser.on('-p', '--profile', 'Enable profiling of examples with output of the top 10 slowest examples') do |o|
85
115
  options[:profile_examples] = o
86
116
  end
87
117
 
88
- parser.on('-P', '--pattern PATTERN', 'Load files matching this pattern. Default is "spec/**/*_spec.rb"') do |o|
89
- options[:pattern] = o
90
- end
118
+ parser.separator <<-FILTERING
91
119
 
92
- parser.on('-r', '--require PATH', 'Require a file') do |path|
93
- options[:requires] ||= []
94
- options[:requires] << path
95
- end
120
+ **** Filtering and tags ****
96
121
 
97
- parser.on('-v', '--version', 'Show version') do
98
- puts RSpec::Core::Version::STRING
99
- exit
100
- end
122
+ In addition to the following options for selecting specific files, groups,
123
+ or examples, you can select a single example by appending the line number to
124
+ the filename:
101
125
 
102
- parser.on('-X', '--[no-]drb', 'Run examples via DRb') do |o|
103
- options[:drb] = o
104
- end
126
+ rspec path/to/a_spec.rb:37
105
127
 
106
- parser.on('--configure COMMAND', 'Generate configuration files') do |cmd|
107
- CommandLineConfiguration.new(cmd).run
108
- exit
109
- end
128
+ FILTERING
110
129
 
111
- parser.on('--drb-port [PORT]', 'Port to connect to on the DRb server') do |o|
112
- options[:drb_port] = o.to_i
130
+ parser.on('-P', '--pattern PATTERN', 'Load files matching pattern (default: "spec/**/*_spec.rb")') do |o|
131
+ options[:pattern] = o
113
132
  end
114
133
 
115
- parser.on('--fail-fast', 'Abort the run on first failure.') do |o|
116
- options[:fail_fast] = true
134
+ parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING") do |o|
135
+ options[:full_description] = Regexp.compile(Regexp.escape(o))
117
136
  end
118
137
 
119
- parser.on('--failure-exit-code CODE', 'Override the exit code used when there are failing specs.') do |o|
120
- options[:failure_exit_code] = o.to_i
138
+ parser.on('-l', '--line_number LINE', 'Specify line number of an example or group (may be specified multiple times)') do |o|
139
+ (options[:line_numbers] ||= []) << o
121
140
  end
122
141
 
123
- parser.on('-t', '--tag TAG[:VALUE]', 'Run examples with the specified tag',
124
- 'To exclude examples, add ~ before the tag (e.g. ~slow)',
125
- '(TAG is always converted to a symbol)') do |tag|
126
- filter_type = tag =~ /^~/ ? :exclusion_filter : :filter
142
+ parser.on('-t', '--tag TAG[:VALUE]',
143
+ 'Run examples with the specified tag, or exclude',
144
+ 'examples by ading ~ before the tag (e.g. ~slow)',
145
+ '(TAG is always converted to a symbol)') do |tag|
146
+ filter_type = tag =~ /^~/ ? :exclusion_filter : :inclusion_filter
127
147
 
128
148
  name,value = tag.gsub(/^(~@|~|@)/, '').split(':')
129
149
  name = name.to_sym
130
- value = true if value.nil?
131
150
 
132
151
  options[filter_type] ||= {}
133
- options[filter_type][name] = value
134
- end
135
-
136
- parser.on('--tty', 'Used internally by rspec when sending commands to other processes') do |o|
137
- options[:tty] = true
152
+ options[filter_type][name] = case value
153
+ when /^(true|false|nil)$/
154
+ eval(value)
155
+ when nil
156
+ true
157
+ else
158
+ value
159
+ end
138
160
  end
139
161
 
140
162
  parser.on('--default_path PATH', 'Set the default path where RSpec looks for examples.',
141
163
  'Can be a path to a file or a directory') do |path|
142
164
  options[:default_path] = path
143
165
  end
166
+
167
+ parser.separator("\n **** Utility ****\n\n")
168
+
169
+ parser.on('-v', '--version', 'Show version') do
170
+ puts RSpec::Core::Version::STRING
171
+ exit
172
+ end
173
+
174
+ parser.on_tail('-h', '--help', "You're looking at it.") do
175
+ puts parser
176
+ exit
177
+ end
178
+
144
179
  end
145
180
  end
146
181
  end