rspec-core 2.0.0.beta.22 → 2.6.4

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 (173) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +0 -1
  3. data/.travis.yml +9 -0
  4. data/Changelog.md +305 -0
  5. data/Gemfile +45 -20
  6. data/Guardfile +5 -0
  7. data/License.txt +2 -1
  8. data/{README.markdown → README.md} +23 -5
  9. data/Rakefile +63 -32
  10. data/bin/autospec +13 -0
  11. data/bin/rspec +24 -2
  12. data/cucumber.yml +1 -1
  13. data/features/.nav +57 -0
  14. data/features/Autotest.md +38 -0
  15. data/features/README.md +17 -0
  16. data/features/Upgrade.md +320 -0
  17. data/features/command_line/README.md +28 -0
  18. data/features/command_line/configure.feature +18 -15
  19. data/features/command_line/example_name_option.feature +37 -23
  20. data/features/command_line/exit_status.feature +16 -31
  21. data/features/command_line/format_option.feature +73 -0
  22. data/features/command_line/line_number_appended_to_path.feature +25 -27
  23. data/features/command_line/line_number_option.feature +11 -10
  24. data/features/command_line/rake_task.feature +68 -0
  25. data/features/command_line/tag.feature +90 -0
  26. data/features/configuration/alias_example_to.feature +48 -0
  27. data/features/configuration/custom_settings.feature +8 -10
  28. data/features/configuration/fail_fast.feature +77 -0
  29. data/features/configuration/read_options_from_file.feature +42 -26
  30. data/features/example_groups/basic_structure.feature +55 -0
  31. data/features/example_groups/shared_context.feature +74 -0
  32. data/features/example_groups/shared_example_group.feature +56 -41
  33. data/features/expectation_framework_integration/configure_expectation_framework.feature +73 -0
  34. data/features/filtering/exclusion_filters.feature +69 -9
  35. data/features/filtering/if_and_unless.feature +168 -0
  36. data/features/filtering/inclusion_filters.feature +58 -26
  37. data/features/filtering/run_all_when_everything_filtered.feature +46 -0
  38. data/features/formatters/custom_formatter.feature +17 -13
  39. data/features/formatters/text_formatter.feature +43 -0
  40. data/features/helper_methods/arbitrary_methods.feature +40 -0
  41. data/features/helper_methods/let.feature +50 -0
  42. data/features/helper_methods/modules.feature +149 -0
  43. data/features/hooks/around_hooks.feature +99 -69
  44. data/features/hooks/before_and_after_hooks.feature +74 -40
  45. data/features/hooks/filtering.feature +227 -0
  46. data/features/metadata/current_example.feature +17 -0
  47. data/features/metadata/described_class.feature +17 -0
  48. data/features/metadata/user_defined.feature +111 -0
  49. data/features/mock_framework_integration/use_any_framework.feature +106 -0
  50. data/features/mock_framework_integration/use_flexmock.feature +84 -11
  51. data/features/mock_framework_integration/use_mocha.feature +85 -11
  52. data/features/mock_framework_integration/use_rr.feature +86 -11
  53. data/features/mock_framework_integration/use_rspec.feature +85 -11
  54. data/features/pending/pending_examples.feature +143 -5
  55. data/features/spec_files/arbitrary_file_suffix.feature +2 -2
  56. data/features/step_definitions/additional_cli_steps.rb +30 -0
  57. data/features/subject/attribute_of_subject.feature +93 -15
  58. data/features/subject/explicit_subject.feature +28 -17
  59. data/features/subject/implicit_receiver.feature +29 -0
  60. data/features/subject/implicit_subject.feature +9 -10
  61. data/features/support/env.rb +6 -1
  62. data/lib/autotest/discover.rb +1 -0
  63. data/lib/autotest/rspec2.rb +15 -11
  64. data/lib/rspec/autorun.rb +2 -0
  65. data/lib/rspec/core/backward_compatibility.rb +32 -3
  66. data/lib/rspec/core/command_line.rb +4 -28
  67. data/lib/rspec/core/command_line_configuration.rb +16 -16
  68. data/lib/rspec/core/configuration.rb +286 -89
  69. data/lib/rspec/core/configuration_options.rb +74 -40
  70. data/lib/rspec/core/deprecation.rb +1 -1
  71. data/lib/rspec/core/drb_command_line.rb +5 -11
  72. data/lib/rspec/core/dsl.rb +11 -0
  73. data/lib/rspec/core/example.rb +63 -39
  74. data/lib/rspec/core/example_group.rb +109 -59
  75. data/lib/rspec/core/expecting/with_rspec.rb +9 -0
  76. data/lib/rspec/core/expecting/with_stdlib.rb +9 -0
  77. data/lib/rspec/core/extensions/kernel.rb +1 -1
  78. data/lib/rspec/core/extensions.rb +0 -1
  79. data/lib/rspec/core/formatters/base_formatter.rb +30 -15
  80. data/lib/rspec/core/formatters/base_text_formatter.rb +68 -40
  81. data/lib/rspec/core/formatters/documentation_formatter.rb +4 -2
  82. data/lib/rspec/core/formatters/helpers.rb +0 -4
  83. data/lib/rspec/core/formatters/html_formatter.rb +146 -41
  84. data/lib/rspec/core/formatters/progress_formatter.rb +1 -0
  85. data/lib/rspec/core/formatters/snippet_extractor.rb +1 -1
  86. data/lib/rspec/core/formatters/text_mate_formatter.rb +3 -1
  87. data/lib/rspec/core/hooks.rb +56 -17
  88. data/lib/rspec/core/metadata.rb +75 -64
  89. data/lib/rspec/core/metadata_hash_builder.rb +93 -0
  90. data/lib/rspec/core/mocking/with_flexmock.rb +2 -0
  91. data/lib/rspec/core/mocking/with_mocha.rb +2 -0
  92. data/lib/rspec/core/mocking/with_rr.rb +2 -0
  93. data/lib/rspec/core/mocking/with_rspec.rb +3 -1
  94. data/lib/rspec/core/option_parser.rb +49 -7
  95. data/lib/rspec/core/pending.rb +22 -4
  96. data/lib/rspec/core/rake_task.rb +64 -28
  97. data/lib/rspec/core/reporter.rb +6 -5
  98. data/lib/rspec/core/ruby_project.rb +2 -2
  99. data/lib/rspec/core/runner.rb +50 -6
  100. data/lib/rspec/core/shared_context.rb +16 -0
  101. data/lib/rspec/core/shared_example_group.rb +19 -4
  102. data/lib/rspec/core/subject.rb +92 -65
  103. data/lib/rspec/core/version.rb +1 -1
  104. data/lib/rspec/core/world.rb +85 -27
  105. data/lib/rspec/core.rb +55 -24
  106. data/lib/rspec/monkey/spork/test_framework/rspec.rb +1 -0
  107. data/rspec-core.gemspec +4 -25
  108. data/script/FullBuildRakeFile +63 -0
  109. data/script/cucumber +1 -0
  110. data/script/full_build +1 -0
  111. data/script/spec +1 -0
  112. data/spec/autotest/discover_spec.rb +19 -0
  113. data/spec/autotest/failed_results_re_spec.rb +25 -9
  114. data/spec/autotest/rspec_spec.rb +32 -41
  115. data/spec/rspec/core/command_line_spec.rb +62 -7
  116. data/spec/rspec/core/configuration_options_spec.rb +216 -148
  117. data/spec/rspec/core/configuration_spec.rb +419 -108
  118. data/spec/rspec/core/deprecations_spec.rb +38 -1
  119. data/spec/rspec/core/drb_command_line_spec.rb +21 -56
  120. data/spec/rspec/core/example_group_spec.rb +366 -127
  121. data/spec/rspec/core/example_spec.rb +125 -45
  122. data/spec/rspec/core/formatters/base_formatter_spec.rb +61 -1
  123. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +134 -97
  124. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +7 -6
  125. data/spec/rspec/core/formatters/helpers_spec.rb +1 -1
  126. data/spec/rspec/core/formatters/html_formatted-1.8.6.html +199 -81
  127. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +195 -83
  128. data/spec/rspec/core/formatters/html_formatted-1.8.7.html +199 -81
  129. data/spec/rspec/core/formatters/html_formatted-1.9.1.html +206 -81
  130. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +206 -61
  131. data/spec/rspec/core/formatters/html_formatter_spec.rb +17 -9
  132. data/spec/rspec/core/formatters/progress_formatter_spec.rb +1 -1
  133. data/spec/rspec/core/formatters/text_mate_formatted-1.8.6.html +199 -81
  134. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +195 -81
  135. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +199 -81
  136. data/spec/rspec/core/formatters/text_mate_formatted-1.9.1.html +206 -81
  137. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +206 -81
  138. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +22 -7
  139. data/spec/rspec/core/hooks_filtering_spec.rb +128 -5
  140. data/spec/rspec/core/hooks_spec.rb +90 -4
  141. data/spec/rspec/core/metadata_spec.rb +176 -163
  142. data/spec/rspec/core/option_parser_spec.rb +73 -6
  143. data/spec/rspec/core/pending_example_spec.rb +137 -35
  144. data/spec/rspec/core/rake_task_spec.rb +62 -29
  145. data/spec/rspec/core/reporter_spec.rb +20 -4
  146. data/spec/rspec/core/resources/formatter_specs.rb +25 -1
  147. data/spec/rspec/core/rspec_matchers_spec.rb +45 -0
  148. data/spec/rspec/core/runner_spec.rb +60 -10
  149. data/spec/rspec/core/shared_context_spec.rb +30 -0
  150. data/spec/rspec/core/shared_example_group_spec.rb +59 -23
  151. data/spec/rspec/core/subject_spec.rb +136 -0
  152. data/spec/rspec/core/world_spec.rb +211 -68
  153. data/spec/rspec/core_spec.rb +28 -0
  154. data/spec/spec_helper.rb +41 -24
  155. data/spec/support/matchers.rb +44 -13
  156. data/spec/support/shared_example_groups.rb +41 -0
  157. data/spec/support/spec_files.rb +44 -0
  158. data/spec.txt +1126 -0
  159. metadata +100 -170
  160. data/.treasure_map.rb +0 -23
  161. data/History.md +0 -30
  162. data/Upgrade.markdown +0 -150
  163. data/autotest/discover.rb +0 -2
  164. data/features/README.markdown +0 -12
  165. data/features/example_groups/describe_aliases.feature +0 -25
  166. data/features/example_groups/nested_groups.feature +0 -44
  167. data/features/hooks/described_class.feature +0 -14
  168. data/features/hooks/halt.feature +0 -26
  169. data/lib/rspec/core/around_proxy.rb +0 -14
  170. data/lib/rspec/core/extensions/object.rb +0 -15
  171. data/lib/rspec/core/formatters.rb +0 -8
  172. data/spec/ruby_forker.rb +0 -13
  173. data/specs.watchr +0 -59
@@ -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
@@ -0,0 +1,11 @@
1
+ module RSpec
2
+ module Core
3
+ module DSL
4
+ def describe(*args, &example_group_block)
5
+ RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ include RSpec::Core::DSL
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Core
3
3
  class Example
4
4
 
5
- attr_reader :metadata, :options
5
+ attr_reader :metadata, :options, :example_group_instance
6
6
 
7
7
  def self.delegate_to_metadata(*keys)
8
8
  keys.each do |key|
@@ -10,34 +10,31 @@ module RSpec
10
10
  end
11
11
  end
12
12
 
13
- delegate_to_metadata :description, :full_description, :execution_result, :file_path, :pending
13
+ delegate_to_metadata :description, :full_description, :execution_result, :file_path, :pending, :location
14
14
 
15
15
  def initialize(example_group_class, desc, options, example_block=nil)
16
16
  @example_group_class, @options, @example_block = example_group_class, options, example_block
17
17
  @metadata = @example_group_class.metadata.for_example(desc, options)
18
18
  @exception = nil
19
- @pending_declared_in_example = @in_block = false
19
+ @pending_declared_in_example = false
20
20
  end
21
21
 
22
22
  def example_group
23
23
  @example_group_class
24
24
  end
25
25
 
26
- def behaviour
27
- RSpec.deprecate("behaviour", "example_group")
28
- example_group
26
+ def around_hooks
27
+ @around_hooks ||= example_group.around_hooks_for(self)
29
28
  end
30
29
 
31
- def in_block?
32
- @in_block
30
+ def apply?(predicate, filters)
31
+ @metadata.apply?(predicate, filters) ||
32
+ @example_group_class.apply?(predicate, filters)
33
33
  end
34
34
 
35
- def pending?
36
- !!pending
37
- end
35
+ alias_method :pending?, :pending
38
36
 
39
37
  def run(example_group_instance, reporter)
40
- return if RSpec.wants_to_quit
41
38
  @example_group_instance = example_group_instance
42
39
  @example_group_instance.example = self
43
40
 
@@ -45,26 +42,32 @@ module RSpec
45
42
 
46
43
  begin
47
44
  unless pending
48
- with_pending_capture do
49
- with_around_hooks do
50
- begin
51
- run_before_each
52
- @in_block = true
53
- @example_group_instance.instance_eval(&@example_block)
54
- rescue Exception => e
55
- set_exception(e)
56
- ensure
57
- @in_block = false
58
- run_after_each
59
- 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
60
55
  end
61
56
  end
62
57
  end
63
58
  rescue Exception => e
64
59
  set_exception(e)
65
60
  ensure
66
- @example_group_instance.example = nil
67
- 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
68
71
  end
69
72
 
70
73
  finish(reporter)
@@ -80,17 +83,31 @@ module RSpec
80
83
  finish(reporter)
81
84
  end
82
85
 
83
- private
86
+ def self.procsy(metadata, &block)
87
+ Proc.new(&block).extend(Procsy).with(metadata)
88
+ end
89
+
90
+ module Procsy
91
+ attr_reader :metadata
84
92
 
85
- def with_pending_capture(&block)
86
- @pending_declared_in_example = catch(:pending_declared_in_example) do
87
- block.call
88
- throw :pending_declared_in_example, false
93
+ def self.extended(object)
94
+ def object.run; call; end
95
+ end
96
+
97
+ def with(metadata)
98
+ @metadata = metadata
99
+ self
89
100
  end
90
101
  end
91
102
 
92
- def with_around_hooks(&wrapped_example)
93
- @example_group_class.eval_around_eachs(@example_group_instance, wrapped_example).call
103
+ private
104
+
105
+ def with_around_hooks(&block)
106
+ if around_hooks.empty?
107
+ yield
108
+ else
109
+ @example_group_class.eval_around_eachs(self, Example.procsy(metadata, &block)).call
110
+ end
94
111
  end
95
112
 
96
113
  def start(reporter)
@@ -100,7 +117,7 @@ module RSpec
100
117
 
101
118
  def finish(reporter)
102
119
  if @exception
103
- record_finished 'failed', :exception_encountered => @exception
120
+ record_finished 'failed', :exception => @exception
104
121
  reporter.example_failed self
105
122
  false
106
123
  elsif @pending_declared_in_example
@@ -125,20 +142,27 @@ module RSpec
125
142
 
126
143
  def run_before_each
127
144
  @example_group_instance.setup_mocks_for_rspec if @example_group_instance.respond_to?(:setup_mocks_for_rspec)
128
- @example_group_class.eval_before_eachs(@example_group_instance)
145
+ @example_group_class.eval_before_eachs(self)
129
146
  end
130
147
 
131
148
  def run_after_each
132
- @example_group_class.eval_after_eachs(@example_group_instance)
149
+ @example_group_class.eval_after_eachs(self)
133
150
  @example_group_instance.verify_mocks_for_rspec if @example_group_instance.respond_to?(:verify_mocks_for_rspec)
134
151
  ensure
135
152
  @example_group_instance.teardown_mocks_for_rspec if @example_group_instance.respond_to?(:teardown_mocks_for_rspec)
136
153
  end
137
154
 
138
155
  def assign_auto_description
139
- if description.empty?
140
- metadata[:description] = RSpec::Matchers.generated_description
141
- RSpec::Matchers.clear_generated_description
156
+ if description.empty? and !pending?
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
142
166
  end
143
167
  end
144
168
 
@@ -1,17 +1,20 @@
1
1
  module RSpec
2
2
  module Core
3
3
  class ExampleGroup
4
+ extend MetadataHashBuilder::WithDeprecationWarning
4
5
  extend Extensions::ModuleEvalWithArgs
5
- include Extensions::InstanceEvalWithArgs
6
+ extend Subject::ClassMethods
6
7
  extend Hooks
7
- include Subject
8
- include Let
8
+
9
+ include Extensions::InstanceEvalWithArgs
10
+ include Subject::InstanceMethods
9
11
  include Pending
12
+ include Let
10
13
 
11
14
  attr_accessor :example
12
15
 
13
16
  def running_example
14
- RSpec.deprecate('running_example', 'example')
17
+ RSpec.deprecate("running_example", "example")
15
18
  example
16
19
  end
17
20
 
@@ -19,8 +22,8 @@ module RSpec
19
22
  RSpec.world
20
23
  end
21
24
 
22
- def self.inherited(klass)
23
- world.example_groups << klass if klass.superclass == ExampleGroup
25
+ def self.register
26
+ world.register(self)
24
27
  end
25
28
 
26
29
  class << self
@@ -39,9 +42,9 @@ module RSpec
39
42
 
40
43
  def self.define_example_method(name, extra_options={})
41
44
  module_eval(<<-END_RUBY, __FILE__, __LINE__)
42
- def self.#{name}(desc=nil, options={}, &block)
45
+ def self.#{name}(desc=nil, *args, &block)
46
+ options = build_metadata_hash_from(args)
43
47
  options.update(:pending => true) unless block
44
- options.update(:caller => caller)
45
48
  options.update(#{extra_options.inspect})
46
49
  examples << RSpec::Core::Example.new(self, desc, options, block)
47
50
  examples.last
@@ -57,18 +60,20 @@ module RSpec
57
60
 
58
61
  alias_example_to :it
59
62
  alias_example_to :specify
60
- alias_example_to :focused, :focused => true
63
+ alias_example_to :focused, :focused => true, :focus => true
64
+ alias_example_to :focus, :focused => true, :focus => true
61
65
  alias_example_to :pending, :pending => true
66
+ alias_example_to :xit, :pending => true
62
67
 
63
- def self.define_shared_group_method(new_name, report_label=nil)
68
+ def self.define_nested_shared_group_method(new_name, report_label=nil)
64
69
  module_eval(<<-END_RUBY, __FILE__, __LINE__)
65
70
  def self.#{new_name}(name, *args, &customization_block)
66
71
  shared_block = world.shared_example_groups[name]
67
72
  raise "Could not find shared example group named \#{name.inspect}" unless shared_block
68
73
 
69
74
  group = describe("#{report_label || "it should behave like"} \#{name}") do
70
- module_eval_with_args *args, &shared_block
71
- module_eval &customization_block if customization_block
75
+ module_eval_with_args(*args, &shared_block)
76
+ module_eval(&customization_block) if customization_block
72
77
  end
73
78
  group.metadata[:shared_group_name] = name
74
79
  group
@@ -76,14 +81,22 @@ module RSpec
76
81
  END_RUBY
77
82
  end
78
83
 
79
- define_shared_group_method :it_should_behave_like
84
+ define_nested_shared_group_method :it_should_behave_like
80
85
 
81
86
  class << self
82
- 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
83
88
  end
84
89
 
85
90
  alias_it_should_behave_like_to :it_behaves_like, "behaves like"
86
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
+
87
100
  def self.examples
88
101
  @examples ||= []
89
102
  end
@@ -93,7 +106,7 @@ module RSpec
93
106
  end
94
107
 
95
108
  def self.descendant_filtered_examples
96
- filtered_examples + children.collect{|c| c.descendant_filtered_examples}
109
+ @descendant_filtered_examples ||= filtered_examples + children.inject([]){|l,c| l + c.descendant_filtered_examples}
97
110
  end
98
111
 
99
112
  def self.metadata
@@ -101,7 +114,7 @@ module RSpec
101
114
  end
102
115
 
103
116
  def self.superclass_metadata
104
- self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
117
+ @superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
105
118
  end
106
119
 
107
120
  def self.describe(*args, &example_group_block)
@@ -109,7 +122,6 @@ module RSpec
109
122
  @_subclass_count += 1
110
123
  args << {} unless args.last.is_a?(Hash)
111
124
  args.last.update(:example_group_block => example_group_block)
112
- args.last.update(:caller => caller)
113
125
 
114
126
  # TODO 2010-05-05: Because we don't know if const_set is thread-safe
115
127
  child = const_set(
@@ -136,7 +148,7 @@ module RSpec
136
148
  end
137
149
 
138
150
  def self.descendants
139
- [self] + children.collect {|c| c.descendants}.flatten
151
+ @_descendants ||= [self] + children.inject([]) {|list, c| list + c.descendants}
140
152
  end
141
153
 
142
154
  def self.ancestors
@@ -144,10 +156,30 @@ module RSpec
144
156
  end
145
157
 
146
158
  def self.top_level?
147
- ancestors.size == 1
159
+ @top_level ||= superclass == ExampleGroup
160
+ end
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
148
168
  end
149
169
 
150
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
151
183
  @metadata = RSpec::Core::Metadata.new(superclass_metadata).process(*args)
152
184
  world.configure_group(self)
153
185
  end
@@ -157,49 +189,65 @@ module RSpec
157
189
  end
158
190
 
159
191
  def self.store_before_all_ivars(example_group_instance)
192
+ return if example_group_instance.instance_variables.empty?
160
193
  example_group_instance.instance_variables.each { |ivar|
161
194
  before_all_ivars[ivar] = example_group_instance.instance_variable_get(ivar)
162
195
  }
163
196
  end
164
197
 
165
198
  def self.assign_before_all_ivars(ivars, example_group_instance)
199
+ return if ivars.empty?
166
200
  ivars.each { |ivar, val| example_group_instance.instance_variable_set(ivar, val) }
167
201
  end
168
202
 
169
203
  def self.eval_before_alls(example_group_instance)
170
204
  return if descendant_filtered_examples.empty?
171
205
  assign_before_all_ivars(superclass.before_all_ivars, example_group_instance)
172
- world.run_hook_filtered(:before, :all, self, example_group_instance) if top_level?
206
+ world.run_hook_filtered(:before, :all, self, example_group_instance)
173
207
  run_hook!(:before, :all, example_group_instance)
174
208
  store_before_all_ivars(example_group_instance)
175
209
  end
176
210
 
177
- def self.eval_around_eachs(example_group_instance, wrapped_example)
178
- around_hooks.reverse.inject(wrapped_example) do |wrapper, hook|
179
- def wrapper.run; call; end
180
- lambda { example_group_instance.instance_eval_with_args(wrapper, &hook) }
211
+ def self.eval_around_eachs(example, initial_procsy)
212
+ example.around_hooks.reverse.inject(initial_procsy) do |procsy, around_hook|
213
+ Example.procsy(procsy.metadata) do
214
+ example.example_group_instance.instance_eval_with_args(procsy, &around_hook)
215
+ end
181
216
  end
182
217
  end
183
218
 
184
- def self.eval_before_eachs(example_group_instance)
185
- world.run_hook_filtered(:before, :each, self, example_group_instance)
186
- ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example_group_instance) }
219
+ def self.eval_before_eachs(example)
220
+ world.run_hook_filtered(:before, :each, self, example.example_group_instance, example)
221
+ ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example.example_group_instance) }
187
222
  end
188
223
 
189
- def self.eval_after_eachs(example_group_instance)
190
- ancestors.each { |ancestor| ancestor.run_hook(:after, :each, example_group_instance) }
191
- world.run_hook_filtered(:after, :each, self, example_group_instance)
224
+ def self.eval_after_eachs(example)
225
+ ancestors.each { |ancestor| ancestor.run_hook(:after, :each, example.example_group_instance) }
226
+ world.run_hook_filtered(:after, :each, self, example.example_group_instance, example)
192
227
  end
193
228
 
194
229
  def self.eval_after_alls(example_group_instance)
195
230
  return if descendant_filtered_examples.empty?
196
231
  assign_before_all_ivars(before_all_ivars, example_group_instance)
197
- run_hook!(:after, :all, example_group_instance)
198
- world.run_hook_filtered(:after, :all, self, example_group_instance) if top_level?
232
+
233
+ begin
234
+ run_hook!(:after, :all, example_group_instance)
235
+ rescue => e
236
+ # TODO: come up with a better solution for this.
237
+ RSpec.configuration.reporter.message <<-EOS
238
+
239
+ An error occurred in an after(:all) hook.
240
+ #{e.class}: #{e.message}
241
+ occurred at #{e.backtrace.first}
242
+
243
+ EOS
244
+ end
245
+
246
+ world.run_hook_filtered(:after, :all, self, example_group_instance)
199
247
  end
200
248
 
201
- def self.around_hooks
202
- (world.find_hook(:around, :each, self) + ancestors.reverse.map{|a| a.find_hook(:around, :each, self)}).flatten
249
+ def self.around_hooks_for(example)
250
+ world.find_hook(:around, :each, self, example) + ancestors.reverse.inject([]){|l,a| l + a.find_hook(:around, :each, self, example)}
203
251
  end
204
252
 
205
253
  def self.run(reporter)
@@ -207,47 +255,56 @@ module RSpec
207
255
  RSpec.clear_remaining_example_groups if top_level?
208
256
  return
209
257
  end
210
- @reporter = reporter
211
- example_group_instance = new
212
258
  reporter.example_group_started(self)
213
259
 
214
260
  begin
215
- eval_before_alls(example_group_instance)
216
- result_for_this_group = run_examples(example_group_instance, reporter)
261
+ eval_before_alls(new)
262
+ result_for_this_group = run_examples(reporter)
217
263
  results_for_descendants = children.map {|child| child.run(reporter)}.all?
218
264
  result_for_this_group && results_for_descendants
219
265
  rescue Exception => ex
220
266
  fail_filtered_examples(ex, reporter)
221
267
  ensure
222
- eval_after_alls(example_group_instance)
268
+ eval_after_alls(new)
269
+ before_all_ivars.clear
223
270
  reporter.example_group_finished(self)
224
271
  end
225
272
  end
226
273
 
227
274
  def self.fail_filtered_examples(exception, reporter)
228
275
  filtered_examples.each { |example| example.fail_fast(reporter, exception) }
276
+
277
+ children.each do |child|
278
+ reporter.example_group_started(child)
279
+ child.fail_filtered_examples(exception, reporter)
280
+ reporter.example_group_finished(child)
281
+ end
282
+ false
229
283
  end
230
284
 
231
- def self.run_examples(instance, reporter)
285
+ def self.fail_fast?
286
+ RSpec.configuration.fail_fast?
287
+ end
288
+
289
+ def self.run_examples(reporter)
232
290
  filtered_examples.map do |example|
233
- begin
234
- set_ivars(instance, before_all_ivars)
235
- example.run(instance, reporter)
236
- ensure
237
- clear_ivars(instance)
238
- clear_memoized(instance)
239
- end
291
+ next if RSpec.wants_to_quit
292
+ instance = new
293
+ set_ivars(instance, before_all_ivars)
294
+ succeeded = example.run(instance, reporter)
295
+ RSpec.wants_to_quit = true if fail_fast? && !succeeded
296
+ succeeded
240
297
  end.all?
241
298
  end
242
299
 
243
- def self.all_apply?(filters)
244
- metadata.all_apply?(filters)
300
+ def self.apply?(predicate, filters)
301
+ metadata.apply?(predicate, filters)
245
302
  end
246
303
 
247
304
  def self.declaration_line_numbers
248
- [metadata[:example_group][:line_number]] +
305
+ @declaration_line_numbers ||= [metadata[:example_group][:line_number]] +
249
306
  examples.collect {|e| e.metadata[:line_number]} +
250
- children.collect {|c| c.declaration_line_numbers}.flatten
307
+ children.inject([]) {|l,c| l + c.declaration_line_numbers}
251
308
  end
252
309
 
253
310
  def self.top_level_description
@@ -258,14 +315,6 @@ module RSpec
258
315
  ivars.each {|name, value| instance.instance_variable_set(name, value)}
259
316
  end
260
317
 
261
- def self.clear_ivars(instance)
262
- instance.instance_variables.each { |ivar| instance.send(:remove_instance_variable, ivar) }
263
- end
264
-
265
- def self.clear_memoized(instance)
266
- instance.__memoized.clear
267
- end
268
-
269
318
  def described_class
270
319
  self.class.described_class
271
320
  end
@@ -274,6 +323,7 @@ module RSpec
274
323
  begin
275
324
  instance_eval(&hook)
276
325
  rescue Exception => e
326
+ raise unless example
277
327
  example.set_exception(e)
278
328
  end
279
329
  end
@@ -0,0 +1,9 @@
1
+ require 'rspec/expectations'
2
+
3
+ module RSpec
4
+ module Core
5
+ module ExpectationFrameworkAdapter
6
+ include RSpec::Matchers
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'test/unit/assertions'
2
+
3
+ module RSpec
4
+ module Core
5
+ module ExpectationFrameworkAdapter
6
+ include Test::Unit::Assertions
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  module Kernel
2
2
  def debugger(*args)
3
- RSpec.configuration.error_stream.puts "debugger statement ignored, use -d or --debug option to enable debugging\n#{caller(0)[1]}"
3
+ (RSpec.configuration.error_stream || $stderr).puts "\n***** debugger statement ignored, use -d or --debug option to enable debugging\n#{caller(0)[1]}"
4
4
  end unless respond_to?(:debugger)
5
5
  end
@@ -1,4 +1,3 @@
1
- require 'rspec/core/extensions/object'
2
1
  require 'rspec/core/extensions/kernel'
3
2
  require 'rspec/core/extensions/instance_eval_with_args'
4
3
  require 'rspec/core/extensions/module_eval_with_args'
@@ -1,3 +1,6 @@
1
+ require 'rspec/core/formatters/helpers'
2
+ require 'stringio'
3
+
1
4
  module RSpec
2
5
  module Core
3
6
  module Formatters
@@ -9,8 +12,15 @@ module RSpec
9
12
  attr_reader :example_count, :pending_count, :failure_count
10
13
  attr_reader :failed_examples, :pending_examples
11
14
 
15
+ def self.relative_path(line)
16
+ line = line.sub(File.expand_path("."), ".")
17
+ line = line.sub(/\A([^:]+:\d+)$/, '\\1')
18
+ return nil if line == '-e:1'
19
+ line
20
+ end
21
+
12
22
  def initialize(output)
13
- @output = output
23
+ @output = output || StringIO.new
14
24
  @example_count = @pending_count = @failure_count = 0
15
25
  @examples = []
16
26
  @failed_examples = []
@@ -43,11 +53,6 @@ module RSpec
43
53
  def example_group_finished(example_group)
44
54
  end
45
55
 
46
- def add_example_group(example_group)
47
- RSpec.deprecate("add_example_group", "example_group_started")
48
- example_group_started(example_group)
49
- end
50
-
51
56
  def example_started(example)
52
57
  examples << example
53
58
  end
@@ -98,6 +103,11 @@ module RSpec
98
103
  def format_backtrace(backtrace, example)
99
104
  return "" unless backtrace
100
105
  return backtrace if example.metadata[:full_backtrace] == true
106
+
107
+ if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE)
108
+ backtrace = backtrace[0, at_exit_index]
109
+ end
110
+
101
111
  cleansed = backtrace.map { |line| backtrace_line(line) }.compact
102
112
  cleansed.empty? ? backtrace : cleansed
103
113
  end
@@ -110,26 +120,31 @@ module RSpec
110
120
 
111
121
  def backtrace_line(line)
112
122
  return nil if configuration.cleaned_from_backtrace?(line)
113
- line = line.sub(File.expand_path("."), ".")
114
- line = line.sub(/\A([^:]+:\d+)$/, '\\1')
115
- return nil if line == '-e:1'
116
- line
123
+ self.class.relative_path(line)
117
124
  end
118
125
 
119
126
  def read_failed_line(exception, example)
120
- original_file = example.file_path.to_s.downcase
121
- matching_line = exception.backtrace.detect { |line| line.match(/(.+?):(\d+)(|:\d+)/)[1].downcase == original_file.downcase }
122
-
123
- return "Unable to find matching line from backtrace" if matching_line.nil?
127
+ unless matching_line = find_failed_line(exception.backtrace, example.file_path)
128
+ return "Unable to find matching line from backtrace"
129
+ end
124
130
 
125
131
  file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
132
+
126
133
  if File.exist?(file_path)
127
- open(file_path, 'r') { |f| f.readlines[line_number.to_i - 1] }
134
+ File.readlines(file_path)[line_number.to_i - 1]
128
135
  else
129
136
  "Unable to find #{file_path} to read failed line"
130
137
  end
131
138
  end
132
139
 
140
+ def find_failed_line(backtrace, path)
141
+ backtrace.detect { |line|
142
+ match = line.match(/(.+?):(\d+)(|:\d+)/)
143
+ match && match[1].downcase == path.downcase
144
+ }
145
+
146
+ end
147
+
133
148
  def start_sync_output
134
149
  @old_sync, output.sync = output.sync, true if output_supports_sync
135
150
  end