rspec 0.7.3 → 0.7.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 (44) hide show
  1. data/CHANGES +23 -1
  2. data/Rakefile +11 -9
  3. data/bin/spec +0 -1
  4. data/lib/spec.rb +1 -0
  5. data/lib/spec/callback.rb +3 -0
  6. data/lib/spec/callback/callback_container.rb +60 -0
  7. data/lib/spec/callback/extensions/module.rb +24 -0
  8. data/lib/spec/callback/extensions/object.rb +33 -0
  9. data/lib/spec/expectations/diff.rb +10 -14
  10. data/lib/spec/expectations/extensions.rb +1 -3
  11. data/lib/spec/expectations/extensions/numeric.rb +6 -1
  12. data/lib/spec/expectations/extensions/object.rb +72 -18
  13. data/lib/spec/expectations/should/base.rb +27 -5
  14. data/lib/spec/expectations/should/have.rb +2 -2
  15. data/lib/spec/expectations/should/should.rb +5 -4
  16. data/lib/spec/mocks/error_generator.rb +23 -12
  17. data/lib/spec/mocks/message_expectation.rb +4 -0
  18. data/lib/spec/mocks/mock_handler.rb +9 -8
  19. data/lib/spec/rake/spectask.rb +2 -1
  20. data/lib/spec/runner.rb +0 -1
  21. data/lib/spec/runner/backtrace_tweaker.rb +1 -0
  22. data/lib/spec/runner/context_eval.rb +1 -1
  23. data/lib/spec/runner/formatter/base_text_formatter.rb +1 -1
  24. data/lib/spec/runner/formatter/html_formatter.rb +94 -74
  25. data/lib/spec/runner/option_parser.rb +5 -1
  26. data/lib/spec/runner/specification.rb +64 -37
  27. data/lib/spec/version.rb +3 -3
  28. data/vendor/{selenium → web_spec/selenium}/README.txt +0 -0
  29. data/vendor/{selenium → web_spec/selenium}/find_rspecs_home_page.rb +0 -0
  30. data/vendor/{selenium → web_spec/selenium}/rspec_selenium.rb +0 -0
  31. data/vendor/{selenium → web_spec/selenium}/start_browser_once.patch +0 -0
  32. data/vendor/{watir → web_spec/watir}/README.txt +2 -2
  33. data/vendor/web_spec/watir/find_rspecs_home_page.rb +27 -0
  34. data/vendor/{watir → web_spec/watir}/find_rspecs_home_page.txt +0 -0
  35. data/vendor/{watir → web_spec/watir}/rspec_watir.rb +13 -12
  36. data/vendor/web_spec/web_test_html_formatter.rb +8 -0
  37. data/vendor/web_spec/web_test_html_formatter_helper.rb +26 -0
  38. data/vendor/web_spec/web_test_html_formatter_osx_helper.rb +19 -0
  39. data/vendor/web_spec/web_test_html_formatter_win_helper.rb +14 -0
  40. metadata +19 -14
  41. data/lib/spec/expectations/extensions/inspect_for_expectation_not_met_error.rb +0 -15
  42. data/lib/spec/expectations/extensions/symbol.rb +0 -5
  43. data/lib/spec/runner/extensions/object.rb +0 -21
  44. data/vendor/watir/find_rspecs_home_page.rb +0 -21
@@ -40,7 +40,7 @@ module Spec
40
40
  end
41
41
 
42
42
  def msg(sym, args, text)
43
- "#{@target.inspect_for_expectation_not_met_error} #{text} #{sym}: #{args.collect{|arg| arg.inspect_for_expectation_not_met_error}.join(', ')}"
43
+ "#{@target.inspect} #{text} #{sym}: #{args.collect{|arg| arg.inspect}.join(', ')}"
44
44
  end
45
45
 
46
46
  def actual_size(collection)
@@ -49,7 +49,7 @@ module Spec
49
49
  end
50
50
 
51
51
  def build_message(sym, args)
52
- message = "#{@target.inspect_for_expectation_not_met_error} should have"
52
+ message = "#{@target.inspect} should have"
53
53
  message += " at least" if @at_least
54
54
  message += " at most" if @at_most
55
55
  message += " #{@expected} #{sym} (has #{actual_size(collection(sym, args))})"
@@ -7,7 +7,7 @@ module Spec
7
7
  @target = target
8
8
  @be_seen = false
9
9
  end
10
-
10
+
11
11
  def have(expected_number=nil)
12
12
  Have.new(@target, :exactly, expected_number)
13
13
  end
@@ -45,7 +45,8 @@ module Spec
45
45
 
46
46
  def __delegate_method_missing_to_target(original_sym, actual_sym, *args)
47
47
  return if @target.send(actual_sym, *args)
48
- fail_with_message(default_message("should#{@be_seen ? ' be' : ''} #{original_sym}" + (args.empty? ? '' : ' ' + args[0].inspect)))
48
+ message = default_message("should#{@be_seen ? ' be' : ''} #{original_sym}", args[0])
49
+ fail_with_message(message)
49
50
  end
50
51
 
51
52
  def match(expected)
@@ -58,9 +59,9 @@ module Spec
58
59
  rescue exception => e
59
60
  unless message.nil?
60
61
  if message.is_a?(Regexp)
61
- e.message.should_match message
62
+ e.message.should =~ message
62
63
  else
63
- e.message.should_eql message
64
+ e.message.should == message
64
65
  end
65
66
  end
66
67
  return
@@ -3,7 +3,7 @@ module Spec
3
3
  class ErrorGenerator
4
4
  attr_writer :opts
5
5
 
6
- def initialize target, name
6
+ def initialize(target, name)
7
7
  @target = target
8
8
  @name = name
9
9
  end
@@ -12,27 +12,34 @@ module Spec
12
12
  @opts ||= {}
13
13
  end
14
14
 
15
- def raise_unexpected_message_error sym, *args
15
+ def raise_unexpected_message_error(sym, *args)
16
16
  __raise "#{intro} received unexpected message :#{sym}#{arg_message(*args)}"
17
17
  end
18
18
 
19
- def raise_expectation_error sym, expected_received_count, actual_received_count, *args
19
+ def raise_unexpected_message_args_error(expectation, *args)
20
+ #this is either :no_args or an Array
21
+ expected_args = (expectation.expected_args == :no_args ? "(no args)" : format_args(*expectation.expected_args))
22
+ actual_args = args.empty? ? "(no args)" : format_args(*args)
23
+ __raise "#{intro} expected #{expectation.sym.inspect} with #{expected_args} but received it with #{actual_args}"
24
+ end
25
+
26
+ def raise_expectation_error(sym, expected_received_count, actual_received_count, *args)
20
27
  __raise "#{intro} expected :#{sym}#{arg_message(*args)} #{count_message(expected_received_count)}, but received it #{count_message(actual_received_count)}"
21
28
  end
22
29
 
23
- def raise_out_of_order_error sym
30
+ def raise_out_of_order_error(sym)
24
31
  __raise "#{intro} received :#{sym} out of order"
25
32
  end
26
33
 
27
- def raise_block_failed_error sym, detail
34
+ def raise_block_failed_error(sym, detail)
28
35
  __raise "#{intro} received :#{sym} but passed block failed with: #{detail}"
29
36
  end
30
37
 
31
- def raise_missing_block_error args_to_yield
38
+ def raise_missing_block_error(args_to_yield)
32
39
  __raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no block was passed"
33
40
  end
34
41
 
35
- def raise_wrong_arity_error args_to_yield, arity
42
+ def raise_wrong_arity_error(args_to_yield, arity)
36
43
  __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}"
37
44
  end
38
45
 
@@ -41,15 +48,19 @@ module Spec
41
48
  @name ? "Mock '#{@name}'" : @target.to_s
42
49
  end
43
50
 
44
- def __raise message
51
+ def __raise(message)
45
52
  message = opts[:message] unless opts[:message].nil?
46
53
  Kernel::raise(Spec::Mocks::MockExpectationError, message)
47
54
  end
48
55
 
49
- def arg_message *args
50
- return "" if [:any_args] == args
51
- return if args.empty?
52
- " with [" + arg_list(*args) + "]"
56
+ def arg_message(*args)
57
+ " with " + format_args(*args)
58
+ end
59
+
60
+ def format_args(*args)
61
+ return "(no args)" if args.empty? || args == :no_args || args == [:no_args]
62
+ return "(any args)" if [:any_args] == args
63
+ "(" + arg_list(*args) + ")"
53
64
  end
54
65
 
55
66
  def arg_list(*args)
@@ -22,6 +22,10 @@ module Spec
22
22
  @at_most = nil
23
23
  @args_to_yield = nil
24
24
  end
25
+
26
+ def expected_args
27
+ @args_expectation.args
28
+ end
25
29
 
26
30
  def and_return(*values, &return_block)
27
31
  Kernel::raise AmbiguousReturnError unless @method_block.nil?
@@ -41,14 +41,11 @@ module Spec
41
41
  end
42
42
 
43
43
  def __add expected_from, sym, block
44
- Runner::Specification.add_listener(self) if @options[:auto_verify]
44
+ current_spec = Runner::Specification.current
45
+ current_spec.after_teardown {verify} if current_spec && @options[:auto_verify]
45
46
  define_expected_method(sym)
46
47
  end
47
48
 
48
- def spec_finished spec
49
- verify
50
- end
51
-
52
49
  def define_expected_method(sym)
53
50
  if @target.respond_to?(sym) && !@proxied_methods[sym]
54
51
  @proxied_methods[sym] = @target.method(sym)
@@ -106,7 +103,7 @@ module Spec
106
103
  @proxied_methods.clear
107
104
  end
108
105
 
109
- def metaclass_eval str
106
+ def metaclass_eval(str)
110
107
  (class << @target; self; end).class_eval str
111
108
  end
112
109
 
@@ -137,13 +134,17 @@ module Spec
137
134
  elsif stub = find_matching_method_stub(sym)
138
135
  stub.invoke([], nil)
139
136
  elsif expectation = find_almost_matching_expectation(sym, *args)
140
- raise_unexpected_message_error(sym, *args) unless has_negative_expectation?(sym) unless null_object?
137
+ raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(sym) unless null_object?
141
138
  else
142
139
  @target.send :method_missing, sym, *args, &block
143
140
  end
144
141
  end
145
142
 
146
- def raise_unexpected_message_error sym, *args
143
+ def raise_unexpected_message_args_error(expectation, *args)
144
+ @error_generator.raise_unexpected_message_args_error expectation, *args
145
+ end
146
+
147
+ def raise_unexpected_message_error(sym, *args)
147
148
  @error_generator.raise_unexpected_message_error sym, *args
148
149
  end
149
150
 
@@ -12,8 +12,9 @@ module Spec
12
12
  #
13
13
  # Example:
14
14
  #
15
- # Rake::SpecTask.new do |t|
15
+ # Spec::Rake::SpecTask.new do |t|
16
16
  # t.warning = true
17
+ # t.rcov = true
17
18
  # end
18
19
  #
19
20
  # This will create a task that can be run with:
@@ -11,6 +11,5 @@ require 'spec/runner/backtrace_tweaker'
11
11
  require 'spec/runner/reporter'
12
12
  require 'spec/runner/spec_matcher'
13
13
  require 'spec/runner/extensions/kernel'
14
- require 'spec/runner/extensions/object'
15
14
  require 'spec/runner/spec_should_raise_handler'
16
15
  require 'spec/runner/spec_parser'
@@ -29,6 +29,7 @@ module Spec
29
29
  line = nil if line =~ /\/lib\/spec\/mocks\//
30
30
  line = nil if line =~ /\/lib\/spec\/rake\//
31
31
  line = nil if line =~ /\/lib\/spec\/runner\//
32
+ line = nil if line =~ /\/lib\/spec\/callback\//
32
33
  line = nil if line =~ /bin\/spec:/
33
34
  line = nil if line =~ /bin\/rcov:/
34
35
  line = nil if line =~ /lib\/rspec_on_rails/
@@ -98,7 +98,7 @@ module Spec
98
98
  if part.is_a?(UnboundMethod)
99
99
  part.bind(self).call
100
100
  else
101
- instance_exec(&part)
101
+ instance_eval(&part)
102
102
  end
103
103
  end
104
104
  end
@@ -92,7 +92,7 @@ module Spec
92
92
  protected
93
93
 
94
94
  def backtrace_line(line)
95
- line
95
+ line.sub(/\A([^:]+:\d+)$/, '\\1:')
96
96
  end
97
97
 
98
98
  def colour(text, colour_code)
@@ -4,83 +4,98 @@ module Spec
4
4
  class HtmlFormatter < BaseTextFormatter
5
5
  def initialize(output, dry_run=false, colour=false)
6
6
  super
7
- @current_count = 0
8
- @spec_count = 0
7
+ @current_spec_number = 0
8
+ @current_context_number = 0
9
9
  end
10
-
10
+
11
11
  def start(spec_count)
12
12
  @spec_count = spec_count
13
-
14
- @output.puts HEADER
13
+
14
+ @output.puts @@header
15
15
  STDOUT.flush
16
16
  end
17
17
 
18
18
  def add_context(name, first)
19
+ @current_context_number += 1
19
20
  unless first
20
- @output.puts " </ul>"
21
+ @output.puts " </dl>"
21
22
  @output.puts "</div>"
22
23
  end
23
24
  @output.puts "<div class=\"context\">"
24
- @output.puts " <ul>"
25
- @output.puts " <li class=\"context_name\">#{name}</li>"
25
+ @output.puts " <dl>"
26
+ @output.puts " <dt id=\"context_#{@current_context_number}\">#{name}</dt>"
26
27
  STDOUT.flush
27
28
  end
28
29
 
29
30
  def start_dump
30
- @output.puts " </ul>"
31
+ @output.puts " </dl>"
31
32
  @output.puts "</div>"
32
33
  STDOUT.flush
33
34
  end
34
35
 
35
36
  def spec_started(name)
36
37
  @current_spec = name
37
- @current_count += 1
38
+ @current_spec_number += 1
38
39
  STDOUT.flush
39
40
  end
40
41
 
41
42
  def spec_passed(name)
42
43
  move_progress
43
- @output.puts " <li class=\"spec passed\"><div class=\"passed_spec_name\">#{escape(@current_spec)}</div></li>"
44
+ @output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{escape(@current_spec)}</span></dd>"
44
45
  STDOUT.flush
45
46
  end
46
47
 
47
48
  def spec_failed(name, counter, failure)
48
- @output.puts " <script type=\"text/javascript\">makeProgressbarRed();</script>"
49
+ @output.puts " <script type=\"text/javascript\">makeRed('header');</script>"
50
+ @output.puts " <script type=\"text/javascript\">makeRed('context_#{@current_context_number}');</script>"
49
51
  move_progress
50
- @output.puts " <li class=\"spec failed\">"
51
- @output.puts " <div class=\"failed_spec_name\">#{escape(@current_spec)}</div>"
52
+ @output.puts " <dd class=\"spec failed\">"
53
+ @output.puts " <span class=\"failed_spec_name\">#{escape(@current_spec)}</span>"
52
54
  @output.puts " <div class=\"failure\" id=\"failure_#{counter}\">"
53
55
  @output.puts " <div class=\"message\"><pre>#{escape(failure.exception.message)}</pre></div>" unless failure.exception.nil?
54
56
  @output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil?
57
+ extra_failure_content
55
58
  @output.puts " </div>"
56
- @output.puts " </li>"
59
+ @output.puts " </dd>"
57
60
  STDOUT.flush
58
61
  end
59
62
 
63
+ # Override this method if you wish to output extra HTML for a failed spec. For example, you
64
+ # could output links to images or other files produced during the specs. Example:
65
+ #
66
+ #
67
+ def extra_failure_content
68
+ end
69
+
60
70
  def move_progress
61
- percent_done = @spec_count == 0 ? 100.0 : (@current_count.to_f / @spec_count.to_f * 1000).to_i / 10.0
71
+ percent_done = @spec_count == 0 ? 100.0 : (@current_spec_number.to_f / @spec_count.to_f * 1000).to_i / 10.0
62
72
  @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
63
73
  end
64
74
 
65
75
  def escape(string)
66
76
  string.gsub(/&/n, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
67
77
  end
68
-
78
+
69
79
  def dump_failure(counter, failure)
70
80
  end
71
81
 
72
82
  def dump_summary(duration, spec_count, failure_count)
83
+ if @dry_run
84
+ totals = "This was a dry-run"
85
+ else
86
+ totals = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
87
+ end
88
+ @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
89
+ @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
90
+ @output.puts "</div>"
73
91
  @output.puts "</body>"
74
92
  @output.puts "</html>"
75
93
  STDOUT.flush
76
94
  end
77
-
78
- RED_BACKGROUND = '#CD0000'
79
- GREEN_BACKGROUND = '#659D32'
80
-
81
- HEADER = <<-HEADER
95
+
96
+ @@header = <<-HEADER
82
97
  <?xml version="1.0" encoding="iso-8859-1"?>
83
- <!DOCTYPE html
98
+ <!DOCTYPE html
84
99
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
85
100
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
86
101
 
@@ -91,98 +106,103 @@ module Spec
91
106
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
92
107
  <script type="text/javascript">
93
108
  function moveProgressBar(percentDone) {
94
- document.getElementById("progress-bar").style.width = percentDone +"%";
109
+ document.getElementById("header").style.width = percentDone +"%";
95
110
  }
96
- function makeProgressbarRed() {
97
- document.getElementById('progress-bar').style.background = '#{RED_BACKGROUND}';
111
+ function makeRed(element_id) {
112
+ document.getElementById(element_id).style.background = '#C40D0D';
98
113
  }
99
114
  </script>
100
115
  <style type="text/css">
101
116
  body {
102
- font-size: 9pt;
103
- font-family: verdana, arial, helvetica;
104
- width: 85%;
117
+ margin: 0; padding: 0;
118
+ background: #fff;
105
119
  }
106
120
 
107
- #progress-bar-bg {
108
- background-color: #C9C9C9;
109
- border-bottom: 1px solid gray;
110
- border-right: 1px solid gray;
121
+ #header {
122
+ background: #65C400; color: #fff;
111
123
  }
112
124
 
113
- #progress-bar {
114
- background-color: #{GREEN_BACKGROUND};
115
- width: 0px;
125
+ h1 {
126
+ margin: 0 0 10px;
127
+ padding: 10px;
128
+ font: bold 18px "Lucida Grande", Helvetica, sans-serif;
116
129
  }
117
130
 
118
- div.context {
119
- padding: 0px;
120
- background: #fff;
121
- margin-top: 0px;
131
+ #summary {
132
+ margin: 0; padding: 5px 10px;
133
+ font: bold 10px "Lucida Grande", Helvetica, sans-serif;
134
+ text-align: right;
135
+ position: absolute;
136
+ top: 0px;
137
+ right: 0px;
122
138
  }
123
139
 
124
- ul {
125
- padding-left: 0px;
140
+ #summary p {
141
+ margin: 0 0 2px;
126
142
  }
127
143
 
128
- li {
129
- list-style-type: none;
130
- margin: 0;
131
- border: 1px solid #fff;
144
+ #summary #totals {
145
+ font-size: 14px;
132
146
  }
133
147
 
134
- li.context_name {
135
- font-size: 1.3em;
136
- font-weight: bold;
137
- color: #589CCF;
148
+ .context {
149
+ margin: 0 10px 5px;
150
+ background: #fff;
138
151
  }
139
152
 
140
- div.passed_spec_name {
141
- font-weight: bold;
142
- color: #324F17;
153
+ dl {
154
+ margin: 0; padding: 0 0 5px;
155
+ font: normal 11px "Lucida Grande", Helvetica, sans-serif;
143
156
  }
144
157
 
145
- div.failed_spec_name {
158
+ dt {
159
+ padding: 3px;
160
+ background: #65C400;
161
+ color: #fff;
146
162
  font-weight: bold;
147
- color: #EEB4B4;
148
163
  }
149
164
 
150
- li.passed {
151
- display: block;
152
- background: #659D32;
153
- padding: 1px 4px;
165
+ dd {
166
+ margin: 5px 0 5px 5px;
167
+ padding: 3px 3px 3px 18px;
154
168
  }
155
169
 
156
- li.failed {
157
- display: block;
158
- background: #CD0000;
159
- color: #000;
160
- padding: 2px 4px;
170
+ dd.spec.passed {
171
+ border-left: 5px solid #65C400;
172
+ border-bottom: 1px solid #65C400;
173
+ background: #DBFFB4; color: #3D7700;
161
174
  }
162
175
 
163
- li.failed .failure {
164
- font-weight: normal;
165
- font-size: 9pt;
176
+ dd.spec.failed {
177
+ border-left: 5px solid #C20000;
178
+ border-bottom: 1px solid #C20000;
179
+ color: #C20000; background: #FFFBD3;
166
180
  }
167
181
 
168
182
  div.backtrace {
169
- color: #fff;
183
+ color: #000;
184
+ font-size: 12px;
170
185
  }
171
186
 
172
- div.backtrace a {
173
- color: #fff;
187
+ a {
188
+ color: #BE5C00;
174
189
  }
175
-
176
190
  </style>
177
191
  </head>
178
192
  <body>
179
193
 
180
- <div id="progress-bar-bg">
181
- <div id="progress-bar">&nbsp;</div>
194
+ <div id="header">
195
+ <h1>RSpec Results</h1>
196
+
197
+ <div id="summary">
198
+ <p id="duration">&nbsp;</p>
199
+ <p id="totals">&nbsp;</p>
200
+ </div>
182
201
  </div>
183
202
 
203
+ <div id="results">
184
204
  HEADER
185
205
  end
186
206
  end
187
207
  end
188
- end
208
+ end