rspec 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
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