rspec 1.1.2 → 1.1.3

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 (96) hide show
  1. data/CHANGES +17 -0
  2. data/Rakefile +7 -4
  3. data/failing_examples/README.txt +7 -0
  4. data/failing_examples/diffing_spec.rb +36 -0
  5. data/failing_examples/failing_autogenerated_docstrings_example.rb +19 -0
  6. data/failing_examples/failure_in_setup.rb +10 -0
  7. data/failing_examples/failure_in_teardown.rb +10 -0
  8. data/failing_examples/mocking_example.rb +40 -0
  9. data/failing_examples/mocking_with_flexmock.rb +26 -0
  10. data/failing_examples/mocking_with_mocha.rb +25 -0
  11. data/failing_examples/mocking_with_rr.rb +27 -0
  12. data/failing_examples/partial_mock_example.rb +20 -0
  13. data/failing_examples/predicate_example.rb +29 -0
  14. data/failing_examples/raising_example.rb +47 -0
  15. data/failing_examples/spec_helper.rb +3 -0
  16. data/failing_examples/syntax_error_example.rb +7 -0
  17. data/failing_examples/team_spec.rb +44 -0
  18. data/failing_examples/timeout_behaviour.rb +7 -0
  19. data/lib/autotest/rspec.rb +21 -35
  20. data/lib/spec.rb +0 -7
  21. data/lib/spec/example/example_group_methods.rb +10 -4
  22. data/lib/spec/example/example_methods.rb +4 -0
  23. data/lib/spec/interop/test.rb +3 -1
  24. data/lib/spec/interop/test/unit/ui/console/testrunner.rb +1 -0
  25. data/lib/spec/matchers/raise_error.rb +19 -15
  26. data/lib/spec/runner.rb +14 -0
  27. data/lib/spec/runner/formatter/story/html_formatter.rb +3 -0
  28. data/lib/spec/runner/formatter/story/plain_text_formatter.rb +4 -1
  29. data/lib/spec/runner/option_parser.rb +5 -33
  30. data/lib/spec/runner/options.rb +51 -18
  31. data/lib/spec/runner/spec_parser.rb +49 -31
  32. data/lib/spec/story/runner.rb +0 -2
  33. data/lib/spec/story/step.rb +8 -6
  34. data/lib/spec/story/world.rb +1 -0
  35. data/lib/spec/version.rb +22 -22
  36. data/pre_commit/lib/pre_commit.rb +4 -0
  37. data/pre_commit/lib/pre_commit/core.rb +50 -0
  38. data/pre_commit/lib/pre_commit/pre_commit.rb +54 -0
  39. data/pre_commit/lib/pre_commit/rspec.rb +111 -0
  40. data/pre_commit/lib/pre_commit/rspec_on_rails.rb +313 -0
  41. data/pre_commit/spec/pre_commit/pre_commit_spec.rb +15 -0
  42. data/pre_commit/spec/pre_commit/rspec_on_rails_spec.rb +36 -0
  43. data/pre_commit/spec/spec_helper.rb +3 -0
  44. data/pre_commit/spec/spec_suite.rb +11 -0
  45. data/rake_tasks/examples.rake +7 -0
  46. data/rake_tasks/examples_with_rcov.rake +9 -0
  47. data/rake_tasks/failing_examples_with_html.rake +9 -0
  48. data/rake_tasks/verify_rcov.rake +7 -0
  49. data/spec/README.jruby +15 -0
  50. data/spec/autotest/rspec_spec.rb +11 -80
  51. data/spec/autotest_helper.rb +2 -1
  52. data/spec/autotest_matchers.rb +47 -0
  53. data/spec/rspec_suite.rb +1 -1
  54. data/spec/spec.opts +6 -0
  55. data/spec/spec/example/example_group_methods_spec.rb +11 -2
  56. data/spec/spec/example/example_methods_spec.rb +69 -56
  57. data/spec/spec/interop/test/unit/resources/spec_that_fails.rb +10 -0
  58. data/spec/spec/interop/test/unit/resources/spec_that_passes.rb +10 -0
  59. data/spec/spec/interop/test/unit/resources/spec_with_errors.rb +10 -0
  60. data/spec/spec/interop/test/unit/resources/test_case_that_fails.rb +10 -0
  61. data/spec/spec/interop/test/unit/resources/test_case_that_passes.rb +10 -0
  62. data/spec/spec/interop/test/unit/resources/test_case_with_errors.rb +10 -0
  63. data/spec/spec/interop/test/unit/resources/testsuite_adapter_spec_with_test_unit.rb +38 -0
  64. data/spec/spec/interop/test/unit/spec_spec.rb +45 -0
  65. data/spec/spec/interop/test/unit/testcase_spec.rb +39 -4
  66. data/spec/spec/interop/test/unit/testsuite_adapter_spec.rb +1 -1
  67. data/spec/spec/matchers/raise_error_spec.rb +7 -1
  68. data/spec/spec/mocks/bug_report_10263.rb +1 -1
  69. data/spec/spec/runner/command_line_spec.rb +3 -2
  70. data/spec/spec/runner/empty_file.txt +0 -0
  71. data/spec/spec/runner/examples.txt +2 -0
  72. data/spec/spec/runner/failed.txt +3 -0
  73. data/spec/spec/runner/formatter/html_formatted-1.8.4.html +365 -0
  74. data/spec/spec/runner/formatter/html_formatted-1.8.5-jruby.html +387 -0
  75. data/spec/spec/runner/formatter/html_formatted-1.8.5.html +371 -0
  76. data/spec/spec/runner/formatter/html_formatted-1.8.6-jruby.html +381 -0
  77. data/spec/spec/runner/formatter/html_formatted-1.8.6.html +365 -0
  78. data/spec/spec/runner/formatter/story/plain_text_formatter_spec.rb +54 -54
  79. data/spec/spec/runner/formatter/text_mate_formatted-1.8.4.html +365 -0
  80. data/spec/spec/runner/formatter/text_mate_formatted-1.8.6.html +365 -0
  81. data/spec/spec/runner/option_parser_spec.rb +50 -49
  82. data/spec/spec/runner/options_spec.rb +72 -2
  83. data/spec/spec/runner/resources/a_bar.rb +0 -0
  84. data/spec/spec/runner/resources/a_foo.rb +0 -0
  85. data/spec/spec/runner/resources/a_spec.rb +1 -0
  86. data/spec/spec/runner/spec.opts +2 -0
  87. data/spec/spec/runner/spec_parser/spec_parser_fixture.rb +70 -0
  88. data/spec/spec/runner/spec_parser_spec.rb +31 -76
  89. data/spec/spec/runner/spec_spaced.opts +2 -0
  90. data/spec/spec/spec_classes.rb +4 -0
  91. data/spec/spec/story/step_spec.rb +22 -0
  92. data/spec/spec/story/world_spec.rb +7 -0
  93. data/stories/interop/test_case_with_should_methods +1 -1
  94. metadata +85 -5
  95. data/spec/spec/interop/test/unit/testcase_spec_with_test_unit.rb +0 -20
  96. data/spec/spec/interop/test/unit/testsuite_adapter_spec_with_test_unit.rb +0 -34
data/lib/spec.rb CHANGED
@@ -27,11 +27,4 @@ module Spec
27
27
  !Object.const_defined?(:Test) || Test::Unit.run?; \
28
28
  end
29
29
  end
30
- end
31
-
32
- at_exit do \
33
- unless $! || Spec.run?; \
34
- success = Spec.run; \
35
- exit success if Spec.exit?; \
36
- end \
37
30
  end
@@ -11,13 +11,14 @@ module Spec
11
11
  end
12
12
  end
13
13
 
14
- attr_reader :description_text, :description_args, :description_options, :spec_path
14
+ attr_reader :description_text, :description_args, :description_options, :spec_path, :registration_binding_block
15
15
 
16
16
  def inherited(klass)
17
17
  super
18
- klass.register
18
+ klass.register {}
19
+ Spec::Runner.register_at_exit_hook
19
20
  end
20
-
21
+
21
22
  # Makes the describe/it syntax available from a class. For example:
22
23
  #
23
24
  # class StackSpec < Spec::ExampleGroup
@@ -236,7 +237,8 @@ module Spec
236
237
  @after_each_parts = nil
237
238
  end
238
239
 
239
- def register
240
+ def register(&registration_binding_block)
241
+ @registration_binding_block = registration_binding_block
240
242
  rspec_options.add_example_group self
241
243
  end
242
244
 
@@ -244,6 +246,10 @@ module Spec
244
246
  rspec_options.remove_example_group self
245
247
  end
246
248
 
249
+ def registration_backtrace
250
+ eval("caller", registration_binding_block.binding)
251
+ end
252
+
247
253
  def run_before_each(example)
248
254
  execute_in_class_hierarchy do |example_group|
249
255
  example.eval_each_fail_fast(example_group.before_each_parts)
@@ -81,6 +81,10 @@ module Spec
81
81
  Spec::Matchers.clear_generated_description
82
82
  end
83
83
  end
84
+
85
+ def implementation_backtrace
86
+ eval("caller", @_implementation)
87
+ end
84
88
 
85
89
  protected
86
90
  include Matchers
@@ -7,4 +7,6 @@ require 'spec/interop/test/unit/autorunner'
7
7
  require 'spec/interop/test/unit/testresult'
8
8
  require 'spec/interop/test/unit/ui/console/testrunner'
9
9
 
10
- Spec::Example::ExampleGroupFactory.default(Test::Unit::TestCase)
10
+ Spec::Example::ExampleGroupFactory.default(Test::Unit::TestCase)
11
+
12
+ Test::Unit.run = true
@@ -36,6 +36,7 @@ module Test
36
36
 
37
37
  alias_method :finished_without_rspec, :finished
38
38
  def finished_with_rspec(elapsed_time)
39
+ @ran_test ||= false
39
40
  if @ran_test
40
41
  finished_without_rspec(elapsed_time)
41
42
  end
@@ -21,27 +21,31 @@ module Spec
21
21
  if @expected_message.nil?
22
22
  @raised_expected_error = true
23
23
  else
24
- case @expected_message
25
- when Regexp
26
- if @expected_message =~ @actual_error.message
27
- @raised_expected_error = true
28
- else
29
- @raised_other = true
30
- end
31
- else
32
- if @expected_message == @actual_error.message
33
- @raised_expected_error = true
34
- else
35
- @raised_other = true
36
- end
37
- end
24
+ verify_message
38
25
  end
39
- rescue => @actual_error
26
+ rescue Exception => @actual_error
40
27
  @raised_other = true
41
28
  ensure
42
29
  return @raised_expected_error
43
30
  end
44
31
  end
32
+
33
+ def verify_message
34
+ case @expected_message
35
+ when Regexp
36
+ if @expected_message =~ @actual_error.message
37
+ @raised_expected_error = true
38
+ else
39
+ @raised_other = true
40
+ end
41
+ else
42
+ if @expected_message == @actual_error.message
43
+ @raised_expected_error = true
44
+ else
45
+ @raised_other = true
46
+ end
47
+ end
48
+ end
45
49
 
46
50
  def failure_message
47
51
  return "expected #{expected_error}#{actual_error}" if @raised_other || !@raised_expected_error
data/lib/spec/runner.rb CHANGED
@@ -183,6 +183,20 @@ module Spec
183
183
  def configure
184
184
  yield configuration
185
185
  end
186
+
187
+ def register_at_exit_hook # :nodoc:
188
+ $spec_runner_at_exit_hook_registered ||= nil
189
+ unless $spec_runner_at_exit_hook_registered
190
+ at_exit do
191
+ unless $! || Spec.run?; \
192
+ success = Spec.run; \
193
+ exit success if Spec.exit?; \
194
+ end
195
+ end
196
+ $spec_runner_at_exit_hook_registered = true
197
+ end
198
+ end
199
+
186
200
  end
187
201
  end
188
202
  end
@@ -98,6 +98,9 @@ EOF
98
98
  scenario_ended
99
99
  end
100
100
 
101
+ def step_upcoming(type, description, *args)
102
+ end
103
+
101
104
  def step_succeeded(type, description, *args)
102
105
  print_step('passed', type, description, *args) # TODO: uses succeeded CSS class
103
106
  end
@@ -76,7 +76,10 @@ module Spec
76
76
  end
77
77
  end
78
78
  end
79
-
79
+
80
+ def step_upcoming(type, description, *args)
81
+ end
82
+
80
83
  def step_succeeded(type, description, *args)
81
84
  found_step(type, description, false, *args)
82
85
  end
@@ -15,6 +15,10 @@ module Spec
15
15
  attr_reader :options
16
16
 
17
17
  OPTIONS = {
18
+ :pattern => ["-p", "--pattern [PATTERN]","Limit files loaded to those matching this pattern. Defaults to '**/*_spec.rb'",
19
+ "Separate multiple patterns with commas.",
20
+ "Applies only to directories named on the command line (files",
21
+ "named explicitly on the command line will be loaded regardless)."],
18
22
  :diff => ["-D", "--diff [FORMAT]", "Show diff of objects that are expected to be equal when they are not",
19
23
  "Builtin formats: unified|u|context|c",
20
24
  "You can also specify a custom differ class",
@@ -84,11 +88,11 @@ module Spec
84
88
  @out_stream = out
85
89
  @options = Options.new(@error_stream, @out_stream)
86
90
 
87
- @spec_parser = SpecParser.new
88
91
  @file_factory = File
89
92
 
90
93
  self.banner = "Usage: spec (FILE|DIRECTORY|GLOB)+ [options]"
91
94
  self.separator ""
95
+ on(*OPTIONS[:pattern]) {|pattern| @options.filename_pattern = pattern}
92
96
  on(*OPTIONS[:diff]) {|diff| @options.parse_diff(diff)}
93
97
  on(*OPTIONS[:colour]) {@options.colour = true}
94
98
  on(*OPTIONS[:example]) {|example| @options.parse_example(example)}
@@ -124,10 +128,6 @@ module Spec
124
128
  blk.call(file) if blk
125
129
  end
126
130
 
127
- if @options.line_number
128
- set_spec_from_line_number
129
- end
130
-
131
131
  @options
132
132
  end
133
133
 
@@ -193,37 +193,9 @@ module Spec
193
193
  exit if stdout?
194
194
  end
195
195
 
196
- def set_spec_from_line_number
197
- if @options.examples.empty?
198
- if @options.files.length == 1
199
- if @file_factory.file?(@options.files[0])
200
- source = @file_factory.open(@options.files[0])
201
- example = @spec_parser.spec_name_for(source, @options.line_number)
202
- @options.parse_example(example)
203
- elsif @file_factory.directory?(@options.files[0])
204
- @error_stream.puts "You must specify one file, not a directory when using the --line option"
205
- exit(1) if stderr?
206
- else
207
- @error_stream.puts "#{@options.files[0]} does not exist"
208
- exit(2) if stderr?
209
- end
210
- else
211
- @error_stream.puts "Only one file can be specified when using the --line option: #{@options.files.inspect}"
212
- exit(3) if stderr?
213
- end
214
- else
215
- @error_stream.puts "You cannot use both --line and --example"
216
- exit(4) if stderr?
217
- end
218
- end
219
-
220
196
  def stdout?
221
197
  @out_stream == $stdout
222
198
  end
223
-
224
- def stderr?
225
- @error_stream == $stderr
226
- end
227
199
  end
228
200
  end
229
201
  end
@@ -29,6 +29,7 @@ module Spec
29
29
  }
30
30
 
31
31
  attr_accessor(
32
+ :filename_pattern,
32
33
  :backtrace_tweaker,
33
34
  :context_lines,
34
35
  :diff_format,
@@ -53,6 +54,7 @@ module Spec
53
54
  def initialize(error_stream, output_stream)
54
55
  @error_stream = error_stream
55
56
  @output_stream = output_stream
57
+ @filename_pattern = "**/*_spec.rb"
56
58
  @backtrace_tweaker = QuietBacktraceTweaker.new
57
59
  @examples = []
58
60
  @colour = false
@@ -84,6 +86,7 @@ module Spec
84
86
  if example_groups.empty?
85
87
  true
86
88
  else
89
+ set_spec_from_line_number if line_number
87
90
  success = runner.run
88
91
  @examples_run = true
89
92
  heckle if heckle_runner
@@ -101,10 +104,14 @@ module Spec
101
104
 
102
105
  def colour=(colour)
103
106
  @colour = colour
104
- begin; \
105
- require 'Win32/Console/ANSI' if @colour && PLATFORM =~ /win32/; \
106
- rescue LoadError ; \
107
- raise "You must gem install win32console to use colour on Windows" ; \
107
+ if @colour && RUBY_PLATFORM =~ /win32/ ;\
108
+ begin ;\
109
+ require 'rubygems' ;\
110
+ require 'Win32/Console/ANSI' ;\
111
+ rescue LoadError ;\
112
+ warn "You must 'gem install win32console' to use colour on Windows" ;\
113
+ @colour = false ;\
114
+ end
108
115
  end
109
116
  end
110
117
 
@@ -175,6 +182,22 @@ module Spec
175
182
  end
176
183
  end
177
184
 
185
+ def files_to_load
186
+ result = []
187
+ sorted_files.each do |file|
188
+ if File.directory?(file)
189
+ filename_pattern.split(",").each do |pattern|
190
+ result += Dir[File.expand_path("#{file}/#{pattern.strip}")]
191
+ end
192
+ elsif File.file?(file)
193
+ result << file
194
+ else
195
+ raise "File or directory not found: #{file}"
196
+ end
197
+ end
198
+ result
199
+ end
200
+
178
201
  protected
179
202
  def examples_should_be_run?
180
203
  return @examples_should_be_run unless @examples_should_be_run.nil?
@@ -205,20 +228,6 @@ module Spec
205
228
  end
206
229
  end
207
230
 
208
- def files_to_load
209
- result = []
210
- sorted_files.each do |file|
211
- if test ?d, file
212
- result += Dir[File.expand_path("#{file}/**/*.rb")]
213
- elsif test ?f, file
214
- result << file
215
- else
216
- raise "File or directory not found: #{file}"
217
- end
218
- end
219
- result
220
- end
221
-
222
231
  def custom_runner
223
232
  return nil unless custom_runner?
224
233
  klass_name, arg = ClassAndArgumentsParser.parse(user_input_for_runner)
@@ -248,6 +257,30 @@ module Spec
248
257
  require 'spec/expectations/differs/default'
249
258
  self.differ_class = Spec::Expectations::Differs::Default
250
259
  end
260
+
261
+ def set_spec_from_line_number
262
+ if examples.empty?
263
+ if files.length == 1
264
+ if File.directory?(files[0])
265
+ error_stream.puts "You must specify one file, not a directory when using the --line option"
266
+ exit(1) if stderr?
267
+ else
268
+ example = SpecParser.new.spec_name_for(files[0], line_number)
269
+ @examples = [example]
270
+ end
271
+ else
272
+ error_stream.puts "Only one file can be specified when using the --line option: #{files.inspect}"
273
+ exit(3) if stderr?
274
+ end
275
+ else
276
+ error_stream.puts "You cannot use both --line and --example"
277
+ exit(4) if stderr?
278
+ end
279
+ end
280
+
281
+ def stderr?
282
+ @error_stream == $stderr
283
+ end
251
284
  end
252
285
  end
253
286
  end
@@ -2,14 +2,28 @@ module Spec
2
2
  module Runner
3
3
  # Parses a spec file and finds the nearest example for a given line number.
4
4
  class SpecParser
5
- def spec_name_for(io, line_number)
6
- source = io.read
7
- example_group, example_group_line = example_group_at_line(source, line_number)
8
- example, example_line = example_at_line(source, line_number)
9
- if example_group && example && (example_group_line < example_line)
10
- "#{example_group} #{example}"
11
- elsif example_group
12
- example_group
5
+ attr_reader :best_match
6
+
7
+ def initialize
8
+ @best_match = {}
9
+ end
10
+
11
+ def spec_name_for(file, line_number)
12
+ best_match.clear
13
+ file = File.expand_path(file)
14
+ rspec_options.example_groups.each do |example_group|
15
+ consider_example_groups_for_best_match example_group, file, line_number
16
+
17
+ example_group.examples.each do |example|
18
+ consider_example_for_best_match example, example_group, file, line_number
19
+ end
20
+ end
21
+ if best_match[:example_group]
22
+ if best_match[:example]
23
+ "#{best_match[:example_group].description} #{best_match[:example].description}"
24
+ else
25
+ best_match[:example_group].description
26
+ end
13
27
  else
14
28
  nil
15
29
  end
@@ -17,36 +31,40 @@ module Spec
17
31
 
18
32
  protected
19
33
 
20
- def example_group_at_line(source, line_number)
21
- find_above(source, line_number, /^\s*(context|describe)\s+(.*)\s+do/)
22
- end
23
-
24
- def example_at_line(source, line_number)
25
- find_above(source, line_number, /^\s*(specify|it)\s+(.*)\s+do/)
34
+ def consider_example_groups_for_best_match(example_group, file, line_number)
35
+ parsed_backtrace = parse_backtrace(example_group.registration_backtrace)
36
+ parsed_backtrace.each do |example_file, example_line|
37
+ if is_best_match?(file, line_number, example_file, example_line)
38
+ best_match.clear
39
+ best_match[:example_group] = example_group
40
+ best_match[:line] = example_line
41
+ end
42
+ end
26
43
  end
27
44
 
28
- # Returns the context/describe or specify/it name and the line number
29
- def find_above(source, line_number, pattern)
30
- lines_above_reversed(source, line_number).each_with_index do |line, n|
31
- return [parse_description($2), line_number-n] if line =~ pattern
45
+ def consider_example_for_best_match(example, example_group, file, line_number)
46
+ parsed_backtrace = parse_backtrace(example.implementation_backtrace)
47
+ parsed_backtrace.each do |example_file, example_line|
48
+ if is_best_match?(file, line_number, example_file, example_line)
49
+ best_match.clear
50
+ best_match[:example_group] = example_group
51
+ best_match[:example] = example
52
+ best_match[:line] = example_line
53
+ end
32
54
  end
33
- nil
34
55
  end
35
56
 
36
- def lines_above_reversed(source, line_number)
37
- lines = source.split("\n")
38
- lines[0...line_number].reverse
57
+ def is_best_match?(file, line_number, example_file, example_line)
58
+ file == File.expand_path(example_file) &&
59
+ example_line <= line_number &&
60
+ example_line > best_match[:line].to_i
39
61
  end
40
-
41
- def parse_description(str)
42
- return str[1..-2] if str =~ /^['"].*['"]$/
43
- if matches = /^['"](.*)['"](,.*)?$/.match(str)
44
- return ::Spec::Example::ExampleGroupMethods.description_text(matches[1])
45
- end
46
- if matches = /^(.*)\s*,\s*['"](.*)['"](,.*)?$/.match(str)
47
- return ::Spec::Example::ExampleGroupMethods.description_text(matches[1], matches[2])
62
+
63
+ def parse_backtrace(backtrace)
64
+ backtrace.collect do |trace_line|
65
+ split_line = trace_line.split(':')
66
+ [split_line[0], Integer(split_line[1])]
48
67
  end
49
- return str
50
68
  end
51
69
  end
52
70
  end