rspec-core 2.7.1 → 2.8.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.md +1 -1
  2. data/features/command_line/order.feature +29 -0
  3. data/features/command_line/tag.feature +10 -9
  4. data/features/configuration/default_path.feature +2 -2
  5. data/features/filtering/exclusion_filters.feature +1 -1
  6. data/features/filtering/run_all_when_everything_filtered.feature +1 -1
  7. data/features/subject/attribute_of_subject.feature +1 -1
  8. data/lib/rspec/core.rb +148 -12
  9. data/lib/rspec/core/command_line.rb +2 -2
  10. data/lib/rspec/core/configuration.rb +300 -155
  11. data/lib/rspec/core/configuration_options.rb +34 -53
  12. data/lib/rspec/core/deprecation.rb +4 -0
  13. data/lib/rspec/core/drb_options.rb +72 -0
  14. data/lib/rspec/core/example.rb +58 -24
  15. data/lib/rspec/core/example_group.rb +10 -5
  16. data/lib/rspec/core/extensions.rb +1 -0
  17. data/lib/rspec/core/extensions/ordered.rb +16 -0
  18. data/lib/rspec/core/filter_manager.rb +170 -0
  19. data/lib/rspec/core/formatters/base_formatter.rb +3 -1
  20. data/lib/rspec/core/formatters/base_text_formatter.rb +6 -0
  21. data/lib/rspec/core/formatters/snippet_extractor.rb +1 -1
  22. data/lib/rspec/core/hooks.rb +197 -1
  23. data/lib/rspec/core/let.rb +3 -2
  24. data/lib/rspec/core/metadata.rb +25 -4
  25. data/lib/rspec/core/option_parser.rb +89 -54
  26. data/lib/rspec/core/pending.rb +41 -0
  27. data/lib/rspec/core/rake_task.rb +9 -25
  28. data/lib/rspec/core/reporter.rb +43 -19
  29. data/lib/rspec/core/shared_context.rb +35 -0
  30. data/lib/rspec/core/shared_example_group.rb +0 -1
  31. data/lib/rspec/core/subject.rb +4 -4
  32. data/lib/rspec/core/version.rb +1 -1
  33. data/lib/rspec/core/world.rb +34 -52
  34. data/spec/autotest/failed_results_re_spec.rb +2 -2
  35. data/spec/command_line/order_spec.rb +131 -0
  36. data/spec/rspec/core/command_line_spec.rb +2 -1
  37. data/spec/rspec/core/configuration_options_spec.rb +83 -163
  38. data/spec/rspec/core/configuration_spec.rb +311 -139
  39. data/spec/rspec/core/drb_options_spec.rb +131 -0
  40. data/spec/rspec/core/example_group_spec.rb +22 -11
  41. data/spec/rspec/core/example_spec.rb +1 -2
  42. data/spec/rspec/core/filter_manager_spec.rb +175 -0
  43. data/spec/rspec/core/formatters/helpers_spec.rb +1 -1
  44. data/spec/rspec/core/formatters/html_formatter_spec.rb +3 -2
  45. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -1
  46. data/spec/rspec/core/metadata_spec.rb +21 -6
  47. data/spec/rspec/core/option_parser_spec.rb +74 -0
  48. data/spec/rspec/core/reporter_spec.rb +18 -1
  49. data/spec/rspec/core/shared_context_spec.rb +54 -17
  50. data/spec/rspec/core/subject_spec.rb +1 -1
  51. data/spec/rspec/core/world_spec.rb +7 -188
  52. data/spec/spec_helper.rb +47 -43
  53. data/spec/support/config_options_helper.rb +27 -0
  54. metadata +28 -12
  55. data/lib/rspec/core/expecting/with_rspec.rb +0 -9
  56. data/lib/rspec/core/expecting/with_stdlib.rb +0 -9
@@ -5,6 +5,47 @@ module RSpec
5
5
 
6
6
  DEFAULT_MESSAGE = 'No reason given'
7
7
 
8
+ # @overload pending()
9
+ # @overload pending(message)
10
+ # @overload pending(message, &block)
11
+ #
12
+ # Stops execution of an example, and reports it as pending. Takes an
13
+ # optional message and block.
14
+ #
15
+ # @param [String] message optional message to add to the summary report.
16
+ # @param [Block] block optional block. If it fails, the example is
17
+ # reported as pending. If it executes cleanly the example fails.
18
+ #
19
+ # @example
20
+ #
21
+ # describe "an example" do
22
+ # # reported as "Pending: no reason given"
23
+ # it "is pending with no message" do
24
+ # pending
25
+ # this_does_not_get_executed
26
+ # end
27
+ #
28
+ # # reported as "Pending: something else getting finished"
29
+ # it "is pending with a custom message" do
30
+ # pending("something else getting finished")
31
+ # this_does_not_get_executed
32
+ # end
33
+ #
34
+ # # reported as "Pending: something else getting finished"
35
+ # it "is pending with a failing block" do
36
+ # pending("something else getting finished") do
37
+ # raise "this is the failure"
38
+ # end
39
+ # end
40
+ #
41
+ # # reported as failure, saying we expected the block to fail but
42
+ # # it passed.
43
+ # it "is pending with a passing block" do
44
+ # pending("something else getting finished") do
45
+ # true.should be(true)
46
+ # end
47
+ # end
48
+ # end
8
49
  def pending(*args)
9
50
  return self.class.before(:each) { pending(*args) } unless example
10
51
 
@@ -20,39 +20,26 @@ module RSpec
20
20
  # 'spec/**/*_spec.rb'
21
21
  attr_accessor :pattern
22
22
 
23
- # Deprecated and has no effect. The rake task now checks
24
- # ENV['BUNDLE_GEMFILE'] instead.
25
- #
26
- # By default, if there is a Gemfile, the generated command will include
27
- # 'bundle exec'. Set this to true to ignore the presence of a Gemfile, and
28
- # not add 'bundle exec' to the command.
29
- #
30
- # default:
31
- # false
23
+ # @deprecated
24
+ # Has no effect. The rake task now checks ENV['BUNDLE_GEMFILE'] instead.
32
25
  def skip_bundler=(*)
33
26
  RSpec.deprecate("RSpec::Core::RakeTask#skip_bundler=")
34
27
  end
35
28
 
36
- # Deprecated and has no effect. The rake task now checks
37
- # ENV['BUNDLE_GEMFILE'] instead.
38
- #
39
- # Name of Gemfile to use.
40
- #
41
- # default:
42
- # Gemfile
29
+ # @deprecated
30
+ # Has no effect. The rake task now checks ENV['BUNDLE_GEMFILE'] instead.
43
31
  def gemfile=(*)
44
32
  RSpec.deprecate("RSpec::Core::RakeTask#gemfile=", 'ENV["BUNDLE_GEMFILE"]')
45
33
  end
46
34
 
47
- # Deprecated. Use ruby_opts="-w" instead.
35
+ # @deprecated
36
+ # Use ruby_opts="-w" instead.
48
37
  #
49
38
  # When true, requests that the specs be run with the warning flag set.
50
39
  # e.g. "ruby -w"
51
40
  #
52
41
  # default:
53
42
  # false
54
- attr_reader :warning
55
-
56
43
  def warning=(true_or_false)
57
44
  RSpec.deprecate("RSpec::Core::RakeTask#warning=", 'ruby_opts="-w"')
58
45
  @warning = true_or_false
@@ -110,7 +97,8 @@ module RSpec
110
97
  # nil
111
98
  attr_accessor :rspec_opts
112
99
 
113
- # Deprecated. Use rspec_opts instead.
100
+ # @deprecated
101
+ # Use rspec_opts instead.
114
102
  #
115
103
  # Command line options to pass to rspec.
116
104
  #
@@ -167,7 +155,7 @@ module RSpec
167
155
  cmd_parts = []
168
156
  cmd_parts << RUBY
169
157
  cmd_parts << ruby_opts
170
- cmd_parts << "-w" if warning?
158
+ cmd_parts << "-w" if @warning
171
159
  cmd_parts << "-S"
172
160
  cmd_parts << runner
173
161
  if rcov
@@ -189,10 +177,6 @@ module RSpec
189
177
  rcov ? rcov_path : rspec_path
190
178
  end
191
179
 
192
- def warning?
193
- warning
194
- end
195
-
196
180
  def blank
197
181
  lambda {|s| s == ""}
198
182
  end
@@ -3,33 +3,42 @@ module RSpec::Core
3
3
  def initialize(*formatters)
4
4
  @formatters = formatters
5
5
  @example_count = @failure_count = @pending_count = 0
6
- @duration = nil
6
+ @duration = @start = nil
7
7
  end
8
8
 
9
- def report(count)
10
- start(count)
9
+ # @api
10
+ # @overload report(count, &block)
11
+ # @overload report(count, seed, &block)
12
+ # @param [Integer] count the number of examples being run
13
+ # @param [Integer] seed the seed used to randomize the spec run
14
+ # @param [Block] block yields itself for further reporting.
15
+ #
16
+ # Initializes the report run and yields itself for further reporting. The
17
+ # block is required, so that the reporter can manage cleaning up after the
18
+ # run.
19
+ #
20
+ # ### Warning:
21
+ #
22
+ # The `seed` argument is an internal API and is not guaranteed to be
23
+ # supported in the future.
24
+ #
25
+ # @example
26
+ #
27
+ # reporter.report(group.examples.size) do |r|
28
+ # example_groups.map {|g| g.run(r) }
29
+ # end
30
+ #
31
+ def report(expected_example_count, seed=nil)
32
+ start(expected_example_count)
11
33
  begin
12
34
  yield self
13
35
  ensure
14
- finish
36
+ finish(seed)
15
37
  end
16
38
  end
17
39
 
18
- def finish
19
- begin
20
- stop
21
- notify :start_dump
22
- notify :dump_pending
23
- notify :dump_failures
24
- notify :dump_summary, @duration, @example_count, @failure_count, @pending_count
25
- ensure
26
- notify :close
27
- end
28
- end
29
-
30
- alias_method :abort, :finish
31
-
32
40
  def start(expected_example_count)
41
+ @start = Time.now
33
42
  notify :start, expected_example_count
34
43
  end
35
44
 
@@ -64,8 +73,23 @@ module RSpec::Core
64
73
  notify :example_pending, example
65
74
  end
66
75
 
76
+ def finish(seed)
77
+ begin
78
+ stop
79
+ notify :start_dump
80
+ notify :dump_pending
81
+ notify :dump_failures
82
+ notify :dump_summary, @duration, @example_count, @failure_count, @pending_count
83
+ notify :seed, seed if seed
84
+ ensure
85
+ notify :close
86
+ end
87
+ end
88
+
89
+ alias_method :abort, :finish
90
+
67
91
  def stop
68
- @duration = Time.now - $rspec_start_time
92
+ @duration = Time.now - @start if @start
69
93
  notify :stop
70
94
  end
71
95
 
@@ -1,7 +1,26 @@
1
1
  module RSpec
2
2
  module Core
3
+ # Exposes [ExampleGroup](ExampleGroup)-level methods to a module, so you
4
+ # can include that module in an [ExampleGroup](ExampleGroup).
5
+ #
6
+ # @note exposed as `RSpec::SharedContext`
7
+ #
8
+ # @example
9
+ #
10
+ # module LoggedInAsAdmin
11
+ # extend RSpec::SharedContext
12
+ # before(:each) do
13
+ # log_in_as :admin
14
+ # end
15
+ # end
16
+ #
17
+ # describe "admin section" do
18
+ # include LoggedInAsAdmin
19
+ # # ...
20
+ # end
3
21
  module SharedContext
4
22
  include Hooks
23
+ include Let::ClassMethods
5
24
 
6
25
  def included(group)
7
26
  [:before, :after].each do |type|
@@ -9,8 +28,24 @@ module RSpec
9
28
  group.hooks[type][scope].concat hooks[type][scope]
10
29
  end
11
30
  end
31
+ _nested_group_declarations.each do |name, block, *args|
32
+ group.describe name, *args, &block
33
+ end
34
+ end
35
+
36
+ def describe(name, *args, &block)
37
+ _nested_group_declarations << [name, block, *args]
12
38
  end
13
39
 
40
+ alias_method :context, :describe
41
+
42
+ private
43
+
44
+ def _nested_group_declarations
45
+ @_nested_group_declarations ||= []
46
+ end
14
47
  end
15
48
  end
49
+
50
+ SharedContext = Core::SharedContext
16
51
  end
@@ -15,7 +15,6 @@ module RSpec
15
15
  host.class_eval(&block)
16
16
  end
17
17
  RSpec.configuration.extend(mod, *args)
18
- else
19
18
  end
20
19
  end
21
20
 
@@ -11,7 +11,7 @@ module RSpec
11
11
  # declared in the example group, then +subject+ will return a new
12
12
  # instance of that class.
13
13
  #
14
- # == Examples
14
+ # @example
15
15
  #
16
16
  # # explicit subject defined by the subject method
17
17
  # describe Person do
@@ -45,7 +45,7 @@ module RSpec
45
45
  # an implicit subject (see +subject+), this supports very concise
46
46
  # expressions.
47
47
  #
48
- # == Examples
48
+ # @example
49
49
  #
50
50
  # describe Person do
51
51
  # it { should be_eligible_to_vote }
@@ -57,7 +57,7 @@ module RSpec
57
57
  # Just like +should+, +should_not+ delegates to the subject (implicit or
58
58
  # explicit) of the example group.
59
59
  #
60
- # == Examples
60
+ # @example
61
61
  #
62
62
  # describe Person do
63
63
  # it { should_not be_eligible_to_vote }
@@ -139,7 +139,7 @@ module RSpec
139
139
  # Defines an explicit subject for an example group which can then be the
140
140
  # implicit receiver (through delegation) of calls to +should+.
141
141
  #
142
- # == Examples
142
+ # @example
143
143
  #
144
144
  # describe CheckingAccount, "with $50" do
145
145
  # subject { CheckingAccount.new(:amount => 50, :currency => :USD) }
@@ -1,7 +1,7 @@
1
1
  module RSpec
2
2
  module Core
3
3
  module Version
4
- STRING = '2.7.1'
4
+ STRING = '2.8.0.rc1'
5
5
  end
6
6
  end
7
7
  end
@@ -2,27 +2,6 @@ module RSpec
2
2
  module Core
3
3
  class World
4
4
 
5
- module Describable
6
- PROC_HEX_NUMBER = /0x[0-9a-f]+@/
7
- PROJECT_DIR = File.expand_path('.')
8
-
9
- def description
10
- reject { |k, v| RSpec::Core::Configuration::CONDITIONAL_FILTERS[k] == v }.inspect.gsub(PROC_HEX_NUMBER, '').gsub(PROJECT_DIR, '.').gsub(' (lambda)','')
11
- end
12
-
13
- def empty_without_conditional_filters?
14
- reject { |k, v| RSpec::Core::Configuration::CONDITIONAL_FILTERS[k] == v }.empty?
15
- end
16
-
17
- def reject
18
- super rescue {}
19
- end
20
-
21
- def empty?
22
- super rescue false
23
- end
24
- end
25
-
26
5
  include RSpec::Core::Hooks
27
6
 
28
7
  attr_reader :example_groups, :filtered_examples, :wants_to_quit
@@ -30,13 +9,13 @@ module RSpec
30
9
 
31
10
  def initialize(configuration=RSpec.configuration)
32
11
  @configuration = configuration
33
- @example_groups = []
12
+ @example_groups = [].extend(Extensions::Ordered)
34
13
  @filtered_examples = Hash.new { |hash,group|
35
14
  hash[group] = begin
36
15
  examples = group.examples.dup
37
- examples = apply_exclusion_filters(examples, exclusion_filter)
38
- examples = apply_inclusion_filters(examples, inclusion_filter)
16
+ examples = filter_manager.prune(examples)
39
17
  examples.uniq
18
+ examples.extend(Extensions::Ordered)
40
19
  end
41
20
  }
42
21
  end
@@ -45,17 +24,21 @@ module RSpec
45
24
  example_groups.clear
46
25
  end
47
26
 
27
+ def filter_manager
28
+ @configuration.filter_manager
29
+ end
30
+
48
31
  def register(example_group)
49
32
  example_groups << example_group
50
33
  example_group
51
34
  end
52
35
 
53
36
  def inclusion_filter
54
- @configuration.inclusion_filter.extend(Describable)
37
+ @configuration.inclusion_filter
55
38
  end
56
39
 
57
40
  def exclusion_filter
58
- @configuration.exclusion_filter.extend(Describable)
41
+ @configuration.exclusion_filter
59
42
  end
60
43
 
61
44
  def configure_group(group)
@@ -70,16 +53,6 @@ module RSpec
70
53
  example_groups.collect {|g| g.descendants}.flatten.inject(0) { |sum, g| sum += g.filtered_examples.size }
71
54
  end
72
55
 
73
- def apply_inclusion_filters(examples, filters)
74
- filters.empty? ? examples : examples.select {|e| e.metadata.any_apply?(filters)}
75
- end
76
-
77
- alias_method :find, :apply_inclusion_filters
78
-
79
- def apply_exclusion_filters(examples, filters)
80
- filters.empty? ? examples : examples.reject {|e| e.metadata.any_apply?(filters)}
81
- end
82
-
83
56
  def preceding_declaration_line(filter_line)
84
57
  declaration_line_numbers.sort.inject(nil) do |highest_prior_declaration_line, line|
85
58
  line <= filter_line ? line : highest_prior_declaration_line
@@ -93,43 +66,52 @@ module RSpec
93
66
  def announce_filters
94
67
  filter_announcements = []
95
68
 
69
+ announce_inclusion_filter filter_announcements
70
+ announce_exclusion_filter filter_announcements
71
+
72
+ unless filter_manager.empty?
73
+ if filter_announcements.length == 1
74
+ reporter.message("Run options: #{filter_announcements[0]}")
75
+ else
76
+ reporter.message("Run options:\n #{filter_announcements.join("\n ")}")
77
+ end
78
+ end
79
+
96
80
  if @configuration.run_all_when_everything_filtered? && example_count.zero?
97
- reporter.message( "No examples matched #{inclusion_filter.description}. Running all.")
81
+ reporter.message("#{everything_filtered_message}; ignoring #{inclusion_filter.description}")
98
82
  filtered_examples.clear
99
- @configuration.clear_inclusion_filter
83
+ inclusion_filter.clear
100
84
  end
101
85
 
102
- announce_inclusion_filter filter_announcements
103
- announce_exclusion_filter filter_announcements
104
-
105
86
  if example_count.zero?
106
87
  example_groups.clear
107
- if filter_announcements.empty?
88
+ if filter_manager.empty?
108
89
  reporter.message("No examples found.")
109
- elsif !inclusion_filter.empty?
110
- message = "No examples matched #{inclusion_filter.description}."
90
+ elsif exclusion_filter.empty_without_conditional_filters?
91
+ message = everything_filtered_message
111
92
  if @configuration.run_all_when_everything_filtered?
112
- message << " Running all."
93
+ message << "; ignoring #{inclusion_filter.description}"
113
94
  end
114
95
  reporter.message(message)
115
- elsif !exclusion_filter.empty?
116
- reporter.message(
117
- "No examples were matched. Perhaps #{exclusion_filter.description} is excluding everything?")
96
+ elsif inclusion_filter.empty?
97
+ reporter.message(everything_filtered_message)
118
98
  end
119
- elsif !filter_announcements.empty?
120
- reporter.message("Run filtered #{filter_announcements.join(', ')}")
121
99
  end
122
100
  end
123
101
 
102
+ def everything_filtered_message
103
+ "\nAll examples were filtered out"
104
+ end
105
+
124
106
  def announce_inclusion_filter(announcements)
125
107
  unless inclusion_filter.empty?
126
- announcements << "including #{inclusion_filter.description}"
108
+ announcements << "include #{inclusion_filter.description}"
127
109
  end
128
110
  end
129
111
 
130
112
  def announce_exclusion_filter(announcements)
131
113
  unless exclusion_filter.empty_without_conditional_filters?
132
- announcements << "excluding #{exclusion_filter.description}"
114
+ announcements << "exclude #{exclusion_filter.description}"
133
115
  end
134
116
  end
135
117