rspec-core 2.5.2 → 2.6.0.rc2

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 (117) hide show
  1. data/.travis.yml +7 -0
  2. data/Gemfile +10 -13
  3. data/README.md +4 -1
  4. data/Rakefile +29 -12
  5. data/cucumber.yml +1 -1
  6. data/features/.nav +10 -4
  7. data/features/Autotest.md +31 -7
  8. data/features/Changelog.md +36 -6
  9. data/features/command_line/configure.feature +2 -2
  10. data/features/command_line/example_name_option.feature +10 -10
  11. data/features/command_line/exit_status.feature +4 -4
  12. data/features/command_line/format_option.feature +4 -4
  13. data/features/command_line/line_number_appended_to_path.feature +11 -11
  14. data/features/command_line/line_number_option.feature +2 -2
  15. data/features/command_line/rake_task.feature +3 -3
  16. data/features/command_line/tag.feature +26 -10
  17. data/features/configuration/alias_example_to.feature +48 -0
  18. data/features/configuration/custom_settings.feature +3 -3
  19. data/features/configuration/fail_fast.feature +3 -3
  20. data/features/configuration/read_options_from_file.feature +4 -4
  21. data/features/example_groups/basic_structure.feature +11 -15
  22. data/features/example_groups/shared_context.feature +74 -0
  23. data/features/example_groups/shared_example_group.feature +21 -17
  24. data/features/expectation_framework_integration/configure_expectation_framework.feature +15 -4
  25. data/features/filtering/exclusion_filters.feature +28 -4
  26. data/features/filtering/{implicit_filters.feature → if_and_unless.feature} +9 -7
  27. data/features/filtering/inclusion_filters.feature +26 -3
  28. data/features/filtering/run_all_when_everything_filtered.feature +1 -1
  29. data/features/formatters/custom_formatter.feature +1 -1
  30. data/features/formatters/text_formatter.feature +45 -0
  31. data/features/helper_methods/arbitrary_methods.feature +2 -2
  32. data/features/helper_methods/let.feature +2 -2
  33. data/features/helper_methods/modules.feature +149 -0
  34. data/features/hooks/around_hooks.feature +11 -11
  35. data/features/hooks/before_and_after_hooks.feature +15 -19
  36. data/features/hooks/filtering.feature +160 -124
  37. data/features/metadata/current_example.feature +17 -0
  38. data/features/metadata/described_class.feature +2 -2
  39. data/features/metadata/user_defined.feature +111 -0
  40. data/features/mock_framework_integration/use_any_framework.feature +1 -1
  41. data/features/mock_framework_integration/use_flexmock.feature +83 -10
  42. data/features/mock_framework_integration/use_mocha.feature +84 -10
  43. data/features/mock_framework_integration/use_rr.feature +85 -10
  44. data/features/mock_framework_integration/use_rspec.feature +84 -10
  45. data/features/pending/pending_examples.feature +8 -8
  46. data/features/spec_files/arbitrary_file_suffix.feature +1 -1
  47. data/features/step_definitions/additional_cli_steps.rb +11 -1
  48. data/features/subject/attribute_of_subject.feature +24 -4
  49. data/features/subject/explicit_subject.feature +5 -5
  50. data/features/subject/implicit_receiver.feature +2 -2
  51. data/features/subject/implicit_subject.feature +2 -2
  52. data/features/support/env.rb +6 -1
  53. data/lib/rspec/core.rb +22 -0
  54. data/lib/rspec/core/backward_compatibility.rb +12 -2
  55. data/lib/rspec/core/command_line.rb +1 -4
  56. data/lib/rspec/core/configuration.rb +25 -17
  57. data/lib/rspec/core/configuration_options.rb +6 -23
  58. data/lib/rspec/core/drb_command_line.rb +5 -11
  59. data/lib/rspec/core/example.rb +29 -21
  60. data/lib/rspec/core/example_group.rb +36 -4
  61. data/lib/rspec/core/formatters/base_formatter.rb +6 -0
  62. data/lib/rspec/core/formatters/base_text_formatter.rb +1 -1
  63. data/lib/rspec/core/formatters/helpers.rb +0 -4
  64. data/lib/rspec/core/hooks.rb +14 -4
  65. data/lib/rspec/core/metadata.rb +1 -1
  66. data/lib/rspec/core/metadata_hash_builder.rb +93 -0
  67. data/lib/rspec/core/mocking/with_flexmock.rb +2 -0
  68. data/lib/rspec/core/mocking/with_mocha.rb +2 -0
  69. data/lib/rspec/core/mocking/with_rr.rb +2 -0
  70. data/lib/rspec/core/mocking/with_rspec.rb +3 -1
  71. data/lib/rspec/core/option_parser.rb +5 -2
  72. data/lib/rspec/core/pending.rb +10 -3
  73. data/lib/rspec/core/reporter.rb +2 -2
  74. data/lib/rspec/core/runner.rb +7 -1
  75. data/lib/rspec/core/shared_example_group.rb +18 -4
  76. data/lib/rspec/core/subject.rb +4 -6
  77. data/lib/rspec/core/version.rb +1 -1
  78. data/lib/rspec/core/world.rb +16 -4
  79. data/rspec-core.gemspec +4 -3
  80. data/spec.txt +1126 -0
  81. data/spec/autotest/failed_results_re_spec.rb +2 -2
  82. data/spec/rspec/core/command_line_spec.rb +0 -2
  83. data/spec/rspec/core/configuration_spec.rb +84 -1
  84. data/spec/rspec/core/deprecations_spec.rb +21 -0
  85. data/spec/rspec/core/drb_command_line_spec.rb +3 -11
  86. data/spec/rspec/core/example_group_spec.rb +213 -56
  87. data/spec/rspec/core/example_spec.rb +110 -0
  88. data/spec/rspec/core/formatters/base_formatter_spec.rb +23 -2
  89. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +9 -0
  90. data/spec/rspec/core/formatters/helpers_spec.rb +1 -1
  91. data/spec/rspec/core/formatters/html_formatted-1.8.6.html +5 -5
  92. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +8 -10
  93. data/spec/rspec/core/formatters/html_formatted-1.8.7.html +5 -5
  94. data/spec/rspec/core/formatters/html_formatted-1.9.1.html +5 -5
  95. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +5 -5
  96. data/spec/rspec/core/formatters/progress_formatter_spec.rb +0 -1
  97. data/spec/rspec/core/formatters/text_mate_formatted-1.8.6.html +5 -5
  98. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +8 -10
  99. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +5 -5
  100. data/spec/rspec/core/formatters/text_mate_formatted-1.9.1.html +5 -5
  101. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +5 -5
  102. data/spec/rspec/core/hooks_spec.rb +86 -0
  103. data/spec/rspec/core/metadata_spec.rb +7 -7
  104. data/spec/rspec/core/option_parser_spec.rb +8 -0
  105. data/spec/rspec/core/pending_example_spec.rb +12 -51
  106. data/spec/rspec/core/reporter_spec.rb +19 -3
  107. data/spec/rspec/core/resources/formatter_specs.rb +7 -1
  108. data/spec/rspec/core/rspec_matchers_spec.rb +45 -0
  109. data/spec/rspec/core/runner_spec.rb +35 -10
  110. data/spec/rspec/core/shared_example_group_spec.rb +57 -21
  111. data/spec/rspec/core/subject_spec.rb +32 -11
  112. data/spec/rspec/core/world_spec.rb +38 -15
  113. data/spec/rspec/core_spec.rb +28 -0
  114. data/spec/spec_helper.rb +22 -2
  115. data/spec/support/matchers.rb +44 -13
  116. data/spec/support/shared_example_groups.rb +41 -0
  117. metadata +39 -16
@@ -1,6 +1,3 @@
1
- # http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html
2
- require 'optparse'
3
-
4
1
  module RSpec
5
2
  module Core
6
3
 
@@ -60,35 +57,21 @@ module RSpec
60
57
  end
61
58
 
62
59
  def parse_options
63
- @options = begin
64
- options_to_merge = []
65
- if custom_options_file
66
- options_to_merge << custom_options
67
- else
68
- options_to_merge << global_options
69
- options_to_merge << local_options
70
- end
71
- options_to_merge << command_line_options
72
- options_to_merge << env_options
73
-
74
- options_to_merge.inject do |merged, options|
75
- merged.merge(options)
76
- end
77
- end
60
+ @options ||= [file_options, command_line_options, env_options].inject {|merged, o| merged.merge o}
78
61
  end
79
62
 
80
63
  private
81
64
 
65
+ def file_options
66
+ custom_options_file ? custom_options : global_options.merge(local_options)
67
+ end
68
+
82
69
  def env_options
83
70
  ENV["SPEC_OPTS"] ? Parser.parse!(ENV["SPEC_OPTS"].split) : {}
84
71
  end
85
72
 
86
73
  def command_line_options
87
- @command_line_options ||= begin
88
- options = Parser.parse!(@args)
89
- options[:files_or_directories_to_run] = @args
90
- options
91
- end
74
+ @command_line_options ||= Parser.parse!(@args).merge :files_or_directories_to_run => @args
92
75
  end
93
76
 
94
77
  def custom_options
@@ -11,18 +11,12 @@ module RSpec
11
11
 
12
12
  def run(err, out)
13
13
  begin
14
- begin
15
- DRb.start_service("druby://localhost:0")
16
- rescue SocketError, Errno::EADDRNOTAVAIL
17
- DRb.start_service("druby://:0")
18
- end
19
- spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{drb_port}")
20
- spec_server.run(@options.drb_argv, err, out)
21
- true
22
- rescue DRb::DRbConnError
23
- err.puts "No DRb server is running. Running in local process instead ..."
24
- false
14
+ DRb.start_service("druby://localhost:0")
15
+ rescue SocketError, Errno::EADDRNOTAVAIL
16
+ DRb.start_service("druby://:0")
25
17
  end
18
+ spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{drb_port}")
19
+ spec_server.run(@options.drb_argv, err, out)
26
20
  end
27
21
  end
28
22
  end
@@ -42,24 +42,32 @@ module RSpec
42
42
 
43
43
  begin
44
44
  unless pending
45
- with_pending_capture do
46
- with_around_hooks do
47
- begin
48
- run_before_each
49
- @example_group_instance.instance_eval(&@example_block)
50
- rescue Exception => e
51
- set_exception(e)
52
- ensure
53
- run_after_each
54
- end
45
+ with_around_hooks do
46
+ begin
47
+ run_before_each
48
+ @example_group_instance.instance_eval(&@example_block)
49
+ rescue Pending::PendingDeclaredInExample => e
50
+ @pending_declared_in_example = e.message
51
+ rescue Exception => e
52
+ set_exception(e)
53
+ ensure
54
+ run_after_each
55
55
  end
56
56
  end
57
57
  end
58
58
  rescue Exception => e
59
59
  set_exception(e)
60
60
  ensure
61
- @example_group_instance.example = nil
62
- assign_auto_description
61
+ @example_group_instance.instance_variables.each do |ivar|
62
+ @example_group_instance.instance_variable_set(ivar, nil)
63
+ end
64
+ @example_group_instance = nil
65
+
66
+ begin
67
+ assign_auto_description
68
+ rescue Exception => e
69
+ set_exception(e)
70
+ end
63
71
  end
64
72
 
65
73
  finish(reporter)
@@ -94,13 +102,6 @@ module RSpec
94
102
 
95
103
  private
96
104
 
97
- def with_pending_capture
98
- @pending_declared_in_example = catch(:pending_declared_in_example) do
99
- yield
100
- throw :pending_declared_in_example, false
101
- end
102
- end
103
-
104
105
  def with_around_hooks(&block)
105
106
  if around_hooks.empty?
106
107
  yield
@@ -153,8 +154,15 @@ module RSpec
153
154
 
154
155
  def assign_auto_description
155
156
  if description.empty? and !pending?
156
- metadata[:description] = RSpec::Matchers.generated_description
157
- RSpec::Matchers.clear_generated_description
157
+ if RSpec.configuration.expecting_with_rspec?
158
+ metadata[:description] = RSpec::Matchers.generated_description
159
+ RSpec::Matchers.clear_generated_description
160
+ else
161
+ raise NotImplementedError.new(
162
+ "Generated descriptions are only supported when you use rspec-expectations. " +
163
+ "You must give every example an explicit description."
164
+ )
165
+ end
158
166
  end
159
167
  end
160
168
 
@@ -8,6 +8,7 @@ module RSpec
8
8
  include Subject::InstanceMethods
9
9
  include Let
10
10
  include Pending
11
+ extend MetadataHashBuilder::WithDeprecationWarning
11
12
 
12
13
  attr_accessor :example
13
14
 
@@ -41,7 +42,8 @@ module RSpec
41
42
 
42
43
  def self.define_example_method(name, extra_options={})
43
44
  module_eval(<<-END_RUBY, __FILE__, __LINE__)
44
- def self.#{name}(desc=nil, options={}, &block)
45
+ def self.#{name}(desc=nil, *args, &block)
46
+ options = build_metadata_hash_from(args)
45
47
  options.update(:pending => true) unless block
46
48
  options.update(#{extra_options.inspect})
47
49
  examples << RSpec::Core::Example.new(self, desc, options, block)
@@ -63,7 +65,7 @@ module RSpec
63
65
  alias_example_to :pending, :pending => true
64
66
  alias_example_to :xit, :pending => true
65
67
 
66
- def self.define_shared_group_method(new_name, report_label=nil)
68
+ def self.define_nested_shared_group_method(new_name, report_label=nil)
67
69
  module_eval(<<-END_RUBY, __FILE__, __LINE__)
68
70
  def self.#{new_name}(name, *args, &customization_block)
69
71
  shared_block = world.shared_example_groups[name]
@@ -79,14 +81,22 @@ module RSpec
79
81
  END_RUBY
80
82
  end
81
83
 
82
- define_shared_group_method :it_should_behave_like
84
+ define_nested_shared_group_method :it_should_behave_like
83
85
 
84
86
  class << self
85
- alias_method :alias_it_should_behave_like_to, :define_shared_group_method
87
+ alias_method :alias_it_should_behave_like_to, :define_nested_shared_group_method
86
88
  end
87
89
 
88
90
  alias_it_should_behave_like_to :it_behaves_like, "behaves like"
89
91
 
92
+ def self.include_context(name)
93
+ module_eval(&world.shared_example_groups[name])
94
+ end
95
+
96
+ class << self
97
+ alias_method :include_examples, :include_context
98
+ end
99
+
90
100
  def self.examples
91
101
  @examples ||= []
92
102
  end
@@ -149,7 +159,27 @@ module RSpec
149
159
  @top_level ||= superclass == ExampleGroup
150
160
  end
151
161
 
162
+ def self.ensure_example_groups_are_configured
163
+ unless defined?(@@example_groups_configured)
164
+ RSpec.configuration.configure_mock_framework
165
+ RSpec.configuration.configure_expectation_framework
166
+ @@example_groups_configured = true
167
+ end
168
+ end
169
+
152
170
  def self.set_it_up(*args)
171
+ # Ruby 1.9 has a bug that can lead to infinite recursion and a
172
+ # SystemStackError if you include a module in a superclass after
173
+ # including it in a subclass: https://gist.github.com/845896
174
+ # To prevent this, we must include any modules in RSpec::Core::ExampleGroup
175
+ # before users create example groups and have a chance to include
176
+ # the same module in a subclass of RSpec::Core::ExampleGroup.
177
+ # So we need to configure example groups here.
178
+ ensure_example_groups_are_configured
179
+
180
+ symbol_description = args.shift if args.first.is_a?(Symbol)
181
+ args << build_metadata_hash_from(args)
182
+ args.unshift(symbol_description) if symbol_description
153
183
  @metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
154
184
  world.configure_group(self)
155
185
  end
@@ -236,6 +266,7 @@ An error occurred in an after(:all) hook.
236
266
  fail_filtered_examples(ex, reporter)
237
267
  ensure
238
268
  eval_after_alls(new)
269
+ before_all_ivars.clear
239
270
  reporter.example_group_finished(self)
240
271
  end
241
272
  end
@@ -248,6 +279,7 @@ An error occurred in an after(:all) hook.
248
279
  child.fail_filtered_examples(exception, reporter)
249
280
  reporter.example_group_finished(child)
250
281
  end
282
+ false
251
283
  end
252
284
 
253
285
  def self.fail_fast?
@@ -1,4 +1,5 @@
1
1
  require 'rspec/core/formatters/helpers'
2
+ require 'stringio'
2
3
 
3
4
  module RSpec
4
5
  module Core
@@ -95,6 +96,11 @@ module RSpec
95
96
  def format_backtrace(backtrace, example)
96
97
  return "" unless backtrace
97
98
  return backtrace if example.metadata[:full_backtrace] == true
99
+
100
+ if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE)
101
+ backtrace = backtrace[0, at_exit_index]
102
+ end
103
+
98
104
  cleansed = backtrace.map { |line| backtrace_line(line) }.compact
99
105
  cleansed.empty? ? backtrace : cleansed
100
106
  end
@@ -148,7 +148,7 @@ module RSpec
148
148
  output.puts "#{short_padding}#{index.next}) #{example.full_description}"
149
149
  output.puts "#{long_padding}#{red("Failure/Error:")} #{red(read_failed_line(exception, example).strip)}"
150
150
  output.puts "#{long_padding}#{red(exception.class.name << ":")}" unless exception.class.name =~ /RSpec/
151
- exception.message.split("\n").each { |line| output.puts "#{long_padding} #{red(line)}" }
151
+ exception.message.split("\n").each { |line| output.puts "#{long_padding} #{red(line)}" } if exception.message
152
152
 
153
153
  example.example_group.ancestors.push(example.example_group).each do |group|
154
154
  if group.metadata[:shared_group_name]
@@ -1,7 +1,5 @@
1
1
  module RSpec
2
-
3
2
  module Core
4
-
5
3
  module Formatters
6
4
 
7
5
  module Helpers
@@ -22,7 +20,5 @@ module RSpec
22
20
  end
23
21
 
24
22
  end
25
-
26
23
  end
27
-
28
24
  end
@@ -1,12 +1,14 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Hooks
4
+ include MetadataHashBuilder::WithConfigWarning
4
5
 
5
6
  class Hook
6
7
  attr_reader :options
7
8
 
8
9
  def initialize(options, &block)
9
10
  @options = options
11
+ raise "no block given for #{self.class::TYPE} hook" unless block
10
12
  @block = block
11
13
  end
12
14
 
@@ -24,6 +26,7 @@ module RSpec
24
26
  end
25
27
 
26
28
  class BeforeHook < Hook
29
+ TYPE = 'before'
27
30
  def run_in(example_group_instance)
28
31
  if example_group_instance
29
32
  example_group_instance.instance_eval(&self)
@@ -34,6 +37,7 @@ module RSpec
34
37
  end
35
38
 
36
39
  class AfterHook < Hook
40
+ TYPE = 'after'
37
41
  def run_in(example_group_instance)
38
42
  if example_group_instance
39
43
  example_group_instance.instance_eval_with_rescue(&self)
@@ -44,6 +48,7 @@ module RSpec
44
48
  end
45
49
 
46
50
  class AroundHook < Hook
51
+ TYPE = 'around'
47
52
  def call(wrapped_example)
48
53
  @block.call(wrapped_example)
49
54
  end
@@ -137,11 +142,16 @@ module RSpec
137
142
 
138
143
  private
139
144
 
140
- def scope_and_options_from(scope=:each, options={})
141
- if Hash === scope
142
- options = scope
143
- scope = :each
145
+ def scope_and_options_from(*args)
146
+ scope = if [:each, :all, :suite].include?(args.first)
147
+ args.shift
148
+ elsif args.any? { |a| a.is_a?(Symbol) }
149
+ raise ArgumentError.new("You must explicitly give a scope (:each, :all, or :suite) when using symbols as metadata for a hook.")
150
+ else
151
+ :each
144
152
  end
153
+
154
+ options = build_metadata_hash_from(args)
145
155
  return scope, options
146
156
  end
147
157
  end
@@ -142,7 +142,7 @@ EOM
142
142
  metadata[key] == value
143
143
  end
144
144
  else
145
- metadata[key] == value
145
+ metadata[key].to_s == value.to_s
146
146
  end
147
147
  end
148
148
 
@@ -0,0 +1,93 @@
1
+ module RSpec
2
+ module Core
3
+ module MetadataHashBuilder
4
+ module Common
5
+ def build_metadata_hash_from(args)
6
+ metadata = args.last.is_a?(Hash) ? args.pop : {}
7
+
8
+ if RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values?
9
+ add_symbols_to_hash(metadata, args)
10
+ else
11
+ warn_about_symbol_usage(args)
12
+ end
13
+
14
+ metadata
15
+ end
16
+
17
+ private
18
+
19
+ def add_symbols_to_hash(hash, args)
20
+ while args.last.is_a?(Symbol)
21
+ hash[args.pop] = true
22
+ end
23
+ end
24
+
25
+ def warn_about_symbol_usage(args)
26
+ symbols = args.select { |a| a.is_a?(Symbol) }
27
+ return if symbols.empty?
28
+ Kernel.warn symbol_metadata_warning(symbols)
29
+ end
30
+ end
31
+
32
+ module WithConfigWarning
33
+ include Common
34
+
35
+ private
36
+
37
+ def symbol_metadata_warning(symbols)
38
+ <<-NOTICE
39
+
40
+ *****************************************************************
41
+ WARNING: You have passed symbols (#{symbols.inspect}) as metadata
42
+ arguments to a configuration option.
43
+
44
+ In RSpec 3, these symbols will be treated as metadata keys with
45
+ a value of `true`. To get this behavior now (and prevent this
46
+ warning), you can set a configuration option:
47
+
48
+ RSpec.configure do |c|
49
+ c.treat_symbols_as_metadata_keys_with_true_values = true
50
+ end
51
+
52
+ Note that this config setting should go before your other config
53
+ settings so that they can use symbols as metadata.
54
+ *****************************************************************
55
+
56
+ NOTICE
57
+ end
58
+ end
59
+
60
+ module WithDeprecationWarning
61
+ include Common
62
+
63
+ private
64
+
65
+ def symbol_metadata_warning(symbols)
66
+ <<-NOTICE
67
+
68
+ *****************************************************************
69
+ DEPRECATION WARNING: you are using deprecated behaviour that will
70
+ be removed from RSpec 3.
71
+
72
+ You have passed symbols (#{symbols.inspect}) as additional
73
+ arguments for a doc string.
74
+
75
+ In RSpec 3, these symbols will be treated as metadata keys with
76
+ a value of `true`. To get this behavior now (and prevent this
77
+ warning), you can set a configuration option:
78
+
79
+ RSpec.configure do |c|
80
+ c.treat_symbols_as_metadata_keys_with_true_values = true
81
+ end
82
+
83
+ Alternately, if your intention is to use the symbol as part of the
84
+ doc string (i.e. to specify a method name), you can change it to
85
+ a string such as "#method_name" to remove this warning.
86
+ *****************************************************************
87
+
88
+ NOTICE
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end