rspec-core 2.99.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +1 -0
  4. data/Changelog.md +339 -1
  5. data/License.txt +1 -0
  6. data/README.md +19 -37
  7. data/exe/rspec +2 -23
  8. data/lib/rspec/core/backport_random.rb +336 -0
  9. data/lib/rspec/core/backtrace_formatter.rb +70 -0
  10. data/lib/rspec/core/configuration.rb +479 -577
  11. data/lib/rspec/core/configuration_options.rb +71 -54
  12. data/lib/rspec/core/drb.rb +111 -0
  13. data/lib/rspec/core/dsl.rb +86 -18
  14. data/lib/rspec/core/example.rb +267 -119
  15. data/lib/rspec/core/example_group.rb +381 -393
  16. data/lib/rspec/core/filter_manager.rb +133 -114
  17. data/lib/rspec/core/flat_map.rb +18 -0
  18. data/lib/rspec/core/formatters/base_formatter.rb +51 -125
  19. data/lib/rspec/core/formatters/base_text_formatter.rb +34 -286
  20. data/lib/rspec/core/formatters/console_codes.rb +24 -1
  21. data/lib/rspec/core/formatters/deprecation_formatter.rb +25 -26
  22. data/lib/rspec/core/formatters/documentation_formatter.rb +27 -25
  23. data/lib/rspec/core/formatters/helpers.rb +14 -36
  24. data/lib/rspec/core/formatters/html_formatter.rb +58 -65
  25. data/lib/rspec/core/formatters/html_printer.rb +12 -18
  26. data/lib/rspec/core/formatters/json_formatter.rb +54 -31
  27. data/lib/rspec/core/formatters/profile_formatter.rb +67 -0
  28. data/lib/rspec/core/formatters/progress_formatter.rb +11 -15
  29. data/lib/rspec/core/formatters/snippet_extractor.rb +22 -11
  30. data/lib/rspec/core/formatters.rb +90 -43
  31. data/lib/rspec/core/hooks.rb +325 -270
  32. data/lib/rspec/core/memoized_helpers.rb +45 -156
  33. data/lib/rspec/core/metadata.rb +284 -236
  34. data/lib/rspec/core/metadata_filter.rb +86 -0
  35. data/lib/rspec/core/mocking_adapters/flexmock.rb +29 -0
  36. data/lib/rspec/core/{mocking/with_mocha.rb → mocking_adapters/mocha.rb} +19 -16
  37. data/lib/rspec/core/mocking_adapters/null.rb +12 -0
  38. data/lib/rspec/core/mocking_adapters/rr.rb +29 -0
  39. data/lib/rspec/core/mocking_adapters/rspec.rb +30 -0
  40. data/lib/rspec/core/notifications.rb +511 -0
  41. data/lib/rspec/core/option_parser.rb +49 -74
  42. data/lib/rspec/core/ordering.rb +156 -0
  43. data/lib/rspec/core/pending.rb +94 -96
  44. data/lib/rspec/core/project_initializer/.rspec +3 -0
  45. data/lib/rspec/core/project_initializer/spec/spec_helper.rb +78 -0
  46. data/lib/rspec/core/project_initializer.rb +24 -64
  47. data/lib/rspec/core/rake_task.rb +44 -130
  48. data/lib/rspec/core/reporter.rb +76 -59
  49. data/lib/rspec/core/ruby_project.rb +2 -1
  50. data/lib/rspec/core/runner.rb +117 -52
  51. data/lib/rspec/core/shared_context.rb +10 -10
  52. data/lib/rspec/core/shared_example_group.rb +108 -121
  53. data/lib/rspec/core/version.rb +3 -1
  54. data/lib/rspec/core/warnings.rb +40 -0
  55. data/lib/rspec/core/world.rb +66 -10
  56. data/lib/rspec/core.rb +64 -104
  57. data.tar.gz.sig +3 -0
  58. metadata +75 -322
  59. metadata.gz.sig +1 -0
  60. data/exe/autospec +0 -13
  61. data/features/Autotest.md +0 -38
  62. data/features/README.md +0 -17
  63. data/features/Upgrade.md +0 -364
  64. data/features/command_line/README.md +0 -28
  65. data/features/command_line/example_name_option.feature +0 -97
  66. data/features/command_line/exit_status.feature +0 -82
  67. data/features/command_line/format_option.feature +0 -75
  68. data/features/command_line/init.feature +0 -18
  69. data/features/command_line/line_number_appended_to_path.feature +0 -140
  70. data/features/command_line/line_number_option.feature +0 -53
  71. data/features/command_line/order.feature +0 -26
  72. data/features/command_line/pattern_option.feature +0 -49
  73. data/features/command_line/rake_task.feature +0 -122
  74. data/features/command_line/require_option.feature +0 -43
  75. data/features/command_line/ruby.feature +0 -22
  76. data/features/command_line/tag.feature +0 -98
  77. data/features/command_line/warnings_option.feature +0 -29
  78. data/features/configuration/alias_example_to.feature +0 -48
  79. data/features/configuration/backtrace_clean_patterns.feature +0 -102
  80. data/features/configuration/custom_settings.feature +0 -84
  81. data/features/configuration/default_path.feature +0 -38
  82. data/features/configuration/deprecation_stream.feature +0 -58
  83. data/features/configuration/fail_fast.feature +0 -77
  84. data/features/configuration/failure_exit_code.feature +0 -36
  85. data/features/configuration/order_and_seed.feature +0 -3
  86. data/features/configuration/output_stream.feature +0 -24
  87. data/features/configuration/pattern.feature +0 -38
  88. data/features/configuration/profile.feature +0 -220
  89. data/features/configuration/read_options_from_file.feature +0 -90
  90. data/features/configuration/run_all_when_everything_filtered.feature +0 -76
  91. data/features/configuration/show_failures_in_pending_blocks.feature +0 -61
  92. data/features/configuration/treat_symbols_as_metadata_keys_with_true_values.feature +0 -52
  93. data/features/example_groups/basic_structure.feature +0 -55
  94. data/features/example_groups/shared_context.feature +0 -74
  95. data/features/example_groups/shared_examples.feature +0 -294
  96. data/features/expectation_framework_integration/configure_expectation_framework.feature +0 -197
  97. data/features/filtering/exclusion_filters.feature +0 -138
  98. data/features/filtering/if_and_unless.feature +0 -168
  99. data/features/filtering/inclusion_filters.feature +0 -105
  100. data/features/formatters/configurable_colors.feature +0 -31
  101. data/features/formatters/custom_formatter.feature +0 -36
  102. data/features/formatters/json_formatter.feature +0 -30
  103. data/features/formatters/text_formatter.feature +0 -46
  104. data/features/helper_methods/arbitrary_methods.feature +0 -40
  105. data/features/helper_methods/let.feature +0 -50
  106. data/features/helper_methods/modules.feature +0 -149
  107. data/features/hooks/around_hooks.feature +0 -343
  108. data/features/hooks/before_and_after_hooks.feature +0 -427
  109. data/features/hooks/filtering.feature +0 -234
  110. data/features/metadata/current_example.feature +0 -56
  111. data/features/metadata/described_class.feature +0 -17
  112. data/features/metadata/user_defined.feature +0 -113
  113. data/features/mock_framework_integration/use_any_framework.feature +0 -106
  114. data/features/mock_framework_integration/use_flexmock.feature +0 -96
  115. data/features/mock_framework_integration/use_mocha.feature +0 -97
  116. data/features/mock_framework_integration/use_rr.feature +0 -98
  117. data/features/mock_framework_integration/use_rspec.feature +0 -97
  118. data/features/pending/pending_examples.feature +0 -229
  119. data/features/spec_files/arbitrary_file_suffix.feature +0 -13
  120. data/features/step_definitions/additional_cli_steps.rb +0 -49
  121. data/features/subject/attribute_of_subject.feature +0 -124
  122. data/features/subject/explicit_subject.feature +0 -101
  123. data/features/subject/implicit_subject.feature +0 -63
  124. data/features/subject/one_liner_syntax.feature +0 -71
  125. data/features/support/env.rb +0 -14
  126. data/features/support/rubinius.rb +0 -6
  127. data/lib/autotest/discover.rb +0 -10
  128. data/lib/autotest/rspec2.rb +0 -77
  129. data/lib/rspec/core/backtrace_cleaner.rb +0 -46
  130. data/lib/rspec/core/backward_compatibility.rb +0 -55
  131. data/lib/rspec/core/caller_filter.rb +0 -60
  132. data/lib/rspec/core/command_line.rb +0 -47
  133. data/lib/rspec/core/deprecated_mutable_array_proxy.rb +0 -32
  134. data/lib/rspec/core/deprecation.rb +0 -26
  135. data/lib/rspec/core/drb_command_line.rb +0 -26
  136. data/lib/rspec/core/drb_options.rb +0 -87
  137. data/lib/rspec/core/extensions/instance_eval_with_args.rb +0 -44
  138. data/lib/rspec/core/extensions/kernel.rb +0 -9
  139. data/lib/rspec/core/extensions/module_eval_with_args.rb +0 -38
  140. data/lib/rspec/core/extensions/ordered.rb +0 -27
  141. data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -34
  142. data/lib/rspec/core/metadata_hash_builder.rb +0 -97
  143. data/lib/rspec/core/mocking/with_absolutely_nothing.rb +0 -11
  144. data/lib/rspec/core/mocking/with_flexmock.rb +0 -27
  145. data/lib/rspec/core/mocking/with_rr.rb +0 -27
  146. data/lib/rspec/core/mocking/with_rspec.rb +0 -27
  147. data/lib/rspec/core/shared_example_group/collection.rb +0 -45
  148. data/spec/autotest/discover_spec.rb +0 -49
  149. data/spec/autotest/failed_results_re_spec.rb +0 -45
  150. data/spec/autotest/rspec_spec.rb +0 -133
  151. data/spec/command_line/order_spec.rb +0 -204
  152. data/spec/rspec/core/backtrace_cleaner_spec.rb +0 -68
  153. data/spec/rspec/core/caller_filter_spec.rb +0 -58
  154. data/spec/rspec/core/command_line_spec.rb +0 -127
  155. data/spec/rspec/core/command_line_spec_output.txt +0 -0
  156. data/spec/rspec/core/configuration_options_spec.rb +0 -417
  157. data/spec/rspec/core/configuration_spec.rb +0 -2072
  158. data/spec/rspec/core/deprecation_spec.rb +0 -27
  159. data/spec/rspec/core/deprecations_spec.rb +0 -59
  160. data/spec/rspec/core/drb_command_line_spec.rb +0 -102
  161. data/spec/rspec/core/drb_options_spec.rb +0 -193
  162. data/spec/rspec/core/dsl_spec.rb +0 -25
  163. data/spec/rspec/core/example_group_spec.rb +0 -1337
  164. data/spec/rspec/core/example_spec.rb +0 -502
  165. data/spec/rspec/core/filter_manager_spec.rb +0 -246
  166. data/spec/rspec/core/formatters/base_formatter_spec.rb +0 -108
  167. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +0 -524
  168. data/spec/rspec/core/formatters/console_codes_spec.rb +0 -50
  169. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +0 -263
  170. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +0 -89
  171. data/spec/rspec/core/formatters/helpers_spec.rb +0 -104
  172. data/spec/rspec/core/formatters/html_formatted.html +0 -397
  173. data/spec/rspec/core/formatters/html_formatter_spec.rb +0 -131
  174. data/spec/rspec/core/formatters/json_formatter_spec.rb +0 -115
  175. data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -30
  176. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +0 -26
  177. data/spec/rspec/core/formatters/text_mate_formatted.html +0 -397
  178. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +0 -107
  179. data/spec/rspec/core/hooks_filtering_spec.rb +0 -227
  180. data/spec/rspec/core/hooks_spec.rb +0 -269
  181. data/spec/rspec/core/kernel_extensions_spec.rb +0 -9
  182. data/spec/rspec/core/memoized_helpers_spec.rb +0 -776
  183. data/spec/rspec/core/metadata_spec.rb +0 -514
  184. data/spec/rspec/core/option_parser_spec.rb +0 -297
  185. data/spec/rspec/core/pending_example_spec.rb +0 -260
  186. data/spec/rspec/core/pending_spec.rb +0 -27
  187. data/spec/rspec/core/project_initializer_spec.rb +0 -130
  188. data/spec/rspec/core/rake_task_spec.rb +0 -202
  189. data/spec/rspec/core/reporter_spec.rb +0 -167
  190. data/spec/rspec/core/resources/a_bar.rb +0 -0
  191. data/spec/rspec/core/resources/a_foo.rb +0 -0
  192. data/spec/rspec/core/resources/a_spec.rb +0 -1
  193. data/spec/rspec/core/resources/custom_example_group_runner.rb +0 -14
  194. data/spec/rspec/core/resources/formatter_specs.rb +0 -60
  195. data/spec/rspec/core/resources/utf8_encoded.rb +0 -8
  196. data/spec/rspec/core/rspec_matchers_spec.rb +0 -45
  197. data/spec/rspec/core/ruby_project_spec.rb +0 -26
  198. data/spec/rspec/core/runner_spec.rb +0 -82
  199. data/spec/rspec/core/shared_context_spec.rb +0 -114
  200. data/spec/rspec/core/shared_example_group/collection_spec.rb +0 -70
  201. data/spec/rspec/core/shared_example_group_spec.rb +0 -138
  202. data/spec/rspec/core/world_spec.rb +0 -142
  203. data/spec/rspec/core_spec.rb +0 -108
  204. data/spec/spec_helper.rb +0 -135
  205. data/spec/support/config_options_helper.rb +0 -15
  206. data/spec/support/helper_methods.rb +0 -55
  207. data/spec/support/in_sub_process.rb +0 -37
  208. data/spec/support/isolate_load_path_mutation.rb +0 -6
  209. data/spec/support/isolated_directory.rb +0 -10
  210. data/spec/support/isolated_home_directory.rb +0 -16
  211. data/spec/support/matchers.rb +0 -65
  212. data/spec/support/mathn_integration_support.rb +0 -12
  213. data/spec/support/sandboxed_mock_space.rb +0 -116
  214. data/spec/support/shared_example_groups.rb +0 -42
  215. data/spec/support/silence_dsl_deprecations.rb +0 -32
  216. data/spec/support/spec_files.rb +0 -44
@@ -2,21 +2,15 @@
2
2
  require 'optparse'
3
3
 
4
4
  module RSpec::Core
5
+ # @private
5
6
  class Parser
6
- def self.parse!(args)
7
- new.parse!(args)
7
+ def self.parse(args)
8
+ new.parse(args)
8
9
  end
9
10
 
10
- class << self
11
- alias_method :parse, :parse!
12
- end
13
-
14
- def parse!(args)
11
+ def parse(args)
15
12
  return {} if args.empty?
16
13
 
17
- pre_parse(args)
18
- convert_deprecated_args(args)
19
-
20
14
  options = args.delete('--tty') ? {:tty => true} : {}
21
15
  begin
22
16
  parser(options).parse!(args)
@@ -27,25 +21,6 @@ module RSpec::Core
27
21
  options
28
22
  end
29
23
 
30
- def convert_deprecated_args(args)
31
- args.map! { |arg|
32
- case arg
33
- when "--formatter"
34
- RSpec.deprecate("The `--formatter` option", :replacement => "-f or --format", :call_site => nil)
35
- "--format"
36
- when "--default_path"
37
- RSpec.deprecate("The `--default_path` option", :replacement => "--default-path", :call_site => nil)
38
- "--default-path"
39
- when "--line_number"
40
- "--line-number"
41
- else
42
- arg
43
- end
44
- }
45
- end
46
-
47
- alias_method :parse, :parse!
48
-
49
24
  def parser(options)
50
25
  OptionParser.new do |parser|
51
26
  parser.banner = "Usage: rspec [options] [files or directories]\n\n"
@@ -65,35 +40,34 @@ module RSpec::Core
65
40
  end
66
41
 
67
42
  parser.on('--order TYPE[:SEED]', 'Run examples by the specified order type.',
68
- ' [defined] groups and examples are run in the order they are defined',
69
- ' [default] deprecated alias for defined',
70
- ' [rand] randomize the order of files, groups and examples',
43
+ ' [defined] examples and groups are run in the order they are defined',
44
+ ' [rand] randomize the order of groups and examples',
71
45
  ' [random] alias for rand',
72
46
  ' [random:SEED] e.g. --order random:123') do |o|
73
- options[:order] = if o == 'default'
74
- RSpec.deprecate("RSpec's `--order default` CLI option", :replacement => "`--order defined`", :call_site => nil)
75
- 'defined'
76
- else
77
- o
78
- end
47
+ options[:order] = o
79
48
  end
80
49
 
81
50
  parser.on('--seed SEED', Integer, 'Equivalent of --order rand:SEED.') do |seed|
82
51
  options[:order] = "rand:#{seed}"
83
52
  end
84
53
 
85
- parser.on('-d', '--debugger', 'Enable debugging.') do |o|
86
- options[:debug] = :cli
87
- end
88
-
89
54
  parser.on('--fail-fast', 'Abort the run on first failure.') do |o|
90
55
  options[:fail_fast] = true
91
56
  end
92
57
 
58
+ parser.on('--no-fail-fast', 'Do not abort the run on first failure.') do |o|
59
+ options[:fail_fast] = false
60
+ end
61
+
93
62
  parser.on('--failure-exit-code CODE', Integer, 'Override the exit code used when there are failing specs.') do |code|
94
63
  options[:failure_exit_code] = code
95
64
  end
96
65
 
66
+ parser.on('--dry-run', 'Print the formatter output of your suite without',
67
+ ' running any examples or hooks') do |o|
68
+ options[:dry_run] = true
69
+ end
70
+
97
71
  parser.on('-X', '--[no-]drb', 'Run examples via DRb.') do |o|
98
72
  options[:drb] = o
99
73
  end
@@ -103,12 +77,8 @@ module RSpec::Core
103
77
  end
104
78
 
105
79
  parser.on('--init', 'Initialize your project with RSpec.') do |cmd|
106
- ProjectInitializer.new(cmd).run
107
- exit
108
- end
109
-
110
- parser.on('--configure', 'Deprecated. Use --init instead.') do |cmd|
111
- warn "--configure is deprecated with no effect. Use --init instead."
80
+ RSpec::Support.require_rspec_core "project_initializer"
81
+ ProjectInitializer.new.run
112
82
  exit
113
83
  end
114
84
 
@@ -118,7 +88,6 @@ module RSpec::Core
118
88
  ' [p]rogress (default - dots)',
119
89
  ' [d]ocumentation (group and example names)',
120
90
  ' [h]tml',
121
- ' [t]extmate',
122
91
  ' [j]son',
123
92
  ' custom formatter class name') do |o|
124
93
  options[:formatters] ||= []
@@ -134,9 +103,8 @@ module RSpec::Core
134
103
  options[:formatters].last << o
135
104
  end
136
105
 
137
- parser.on('--deprecation-out FILE', 'Write deprecation warnings to a file instead of $stdout.') do |file|
138
- # Handled in `pre_parse` so we can set the deprecation stream as early as
139
- # possible in case any other options cause deprecations to be issued.
106
+ parser.on('--deprecation-out FILE', 'Write deprecation warnings to a file instead of $stderr.') do |file|
107
+ options[:deprecation_stream] = file
140
108
  end
141
109
 
142
110
  parser.on('-b', '--backtrace', 'Enable full backtrace.') do |o|
@@ -156,16 +124,17 @@ module RSpec::Core
156
124
  begin
157
125
  Integer(argument)
158
126
  rescue ArgumentError
159
- Kernel.warn "Non integer specified as profile count, seperate " +
127
+ RSpec.warning "Non integer specified as profile count, seperate " +
160
128
  "your path from options with -- e.g. " +
161
- "`rspec --profile -- #{argument}`"
129
+ "`rspec --profile -- #{argument}`",
130
+ :call_site => nil
162
131
  true
163
132
  end
164
133
  end
165
134
  end
166
135
 
167
136
  parser.on('-w', '--warnings', 'Enable ruby warnings') do
168
- options[:warnings] = true
137
+ $VERBOSE = true
169
138
  end
170
139
 
171
140
  parser.separator <<-FILTERING
@@ -189,15 +158,6 @@ FILTERING
189
158
  (options[:full_description] ||= []) << Regexp.compile(Regexp.escape(o))
190
159
  end
191
160
 
192
- parser.on('-l', '--line-number LINE', 'Specify line number of an example or group (may be',
193
- ' used more than once).') do |o|
194
- Metadata.line_number_filter_deprecation_issued = true
195
- RSpec.deprecate("The `--line-number`/`-l` CLI option",
196
- :replacement => "the `path/to/file.rb:num` form",
197
- :call_site => nil)
198
- (options[:line_numbers] ||= []) << o
199
- end
200
-
201
161
  parser.on('-t', '--tag TAG[:VALUE]',
202
162
  'Run examples with the specified tag, or exclude examples',
203
163
  'by adding ~ before the tag.',
@@ -205,11 +165,21 @@ FILTERING
205
165
  ' - TAG is always converted to a symbol') do |tag|
206
166
  filter_type = tag =~ /^~/ ? :exclusion_filter : :inclusion_filter
207
167
 
208
- name,value = tag.gsub(/^(~@|~|@)/, '').split(':')
168
+ name,value = tag.gsub(/^(~@|~|@)/, '').split(':',2)
209
169
  name = name.to_sym
210
170
 
211
171
  options[filter_type] ||= {}
212
- options[filter_type][name] = value.nil? ? true : eval(value) rescue value
172
+ options[filter_type][name] = case value
173
+ when nil then true # The default value for tags is true
174
+ when 'true' then true
175
+ when 'false' then false
176
+ when 'nil' then nil
177
+ when /^:/ then value[1..-1].to_sym
178
+ when /^\d+$/ then Integer(value)
179
+ when /^\d+.\d+$/ then Float(value)
180
+ else
181
+ value
182
+ end
213
183
  end
214
184
 
215
185
  parser.on('--default-path PATH', 'Set the default path where RSpec looks for examples (can',
@@ -224,19 +194,24 @@ FILTERING
224
194
  exit
225
195
  end
226
196
 
197
+ # these options would otherwise be confusing to users, so we forcibly prevent them from executing
198
+ # --I is too similar to -I
199
+ # -d was a shorthand for --debugger, which is removed, but now would trigger --default-path
200
+ invalid_options = %w[-d --I]
201
+
227
202
  parser.on_tail('-h', '--help', "You're looking at it.") do
228
- puts parser
203
+ # removing the blank invalid options from the output
204
+ puts parser.to_s.gsub(/^\s+(#{invalid_options.join('|')})\s*$\n/,'')
229
205
  exit
230
206
  end
231
207
 
232
- end
233
- end
234
-
235
- def pre_parse(args)
236
- args.each_cons(2) do |arg, value|
237
- if arg == "--deprecation-out"
238
- RSpec.configuration.deprecation_stream = value
208
+ # this prevents usage of the invalid_options
209
+ invalid_options.each do |option|
210
+ parser.on(option) do
211
+ raise OptionParser::InvalidOption.new
212
+ end
239
213
  end
214
+
240
215
  end
241
216
  end
242
217
  end
@@ -0,0 +1,156 @@
1
+ module RSpec
2
+ module Core
3
+ if defined?(::Random)
4
+ # @private
5
+ RandomNumberGenerator = ::Random
6
+ else
7
+ RSpec::Support.require_rspec_core "backport_random"
8
+ # @private
9
+ RandomNumberGenerator = RSpec::Core::Backports::Random
10
+ end
11
+
12
+ # @private
13
+ module Ordering
14
+ # @private
15
+ # The default global ordering (defined order).
16
+ class Identity
17
+ def order(items)
18
+ items
19
+ end
20
+ end
21
+
22
+ # @private
23
+ # Orders items randomly.
24
+ class Random
25
+ def initialize(configuration)
26
+ @configuration = configuration
27
+ @used = false
28
+ end
29
+
30
+ def used?
31
+ @used
32
+ end
33
+
34
+ def order(items)
35
+ @used = true
36
+ rng = RandomNumberGenerator.new(@configuration.seed)
37
+ shuffle items, rng
38
+ end
39
+
40
+ if RUBY_VERSION > '1.9.3'
41
+ def shuffle(list, rng)
42
+ list.shuffle(:random => rng)
43
+ end
44
+ else
45
+ def shuffle(list, rng)
46
+ shuffled = list.dup
47
+ shuffled.size.times do |i|
48
+ j = i + rng.rand(shuffled.size - i)
49
+ next if i == j
50
+ shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
51
+ end
52
+
53
+ shuffled
54
+ end
55
+ end
56
+ end
57
+
58
+ # @private
59
+ # Orders items based on a custom block.
60
+ class Custom
61
+ def initialize(callable)
62
+ @callable = callable
63
+ end
64
+
65
+ def order(list)
66
+ @callable.call(list)
67
+ end
68
+ end
69
+
70
+ # @private
71
+ # Stores the different ordering strategies.
72
+ class Registry
73
+ def initialize(configuration)
74
+ @configuration = configuration
75
+ @strategies = {}
76
+
77
+ register(:random, Random.new(configuration))
78
+
79
+ identity = Identity.new
80
+ register(:defined, identity)
81
+
82
+ # The default global ordering is --defined.
83
+ register(:global, identity)
84
+ end
85
+
86
+ def fetch(name, &fallback)
87
+ @strategies.fetch(name, &fallback)
88
+ end
89
+
90
+ def register(sym, strategy)
91
+ @strategies[sym] = strategy
92
+ end
93
+
94
+ def used_random_seed?
95
+ @strategies[:random].used?
96
+ end
97
+ end
98
+
99
+ # @private
100
+ # Manages ordering configuration.
101
+ #
102
+ # @note This is not intended to be used externally. Use
103
+ # the APIs provided by `RSpec::Core::Configuration` instead.
104
+ class ConfigurationManager
105
+ attr_reader :seed, :ordering_registry
106
+
107
+ def initialize
108
+ @ordering_registry = Registry.new(self)
109
+ @seed = rand(0xFFFF)
110
+ @seed_forced = false
111
+ @order_forced = false
112
+ end
113
+
114
+ def seed_used?
115
+ ordering_registry.used_random_seed?
116
+ end
117
+
118
+ def seed=(seed)
119
+ return if @seed_forced
120
+ register_ordering(:global, ordering_registry.fetch(:random))
121
+ @seed = seed.to_i
122
+ end
123
+
124
+ def order=(type)
125
+ order, seed = type.to_s.split(':')
126
+ @seed = seed = seed.to_i if seed
127
+
128
+ ordering_name = if order.include?('rand')
129
+ :random
130
+ elsif order == 'defined'
131
+ :defined
132
+ end
133
+
134
+ register_ordering(:global, ordering_registry.fetch(ordering_name)) if ordering_name
135
+ end
136
+
137
+ def force(hash)
138
+ if hash.has_key?(:seed)
139
+ self.seed = hash[:seed]
140
+ @seed_forced = true
141
+ @order_forced = true
142
+ elsif hash.has_key?(:order)
143
+ self.order = hash[:order]
144
+ @order_forced = true
145
+ end
146
+ end
147
+
148
+ def register_ordering(name, strategy = Custom.new(Proc.new { |l| yield l }))
149
+ return if @order_forced && name == :global
150
+ ordering_registry.register(name, strategy)
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
@@ -1,16 +1,18 @@
1
1
  module RSpec
2
2
  module Core
3
+ # Provides methods to mark examples as pending. These methods are available to be
4
+ # called from within any example or hook.
3
5
  module Pending
6
+ # Raised in the middle of an example to indicate that it should be marked as skipped.
4
7
  class SkipDeclaredInExample < StandardError
5
8
  attr_reader :argument
6
9
 
7
10
  def initialize(argument)
8
- super(argument.to_s)
9
11
  @argument = argument
10
12
  end
11
13
  end
12
14
 
13
- # If Test::Unit is loaed, we'll use its error as baseclass, so that Test::Unit
15
+ # If Test::Unit is loaded, we'll use its error as baseclass, so that Test::Unit
14
16
  # will report unmet RSpec expectations as failures rather than errors.
15
17
  begin
16
18
  class PendingExampleFixedError < Test::Unit::AssertionFailedError; end
@@ -18,52 +20,37 @@ module RSpec
18
20
  class PendingExampleFixedError < StandardError; end
19
21
  end
20
22
 
23
+ # @private
21
24
  NO_REASON_GIVEN = 'No reason given'
25
+
26
+ # @private
22
27
  NOT_YET_IMPLEMENTED = 'Not yet implemented'
23
28
 
24
29
  # @overload pending()
25
30
  # @overload pending(message)
26
- # @overload pending(message, &block)
27
31
  #
28
- # Stops execution of an example, and reports it as pending. Takes an
29
- # optional message and block.
32
+ # Marks an example as pending. The rest of the example will still be
33
+ # executed, and if it passes the example will fail to indicate that the
34
+ # pending can be removed.
30
35
  #
31
- # @param [String] message optional message to add to the summary report.
32
- # @param [Block] block optional block. If it fails, the example is
33
- # reported as pending. If it executes cleanly the example fails.
36
+ # @param message [String] optional message to add to the summary report.
34
37
  #
35
38
  # @example
36
- #
37
39
  # describe "an example" do
38
40
  # # reported as "Pending: no reason given"
39
41
  # it "is pending with no message" do
40
42
  # pending
41
- # this_does_not_get_executed
43
+ # raise "broken"
42
44
  # end
43
45
  #
44
46
  # # reported as "Pending: something else getting finished"
45
47
  # it "is pending with a custom message" do
46
48
  # pending("something else getting finished")
47
- # this_does_not_get_executed
48
- # end
49
- #
50
- # # reported as "Pending: something else getting finished"
51
- # it "is pending with a failing block" do
52
- # pending("something else getting finished") do
53
- # raise "this is the failure"
54
- # end
55
- # end
56
- #
57
- # # reported as failure, saying we expected the block to fail but
58
- # # it passed.
59
- # it "is pending with a passing block" do
60
- # pending("something else getting finished") do
61
- # true.should be(true)
62
- # end
49
+ # raise "broken"
63
50
  # end
64
51
  # end
65
52
  #
66
- # @note `before(:each)` hooks are eval'd when you use the `pending`
53
+ # @note `before(:example)` hooks are eval'd when you use the `pending`
67
54
  # method within an example. If you want to declare an example `pending`
68
55
  # and bypass the `before` hooks as well, you can pass `:pending => true`
69
56
  # to the `it` method:
@@ -78,90 +65,101 @@ module RSpec
78
65
  # it "does something", :pending => "something else getting finished" do
79
66
  # # ...
80
67
  # end
81
- def pending(*args, &block)
82
- RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
83
- |The semantics of `RSpec::Core::Pending#pending` are changing in
84
- |RSpec 3. In RSpec 2.x, it caused the example to be skipped. In
85
- |RSpec 3, the rest of the example will still be run but is expected
86
- |to fail, and will be marked as a failure (rather than as pending)
87
- |if the example passes.
88
- |
89
- |Any passed block will no longer be executed. This feature is being
90
- |removed since it was semantically inconsistent, and the behaviour it
91
- |offered is being made available with the other ways of marking an
92
- |example pending.
93
- |
94
- |To keep the same skip semantics, change `pending` to `skip`.
95
- |Otherwise, if you want the new RSpec 3 behavior, you can safely
96
- |ignore this warning and continue to upgrade to RSpec 3 without
97
- |addressing it.
98
- |
99
- |Called from #{CallerFilter.first_non_rspec_line}.
100
- |
101
- EOS
68
+ def pending(message=nil)
69
+ current_example = RSpec.current_example
102
70
 
103
- pending_no_warning(*args, &block)
71
+ if block_given?
72
+ raise ArgumentError, <<-EOS.gsub(/^\s+\|/, '')
73
+ |The semantics of `RSpec::Core::Pending#pending` have changed in
74
+ |RSpec 3. In RSpec 2.x, it caused the example to be skipped. In
75
+ |RSpec 3, the rest of the example is still run but is expected to
76
+ |fail, and will be marked as a failure (rather than as pending) if
77
+ |the example passes.
78
+ |
79
+ |Passing a block within an example is now deprecated. Marking the
80
+ |example as pending provides the same behavior in RSpec 3 which was
81
+ |provided only by the block in RSpec 2.x.
82
+ |
83
+ |Move the code in the block provided to `pending` into the rest of
84
+ |the example body.
85
+ |
86
+ |Called from #{CallerFilter.first_non_rspec_line}.
87
+ |
88
+ EOS
89
+ elsif current_example
90
+ Pending.mark_pending! current_example, message
91
+ else
92
+ raise "`pending` may not be used outside of examples, such as in " +
93
+ "before(:context). Maybe you want `skip`?"
94
+ end
104
95
  end
105
96
 
106
- def pending_no_warning(*args)
107
- return self.class.before(:each) { pending(*args) } unless RSpec.current_example
108
-
109
- options = args.last.is_a?(Hash) ? args.pop : {}
110
- message = args.first || NO_REASON_GIVEN
97
+ # @overload skip()
98
+ # @overload skip(message)
99
+ #
100
+ # Marks an example as pending and skips execution.
101
+ #
102
+ # @param message [String] optional message to add to the summary report.
103
+ #
104
+ # @example
105
+ # describe "an example" do
106
+ # # reported as "Pending: no reason given"
107
+ # it "is skipped with no message" do
108
+ # skip
109
+ # end
110
+ #
111
+ # # reported as "Pending: something else getting finished"
112
+ # it "is skipped with a custom message" do
113
+ # skip "something else getting finished"
114
+ # end
115
+ # end
116
+ def skip(message=nil)
117
+ current_example = RSpec.current_example
111
118
 
112
- if options[:unless] || (options.has_key?(:if) && !options[:if])
113
- return block_given? ? yield : nil
119
+ if current_example
120
+ Pending.mark_skipped! current_example, message
114
121
  end
115
122
 
116
- RSpec.current_example.metadata[:pending] = true
117
- RSpec.current_example.metadata[:execution_result][:pending_message] = message
118
- RSpec.current_example.execution_result[:pending_fixed] = false
119
- if block_given?
120
- begin
121
- result = begin
122
- yield
123
- RSpec.current_example.example_group_instance.instance_eval { verify_mocks_for_rspec }
124
- end
125
- RSpec.current_example.metadata[:pending] = false
126
- rescue Exception => e
127
- RSpec.current_example.execution_result[:exception] = e
128
- ensure
129
- teardown_mocks_for_rspec
130
- end
131
- if result
132
- RSpec.current_example.execution_result[:pending_fixed] = true
133
- raise PendingExampleFixedError.new
134
- end
135
- end
136
123
  raise SkipDeclaredInExample.new(message)
137
124
  end
138
125
 
139
- # Backport from RSpec 3 to aid in upgrading.
126
+ # @private
127
+ #
128
+ # Mark example as skipped
140
129
  #
141
- # Not using alias method because we explictly want to discard any block.
142
- def skip(*args)
143
- pending_no_warning(*args)
130
+ # @param example [RSpec::Core::Example] the example to mark as skipped
131
+ # @param message_or_bool [Boolean, String] the message to use, or true
132
+ def self.mark_skipped!(example, message_or_bool)
133
+ Pending.mark_pending! example, message_or_bool
134
+ example.metadata[:skip] = true
144
135
  end
145
136
 
146
- def self.const_missing(name)
147
- return super unless name == :PendingDeclaredInExample
148
-
149
- RSpec.deprecate("RSpec::Core::PendingDeclaredInExample",
150
- :replacement => "RSpec::Core::Pending::SkipDeclaredInExample")
137
+ # @private
138
+ #
139
+ # Mark example as pending
140
+ #
141
+ # @param example [RSpec::Core::Example] the example to mark as pending
142
+ # @param message_or_bool [Boolean, String] the message to use, or true
143
+ def self.mark_pending!(example, message_or_bool)
144
+ message = if !message_or_bool || !(String === message_or_bool)
145
+ NO_REASON_GIVEN
146
+ else
147
+ message_or_bool
148
+ end
151
149
 
152
- SkipDeclaredInExample
150
+ example.metadata[:pending] = true
151
+ example.execution_result.pending_message = message
152
+ example.execution_result.pending_fixed = false
153
153
  end
154
- end
155
-
156
- # Alias the error for compatibility with extension gems (e.g. formatters)
157
- # that depend on the const name of the error in RSpec <= 2.8.
158
- def self.const_missing(name)
159
- return super unless name == :PendingExampleFixedError
160
154
 
161
- RSpec.deprecate("RSpec::Core::PendingExampleFixedError",
162
- :replacement => "RSpec::Core::Pending::PendingExampleFixedError")
163
-
164
- Pending::PendingExampleFixedError
155
+ # @private
156
+ #
157
+ # Mark example as fixed
158
+ #
159
+ # @param example [RSpec::Core::Example] the example to mark as fixed
160
+ def self.mark_fixed!(example)
161
+ example.execution_result.pending_fixed = true
162
+ end
165
163
  end
166
164
  end
167
165
  end
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper