rspec-core 3.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.document +5 -0
  5. data/.yardopts +8 -0
  6. data/Changelog.md +2243 -0
  7. data/LICENSE.md +26 -0
  8. data/README.md +384 -0
  9. data/exe/rspec +4 -0
  10. data/lib/rspec/autorun.rb +3 -0
  11. data/lib/rspec/core.rb +185 -0
  12. data/lib/rspec/core/backtrace_formatter.rb +65 -0
  13. data/lib/rspec/core/bisect/coordinator.rb +62 -0
  14. data/lib/rspec/core/bisect/example_minimizer.rb +173 -0
  15. data/lib/rspec/core/bisect/fork_runner.rb +134 -0
  16. data/lib/rspec/core/bisect/server.rb +61 -0
  17. data/lib/rspec/core/bisect/shell_command.rb +126 -0
  18. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  19. data/lib/rspec/core/bisect/utilities.rb +58 -0
  20. data/lib/rspec/core/configuration.rb +2308 -0
  21. data/lib/rspec/core/configuration_options.rb +233 -0
  22. data/lib/rspec/core/drb.rb +113 -0
  23. data/lib/rspec/core/dsl.rb +98 -0
  24. data/lib/rspec/core/example.rb +656 -0
  25. data/lib/rspec/core/example_group.rb +889 -0
  26. data/lib/rspec/core/example_status_persister.rb +235 -0
  27. data/lib/rspec/core/filter_manager.rb +231 -0
  28. data/lib/rspec/core/flat_map.rb +20 -0
  29. data/lib/rspec/core/formatters.rb +269 -0
  30. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  31. data/lib/rspec/core/formatters/base_formatter.rb +70 -0
  32. data/lib/rspec/core/formatters/base_text_formatter.rb +75 -0
  33. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  34. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +157 -0
  35. data/lib/rspec/core/formatters/console_codes.rb +68 -0
  36. data/lib/rspec/core/formatters/deprecation_formatter.rb +223 -0
  37. data/lib/rspec/core/formatters/documentation_formatter.rb +70 -0
  38. data/lib/rspec/core/formatters/exception_presenter.rb +508 -0
  39. data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
  40. data/lib/rspec/core/formatters/helpers.rb +110 -0
  41. data/lib/rspec/core/formatters/html_formatter.rb +153 -0
  42. data/lib/rspec/core/formatters/html_printer.rb +414 -0
  43. data/lib/rspec/core/formatters/html_snippet_extractor.rb +120 -0
  44. data/lib/rspec/core/formatters/json_formatter.rb +102 -0
  45. data/lib/rspec/core/formatters/profile_formatter.rb +68 -0
  46. data/lib/rspec/core/formatters/progress_formatter.rb +29 -0
  47. data/lib/rspec/core/formatters/protocol.rb +182 -0
  48. data/lib/rspec/core/formatters/snippet_extractor.rb +134 -0
  49. data/lib/rspec/core/formatters/syntax_highlighter.rb +91 -0
  50. data/lib/rspec/core/hooks.rb +624 -0
  51. data/lib/rspec/core/invocations.rb +87 -0
  52. data/lib/rspec/core/memoized_helpers.rb +554 -0
  53. data/lib/rspec/core/metadata.rb +498 -0
  54. data/lib/rspec/core/metadata_filter.rb +255 -0
  55. data/lib/rspec/core/minitest_assertions_adapter.rb +31 -0
  56. data/lib/rspec/core/mocking_adapters/flexmock.rb +31 -0
  57. data/lib/rspec/core/mocking_adapters/mocha.rb +57 -0
  58. data/lib/rspec/core/mocking_adapters/null.rb +14 -0
  59. data/lib/rspec/core/mocking_adapters/rr.rb +31 -0
  60. data/lib/rspec/core/mocking_adapters/rspec.rb +32 -0
  61. data/lib/rspec/core/notifications.rb +521 -0
  62. data/lib/rspec/core/option_parser.rb +309 -0
  63. data/lib/rspec/core/ordering.rb +158 -0
  64. data/lib/rspec/core/output_wrapper.rb +29 -0
  65. data/lib/rspec/core/pending.rb +165 -0
  66. data/lib/rspec/core/profiler.rb +34 -0
  67. data/lib/rspec/core/project_initializer.rb +48 -0
  68. data/lib/rspec/core/project_initializer/.rspec +1 -0
  69. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +100 -0
  70. data/lib/rspec/core/rake_task.rb +168 -0
  71. data/lib/rspec/core/reporter.rb +257 -0
  72. data/lib/rspec/core/ruby_project.rb +53 -0
  73. data/lib/rspec/core/runner.rb +199 -0
  74. data/lib/rspec/core/sandbox.rb +37 -0
  75. data/lib/rspec/core/set.rb +54 -0
  76. data/lib/rspec/core/shared_context.rb +55 -0
  77. data/lib/rspec/core/shared_example_group.rb +269 -0
  78. data/lib/rspec/core/shell_escape.rb +49 -0
  79. data/lib/rspec/core/test_unit_assertions_adapter.rb +30 -0
  80. data/lib/rspec/core/version.rb +9 -0
  81. data/lib/rspec/core/warnings.rb +40 -0
  82. data/lib/rspec/core/world.rb +275 -0
  83. metadata +292 -0
  84. metadata.gz.sig +0 -0
@@ -0,0 +1,309 @@
1
+ # http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html
2
+ require 'optparse'
3
+
4
+ module RSpec::Core
5
+ # @private
6
+ class Parser
7
+ def self.parse(args, source=nil)
8
+ new(args).parse(source)
9
+ end
10
+
11
+ attr_reader :original_args
12
+
13
+ def initialize(original_args)
14
+ @original_args = original_args
15
+ end
16
+
17
+ def parse(source=nil)
18
+ return { :files_or_directories_to_run => [] } if original_args.empty?
19
+ args = original_args.dup
20
+
21
+ options = args.delete('--tty') ? { :tty => true } : {}
22
+ begin
23
+ parser(options).parse!(args)
24
+ rescue OptionParser::InvalidOption => e
25
+ failure = e.message
26
+ failure << " (defined in #{source})" if source
27
+ abort "#{failure}\n\nPlease use --help for a listing of valid options"
28
+ end
29
+
30
+ options[:files_or_directories_to_run] = args
31
+ options
32
+ end
33
+
34
+ private
35
+
36
+ # rubocop:disable MethodLength
37
+ # rubocop:disable Metrics/AbcSize
38
+ # rubocop:disable CyclomaticComplexity
39
+ # rubocop:disable PerceivedComplexity
40
+ def parser(options)
41
+ OptionParser.new do |parser|
42
+ parser.summary_width = 34
43
+
44
+ parser.banner = "Usage: rspec [options] [files or directories]\n\n"
45
+
46
+ parser.on('-I PATH', 'Specify PATH to add to $LOAD_PATH (may be used more than once).') do |dirs|
47
+ options[:libs] ||= []
48
+ options[:libs].concat(dirs.split(File::PATH_SEPARATOR))
49
+ end
50
+
51
+ parser.on('-r', '--require PATH', 'Require a file.') do |path|
52
+ options[:requires] ||= []
53
+ options[:requires] << path
54
+ end
55
+
56
+ parser.on('-O', '--options PATH', 'Specify the path to a custom options file.') do |path|
57
+ options[:custom_options_file] = path
58
+ end
59
+
60
+ parser.on('--order TYPE[:SEED]', 'Run examples by the specified order type.',
61
+ ' [defined] examples and groups are run in the order they are defined',
62
+ ' [rand] randomize the order of groups and examples',
63
+ ' [random] alias for rand',
64
+ ' [random:SEED] e.g. --order random:123') do |o|
65
+ options[:order] = o
66
+ end
67
+
68
+ parser.on('--seed SEED', Integer, 'Equivalent of --order rand:SEED.') do |seed|
69
+ options[:order] = "rand:#{seed}"
70
+ end
71
+
72
+ parser.on('--bisect[=verbose]', 'Repeatedly runs the suite in order to isolate the failures to the ',
73
+ ' smallest reproducible case.') do |argument|
74
+ options[:bisect] = argument || true
75
+ options[:runner] = RSpec::Core::Invocations::Bisect.new
76
+ end
77
+
78
+ parser.on('--[no-]fail-fast[=COUNT]', 'Abort the run after a certain number of failures (1 by default).') do |argument|
79
+ if argument == true
80
+ value = 1
81
+ elsif argument == false || argument == 0
82
+ value = false
83
+ else
84
+ begin
85
+ value = Integer(argument)
86
+ rescue ArgumentError
87
+ RSpec.warning "Expected an integer value for `--fail-fast`, got: #{argument.inspect}", :call_site => nil
88
+ end
89
+ end
90
+ set_fail_fast(options, value)
91
+ end
92
+
93
+ parser.on('--failure-exit-code CODE', Integer,
94
+ 'Override the exit code used when there are failing specs.') do |code|
95
+ options[:failure_exit_code] = code
96
+ end
97
+
98
+ parser.on('-X', '--[no-]drb', 'Run examples via DRb.') do |use_drb|
99
+ options[:drb] = use_drb
100
+ options[:runner] = RSpec::Core::Invocations::DRbWithFallback.new if use_drb
101
+ end
102
+
103
+ parser.on('--drb-port PORT', 'Port to connect to the DRb server.') do |o|
104
+ options[:drb_port] = o.to_i
105
+ end
106
+
107
+ parser.separator("\n **** Output ****\n\n")
108
+
109
+ parser.on('-f', '--format FORMATTER', 'Choose a formatter.',
110
+ ' [p]rogress (default - dots)',
111
+ ' [d]ocumentation (group and example names)',
112
+ ' [h]tml',
113
+ ' [j]son',
114
+ ' custom formatter class name') do |o|
115
+ options[:formatters] ||= []
116
+ options[:formatters] << [o]
117
+ end
118
+
119
+ parser.on('-o', '--out FILE',
120
+ 'Write output to a file instead of $stdout. This option applies',
121
+ ' to the previously specified --format, or the default format',
122
+ ' if no format is specified.'
123
+ ) do |o|
124
+ options[:formatters] ||= [['progress']]
125
+ options[:formatters].last << o
126
+ end
127
+
128
+ parser.on('--deprecation-out FILE', 'Write deprecation warnings to a file instead of $stderr.') do |file|
129
+ options[:deprecation_stream] = file
130
+ end
131
+
132
+ parser.on('-b', '--backtrace', 'Enable full backtrace.') do |_o|
133
+ options[:full_backtrace] = true
134
+ end
135
+
136
+ parser.on('-c', '--color', '--colour', '') do |_o|
137
+ # flag will be excluded from `--help` output because it is deprecated
138
+ options[:color] = true
139
+ options[:color_mode] = :automatic
140
+ end
141
+
142
+ parser.on('--force-color', '--force-colour', 'Force the output to be in color, even if the output is not a TTY') do |_o|
143
+ if options[:color_mode] == :off
144
+ abort "Please only use one of `--force-color` and `--no-color`"
145
+ end
146
+ options[:color_mode] = :on
147
+ end
148
+
149
+ parser.on('--no-color', '--no-colour', 'Force the output to not be in color, even if the output is a TTY') do |_o|
150
+ if options[:color_mode] == :on
151
+ abort "Please only use one of --force-color and --no-color"
152
+ end
153
+ options[:color_mode] = :off
154
+ end
155
+
156
+ parser.on('-p', '--[no-]profile [COUNT]',
157
+ 'Enable profiling of examples and list the slowest examples (default: 10).') do |argument|
158
+ options[:profile_examples] = if argument.nil?
159
+ true
160
+ elsif argument == false
161
+ false
162
+ else
163
+ begin
164
+ Integer(argument)
165
+ rescue ArgumentError
166
+ RSpec.warning "Non integer specified as profile count, separate " \
167
+ "your path from options with -- e.g. " \
168
+ "`rspec --profile -- #{argument}`",
169
+ :call_site => nil
170
+ true
171
+ end
172
+ end
173
+ end
174
+
175
+ parser.on('--dry-run', 'Print the formatter output of your suite without',
176
+ ' running any examples or hooks') do |_o|
177
+ options[:dry_run] = true
178
+ end
179
+
180
+ parser.on('-w', '--warnings', 'Enable ruby warnings') do
181
+ $VERBOSE = true
182
+ end
183
+
184
+ parser.separator <<-FILTERING
185
+
186
+ **** Filtering/tags ****
187
+
188
+ In addition to the following options for selecting specific files, groups, or
189
+ examples, you can select individual examples by appending the line number(s) to
190
+ the filename:
191
+
192
+ rspec path/to/a_spec.rb:37:87
193
+
194
+ You can also pass example ids enclosed in square brackets:
195
+
196
+ rspec path/to/a_spec.rb[1:5,1:6] # run the 5th and 6th examples/groups defined in the 1st group
197
+
198
+ FILTERING
199
+
200
+ parser.on('--only-failures', "Filter to just the examples that failed the last time they ran.") do
201
+ configure_only_failures(options)
202
+ end
203
+
204
+ parser.on("-n", "--next-failure", "Apply `--only-failures` and abort after one failure.",
205
+ " (Equivalent to `--only-failures --fail-fast --order defined`)") do
206
+ configure_only_failures(options)
207
+ set_fail_fast(options, 1)
208
+ options[:order] ||= 'defined'
209
+ end
210
+
211
+ parser.on('-P', '--pattern PATTERN', 'Load files matching pattern (default: "spec/**/*_spec.rb").') do |o|
212
+ if options[:pattern]
213
+ options[:pattern] += ',' + o
214
+ else
215
+ options[:pattern] = o
216
+ end
217
+ end
218
+
219
+ parser.on('--exclude-pattern PATTERN',
220
+ 'Load files except those matching pattern. Opposite effect of --pattern.') do |o|
221
+ options[:exclude_pattern] = o
222
+ end
223
+
224
+ parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING (may be",
225
+ " used more than once)") do |o|
226
+ (options[:full_description] ||= []) << Regexp.compile(Regexp.escape(o))
227
+ end
228
+
229
+ parser.on('-t', '--tag TAG[:VALUE]',
230
+ 'Run examples with the specified tag, or exclude examples',
231
+ 'by adding ~ before the tag.',
232
+ ' - e.g. ~slow',
233
+ ' - TAG is always converted to a symbol') do |tag|
234
+ filter_type = tag =~ /^~/ ? :exclusion_filter : :inclusion_filter
235
+
236
+ name, value = tag.gsub(/^(~@|~|@)/, '').split(':', 2)
237
+ name = name.to_sym
238
+
239
+ parsed_value = case value
240
+ when nil then true # The default value for tags is true
241
+ when 'true' then true
242
+ when 'false' then false
243
+ when 'nil' then nil
244
+ when /^:/ then value[1..-1].to_sym
245
+ when /^\d+$/ then Integer(value)
246
+ when /^\d+.\d+$/ then Float(value)
247
+ else
248
+ value
249
+ end
250
+
251
+ add_tag_filter(options, filter_type, name, parsed_value)
252
+ end
253
+
254
+ parser.on('--default-path PATH', 'Set the default path where RSpec looks for examples (can',
255
+ ' be a path to a file or a directory).') do |path|
256
+ options[:default_path] = path
257
+ end
258
+
259
+ parser.separator("\n **** Utility ****\n\n")
260
+
261
+ parser.on('--init', 'Initialize your project with RSpec.') do |_cmd|
262
+ options[:runner] = RSpec::Core::Invocations::InitializeProject.new
263
+ end
264
+
265
+ parser.on('-v', '--version', 'Display the version.') do
266
+ options[:runner] = RSpec::Core::Invocations::PrintVersion.new
267
+ end
268
+
269
+ # These options would otherwise be confusing to users, so we forcibly
270
+ # prevent them from executing.
271
+ #
272
+ # * --I is too similar to -I.
273
+ # * -d was a shorthand for --debugger, which is removed, but now would
274
+ # trigger --default-path.
275
+ invalid_options = %w[-d --I]
276
+
277
+ hidden_options = invalid_options + %w[-c]
278
+
279
+ parser.on_tail('-h', '--help', "You're looking at it.") do
280
+ options[:runner] = RSpec::Core::Invocations::PrintHelp.new(parser, hidden_options)
281
+ end
282
+
283
+ # This prevents usage of the invalid_options.
284
+ invalid_options.each do |option|
285
+ parser.on(option) do
286
+ raise OptionParser::InvalidOption.new
287
+ end
288
+ end
289
+ end
290
+ end
291
+ # rubocop:enable Metrics/AbcSize
292
+ # rubocop:enable MethodLength
293
+ # rubocop:enable CyclomaticComplexity
294
+ # rubocop:enable PerceivedComplexity
295
+
296
+ def add_tag_filter(options, filter_type, tag_name, value=true)
297
+ (options[filter_type] ||= {})[tag_name] = value
298
+ end
299
+
300
+ def set_fail_fast(options, value)
301
+ options[:fail_fast] = value
302
+ end
303
+
304
+ def configure_only_failures(options)
305
+ options[:only_failures] = true
306
+ add_tag_filter(options, :inclusion_filter, :last_run_status, 'failed')
307
+ end
308
+ end
309
+ end
@@ -0,0 +1,158 @@
1
+ module RSpec
2
+ module Core
3
+ # @private
4
+ module Ordering
5
+ # @private
6
+ # The default global ordering (defined order).
7
+ class Identity
8
+ def order(items)
9
+ items
10
+ end
11
+ end
12
+
13
+ # @private
14
+ # Orders items randomly.
15
+ class Random
16
+ def initialize(configuration)
17
+ @configuration = configuration
18
+ @used = false
19
+ end
20
+
21
+ def used?
22
+ @used
23
+ end
24
+
25
+ def order(items)
26
+ @used = true
27
+
28
+ seed = @configuration.seed.to_s
29
+ items.sort_by { |item| jenkins_hash_digest(seed + item.id) }
30
+ end
31
+
32
+ private
33
+
34
+ # http://en.wikipedia.org/wiki/Jenkins_hash_function
35
+ # Jenkins provides a good distribution and is simpler than MD5.
36
+ # It's a bit slower than MD5 (primarily because `Digest::MD5` is
37
+ # implemented in C) but has the advantage of not requiring us
38
+ # to load another part of stdlib, which we try to minimize.
39
+ def jenkins_hash_digest(string)
40
+ hash = 0
41
+
42
+ string.each_byte do |byte|
43
+ hash += byte
44
+ hash &= MAX_32_BIT
45
+ hash += ((hash << 10) & MAX_32_BIT)
46
+ hash &= MAX_32_BIT
47
+ hash ^= hash >> 6
48
+ end
49
+
50
+ hash += ((hash << 3) & MAX_32_BIT)
51
+ hash &= MAX_32_BIT
52
+ hash ^= hash >> 11
53
+ hash += ((hash << 15) & MAX_32_BIT)
54
+ hash &= MAX_32_BIT
55
+ hash
56
+ end
57
+
58
+ MAX_32_BIT = 4_294_967_295
59
+ end
60
+
61
+ # @private
62
+ # Orders items based on a custom block.
63
+ class Custom
64
+ def initialize(callable)
65
+ @callable = callable
66
+ end
67
+
68
+ def order(list)
69
+ @callable.call(list)
70
+ end
71
+ end
72
+
73
+ # @private
74
+ # Stores the different ordering strategies.
75
+ class Registry
76
+ def initialize(configuration)
77
+ @configuration = configuration
78
+ @strategies = {}
79
+
80
+ register(:random, Random.new(configuration))
81
+
82
+ identity = Identity.new
83
+ register(:defined, identity)
84
+
85
+ # The default global ordering is --defined.
86
+ register(:global, identity)
87
+ end
88
+
89
+ def fetch(name, &fallback)
90
+ @strategies.fetch(name, &fallback)
91
+ end
92
+
93
+ def register(sym, strategy)
94
+ @strategies[sym] = strategy
95
+ end
96
+
97
+ def used_random_seed?
98
+ @strategies[:random].used?
99
+ end
100
+ end
101
+
102
+ # @private
103
+ # Manages ordering configuration.
104
+ #
105
+ # @note This is not intended to be used externally. Use
106
+ # the APIs provided by `RSpec::Core::Configuration` instead.
107
+ class ConfigurationManager
108
+ attr_reader :seed, :ordering_registry
109
+
110
+ def initialize
111
+ @ordering_registry = Registry.new(self)
112
+ @seed = rand(0xFFFF)
113
+ @seed_forced = false
114
+ @order_forced = false
115
+ end
116
+
117
+ def seed_used?
118
+ ordering_registry.used_random_seed?
119
+ end
120
+
121
+ def seed=(seed)
122
+ return if @seed_forced
123
+ register_ordering(:global, ordering_registry.fetch(:random))
124
+ @seed = seed.to_i
125
+ end
126
+
127
+ def order=(type)
128
+ order, seed = type.to_s.split(':')
129
+ @seed = seed.to_i if seed
130
+
131
+ ordering_name = if order.include?('rand')
132
+ :random
133
+ elsif order == 'defined'
134
+ :defined
135
+ end
136
+
137
+ register_ordering(:global, ordering_registry.fetch(ordering_name)) if ordering_name
138
+ end
139
+
140
+ def force(hash)
141
+ if hash.key?(:seed)
142
+ self.seed = hash[:seed]
143
+ @seed_forced = true
144
+ @order_forced = true
145
+ elsif hash.key?(:order)
146
+ self.order = hash[:order]
147
+ @order_forced = true
148
+ end
149
+ end
150
+
151
+ def register_ordering(name, strategy=Custom.new(Proc.new { |l| yield l }))
152
+ return if @order_forced && name == :global
153
+ ordering_registry.register(name, strategy)
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end