rspec 0.5.12 → 0.5.13
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.
- data/CHANGES +9 -1
- data/README +2 -2
- data/Rakefile +13 -5
- data/examples/custom_formatter.rb +2 -2
- data/examples/file_accessor.rb +18 -0
- data/examples/file_accessor_spec.rb +38 -0
- data/examples/io_processor.rb +8 -0
- data/examples/io_processor_spec.rb +21 -0
- data/lib/spec/api/exceptions.rb +3 -0
- data/lib/spec/api/mocks/message_expectation.rb +45 -29
- data/lib/spec/api/mocks/mock.rb +1 -1
- data/lib/spec/api/mocks/order_group.rb +1 -1
- data/lib/spec/runner.rb +1 -5
- data/lib/spec/runner/formatter.rb +5 -0
- data/lib/spec/runner/formatter/base_text_formatter.rb +79 -0
- data/lib/spec/runner/formatter/html_formatter.rb +156 -0
- data/lib/spec/runner/formatter/progress_bar_formatter.rb +27 -0
- data/lib/spec/runner/formatter/rdoc_formatter.rb +22 -0
- data/lib/spec/runner/formatter/specdoc_formatter.rb +22 -0
- data/lib/spec/runner/option_parser.rb +17 -17
- data/lib/spec/runner/reporter.rb +1 -1
- data/lib/spec/version.rb +1 -1
- data/test/spec/api/helper/arbitrary_predicate_test.rb +38 -38
- data/test/spec/api/helper/diff_test.rb +1 -1
- data/test/spec/api/helper/identity_test.rb +17 -10
- data/test/spec/api/helper/{equality_test.rb → object_equality_test.rb} +15 -29
- data/test/spec/api/helper/regex_matching_test.rb +7 -9
- data/test/spec/api/helper/throwing_test.rb +11 -12
- data/test/spec/api/helper/true_false_special_case_test.rb +15 -17
- data/test/spec/api/helper/typing_test.rb +27 -26
- data/test/spec/api/mocks/mock_arg_constraints_test.rb +1 -1
- data/test/spec/api/mocks/mock_test.rb +45 -11
- data/test/spec/api/mocks/null_object_test.rb +3 -3
- data/test/spec/runner/context_matching_test.rb +2 -2
- data/test/spec/runner/formatter/failure_dump_test.rb +94 -0
- data/test/spec/runner/formatter/html_formatter_test.rb +48 -0
- data/test/spec/runner/formatter/progress_bar_formatter_test.rb +56 -0
- data/test/spec/runner/formatter/rdoc_formatter_test.rb +51 -0
- data/test/spec/runner/formatter/specdoc_formatter_test.rb +57 -0
- data/test/spec/runner/kernel_ext_test.rb +1 -1
- data/test/spec/runner/option_parser_test.rb +22 -12
- data/test/spec/runner/reporter_test.rb +1 -1
- data/test/test_classes.rb +7 -7
- metadata +19 -14
- data/lib/spec/runner/base_text_formatter.rb +0 -77
- data/lib/spec/runner/html_formatter.rb +0 -153
- data/lib/spec/runner/progress_bar_formatter.rb +0 -25
- data/lib/spec/runner/rdoc_formatter.rb +0 -20
- data/lib/spec/runner/specdoc_formatter.rb +0 -20
- data/test/spec/runner/failure_dump_test.rb +0 -92
- data/test/spec/runner/html_formatter_test.rb +0 -47
- data/test/spec/runner/progress_bar_formatter_test.rb +0 -54
- data/test/spec/runner/rdoc_formatter_test.rb +0 -50
- data/test/spec/runner/specdoc_formatter_test.rb +0 -55
data/CHANGES
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
= RSpec Changelog
|
2
2
|
|
3
|
+
== Version 0.5.13
|
4
|
+
This release fixes some subtle bugs in the mock API.
|
5
|
+
|
6
|
+
* Use fully-qualified class name of Exceptions in failure message. Easier to debug that way.
|
7
|
+
* Fixed a bug that caused mocks to yield a one-element array (rather than the element) when one yield arg specified.
|
8
|
+
* Mocks not raise AmbiguousReturnError if an explicit return is used at the same time as an expectation block.
|
9
|
+
* Blocks passed to yielding mocks can now raise without causing mock verification to fail.
|
10
|
+
|
3
11
|
== Version 0.5.12
|
4
12
|
This release adds diff support for failure messages, a HTML formatter plus some other
|
5
13
|
minor enhancements.
|
6
14
|
|
7
15
|
* Added HTML formatter.
|
8
16
|
* Added fail_on_error option to spectask.
|
9
|
-
* Added support for diffing, using the lcs
|
17
|
+
* Added support for diffing, using the diff-lcs Rubygem (#2648).
|
10
18
|
* Remove RSpec on Rails files from backtrace (#4694).
|
11
19
|
* All of RSpec's own tests run successfully after translation with test2spec.
|
12
20
|
* Added --verbose mode for test2spec - useful for debugging when classes fail to translate.
|
data/README
CHANGED
@@ -8,12 +8,12 @@ Then you must install the following gems:
|
|
8
8
|
* webgen
|
9
9
|
* RedCloth
|
10
10
|
* syntax
|
11
|
-
* lcs
|
11
|
+
* diff-lcs
|
12
12
|
|
13
13
|
Note that RSpec itself - once built - doesn't have any dependencies outside the Ruby core
|
14
14
|
and stdlib - with a few exceptions:
|
15
15
|
|
16
|
-
* The spec command line uses lcs
|
16
|
+
* The spec command line uses diff-lcs when --diff is specified.
|
17
17
|
* The test2spec command line uses ParseTree and RubyInline.
|
18
18
|
* The Spec::Rake::SpecTask needs RCov if RCov is enabled in the task.
|
19
19
|
|
data/Rakefile
CHANGED
@@ -32,8 +32,12 @@ Spec::Rake::SpecTask.new('failing_examples') do |t|
|
|
32
32
|
t.spec_files = FileList['failing_examples/**/*_spec.rb']
|
33
33
|
end
|
34
34
|
|
35
|
+
require 'rbconfig'
|
36
|
+
windows = Config::CONFIG['target_os'] == 'mswin32'
|
35
37
|
Rake::TestTask.new do |t|
|
36
|
-
|
38
|
+
tests = FileList['test/**/*_test.rb']
|
39
|
+
tests.exclude 'test/spec/test_to_spec/*.rb' if windows
|
40
|
+
t.test_files = tests
|
37
41
|
t.verbose = true
|
38
42
|
end
|
39
43
|
|
@@ -44,21 +48,25 @@ Rcov::RcovTask.new do |t|
|
|
44
48
|
end
|
45
49
|
|
46
50
|
desc 'Translate our own tests to specs'
|
47
|
-
task :test2spec do
|
51
|
+
task :test2spec => :create_test2spec_dir do
|
48
52
|
rm_rf 'spec/translated'
|
49
53
|
`bin/test2spec --force --template spec/test2spec.erb --specdir spec/translated test`
|
50
54
|
# Remove the spec translations that we don't care about.
|
51
55
|
rm 'spec/translated/spec/test_to_spec/sexp_transformer_assertion_spec.rb'
|
52
56
|
rm 'spec/translated/spec/test_to_spec/sexp_transformer_spec.rb'
|
53
57
|
end
|
58
|
+
task :create_test2spec_dir do
|
59
|
+
mkdir_p 'doc/output/tools' unless File.exist? 'doc/output/tools'
|
60
|
+
end
|
54
61
|
|
55
62
|
desc 'Runs all RSpec specs - translated with test2spec from our own tests'
|
56
63
|
Spec::Rake::SpecTask.new('test2spec_test' => :test2spec) do |t|
|
57
64
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
58
|
-
t.
|
65
|
+
t.spec_opts = ["--format", "html", "--diff"]
|
66
|
+
t.out = 'doc/output/tools/rspec_specs.html'
|
59
67
|
end
|
60
68
|
|
61
|
-
desc 'Generate HTML documentation'
|
69
|
+
desc 'Generate HTML documentation for website'
|
62
70
|
task :webgen => :test2spec do
|
63
71
|
Dir.chdir 'doc' do
|
64
72
|
output = nil
|
@@ -155,7 +163,7 @@ task :tag do
|
|
155
163
|
end
|
156
164
|
|
157
165
|
desc "Build the website with rdoc and rcov, but do not publish it"
|
158
|
-
task :website => [:clobber, :rcov_verify, :webgen, :failing_examples_with_html, :examples_specdoc, :rdoc]
|
166
|
+
task :website => [:clobber, :rcov_verify, :webgen, :failing_examples_with_html, :test2spec_test, :examples_specdoc, :rdoc]
|
159
167
|
|
160
168
|
task :verify_user do
|
161
169
|
raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'spec/runner/base_text_formatter'
|
1
|
+
require 'spec/runner/formatter/base_text_formatter'
|
2
2
|
|
3
3
|
# Example of a custom formatter. Run me with:
|
4
4
|
# bin/spec examples -r examples/custom_formatter.rb -f CustomFormatter
|
5
|
-
class CustomFormatter < Spec::Runner::BaseTextFormatter
|
5
|
+
class CustomFormatter < Spec::Runner::Formatter::BaseTextFormatter
|
6
6
|
def add_context(name, first)
|
7
7
|
@output << "\n" if first
|
8
8
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class FileAccessor
|
2
|
+
def open_and_handle_with(pathname, processor)
|
3
|
+
pathname.open do |io|
|
4
|
+
processor.process(io)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
if __FILE__ == $0
|
10
|
+
require File.dirname(__FILE__) + '/io_processor'
|
11
|
+
require 'pathname'
|
12
|
+
|
13
|
+
accessor = FileAccessor.new
|
14
|
+
io_processor = IoProcessor.new
|
15
|
+
file = Pathname.new ARGV[0]
|
16
|
+
|
17
|
+
accessor.open_and_handle_with(file, io_processor)
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/spec'
|
2
|
+
require File.dirname(__FILE__) + '/file_accessor'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
context "A FileAccessor" do
|
6
|
+
# This sequence diagram illustrates what this spec specifies.
|
7
|
+
#
|
8
|
+
# +--------------+ +----------+ +-------------+
|
9
|
+
# | FileAccessor | | Pathname | | IoProcessor |
|
10
|
+
# +--------------+ +----------+ +-------------+
|
11
|
+
# | | |
|
12
|
+
# open_and_handle_with | | |
|
13
|
+
# -------------------->| | open | |
|
14
|
+
# | |--------------->| | |
|
15
|
+
# | | io | | |
|
16
|
+
# | |<...............| | |
|
17
|
+
# | | | process(io) |
|
18
|
+
# | |---------------------------------->| |
|
19
|
+
# | | | | |
|
20
|
+
# | |<..................................| |
|
21
|
+
# | | |
|
22
|
+
#
|
23
|
+
specify "should open a file and pass it to the processor's process method" do
|
24
|
+
# This is the primary actor
|
25
|
+
accessor = FileAccessor.new
|
26
|
+
|
27
|
+
# These are the primary actor's neighbours, which we mock.
|
28
|
+
file = mock "Pathname"
|
29
|
+
io_processor = mock "IoProcessor"
|
30
|
+
|
31
|
+
io = StringIO.new "whatever"
|
32
|
+
file.should_receive(:open).and_yield io
|
33
|
+
io_processor.should_receive(:process).with(io)
|
34
|
+
|
35
|
+
accessor.open_and_handle_with(file, io_processor)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/spec'
|
2
|
+
require File.dirname(__FILE__) + '/io_processor'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
context "An IoProcessor" do
|
6
|
+
setup do
|
7
|
+
@processor = IoProcessor.new
|
8
|
+
end
|
9
|
+
|
10
|
+
specify "should raise nothing when the file is exactly 32 bytes" do
|
11
|
+
lambda {
|
12
|
+
@processor.process(StringIO.new("z"*32))
|
13
|
+
}.should_not_raise
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "should raise an exception when the file length is less than 32 bytes" do
|
17
|
+
lambda {
|
18
|
+
@processor.process(StringIO.new("z"*31))
|
19
|
+
}.should_raise(DataTooShort)
|
20
|
+
end
|
21
|
+
end
|
data/lib/spec/api/exceptions.rb
CHANGED
@@ -4,12 +4,12 @@ module Spec
|
|
4
4
|
# Represents the expection of the reception of a message
|
5
5
|
class MessageExpectation
|
6
6
|
|
7
|
-
def initialize(mock_name, expectation_ordering, expected_from, sym,
|
7
|
+
def initialize(mock_name, expectation_ordering, expected_from, sym, method_block)
|
8
8
|
@mock_name = mock_name
|
9
9
|
@expected_from = expected_from
|
10
10
|
@sym = sym
|
11
|
-
@method_block =
|
12
|
-
@
|
11
|
+
@method_block = method_block
|
12
|
+
@return_block = lambda {}
|
13
13
|
@received_count = 0
|
14
14
|
@expected_received_count = 1
|
15
15
|
@args_expectation = ArgumentExpectation.new([:any_args])
|
@@ -67,39 +67,54 @@ module Spec
|
|
67
67
|
end
|
68
68
|
|
69
69
|
# This method is called when a method is invoked on a mock
|
70
|
-
def
|
70
|
+
def invoke(args, block)
|
71
71
|
|
72
72
|
handle_order_constraint
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
|
74
|
+
begin
|
75
|
+
Kernel::raise @exception_to_raise.new unless @exception_to_raise.nil?
|
76
|
+
Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil?
|
77
|
+
|
78
|
+
if !@method_block.nil?
|
79
|
+
return invoke_method_block(args)
|
80
|
+
elsif !@args_to_yield.nil?
|
81
|
+
return invoke_with_yield(block)
|
82
|
+
else
|
83
|
+
return invoke_return_block(args, block)
|
79
84
|
end
|
85
|
+
ensure
|
80
86
|
@received_count += 1
|
81
|
-
return result
|
82
87
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
88
|
+
end
|
89
|
+
|
90
|
+
def invoke_method_block(args)
|
91
|
+
begin
|
92
|
+
@method_block.call(*args)
|
93
|
+
rescue Spec::Api::ExpectationNotMetError => detail
|
94
|
+
Kernel::raise Spec::Api::MockExpectationError, "Call expectation violated with: " + detail
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def invoke_with_yield(block)
|
99
|
+
if block.nil?
|
100
|
+
Kernel::raise Spec::Api::MockExpectationError, "Expected block to be passed"
|
94
101
|
end
|
102
|
+
if @args_to_yield.length != block.arity
|
103
|
+
Kernel::raise Spec::Api::MockExpectationError, "Wrong arity of passed block. Expected #{@args_to_yield.size}"
|
104
|
+
end
|
105
|
+
block.call *@args_to_yield
|
106
|
+
end
|
95
107
|
|
108
|
+
def invoke_return_block(args, block)
|
96
109
|
args << block unless block.nil?
|
97
|
-
|
98
|
-
value = @block.call(*args)
|
110
|
+
value = @return_block.call(*args)
|
99
111
|
|
100
|
-
|
101
|
-
|
102
|
-
|
112
|
+
if @consecutive
|
113
|
+
index = [@received_count, value.size-1].min
|
114
|
+
value[index]
|
115
|
+
else
|
116
|
+
value
|
117
|
+
end
|
103
118
|
end
|
104
119
|
|
105
120
|
def with(*args)
|
@@ -170,11 +185,12 @@ module Spec
|
|
170
185
|
self
|
171
186
|
end
|
172
187
|
|
173
|
-
def return(value=nil
|
188
|
+
def return(value=nil, &return_block)
|
189
|
+
Kernel::raise AmbiguousReturnError unless @method_block.nil?
|
174
190
|
return self unless @and_seen
|
175
191
|
@and_seen = false
|
176
192
|
@consecutive = value.instance_of? Array
|
177
|
-
@
|
193
|
+
@return_block = block_given? ? return_block : lambda { value }
|
178
194
|
end
|
179
195
|
|
180
196
|
def raise(exception=Exception)
|
data/lib/spec/api/mocks/mock.rb
CHANGED
@@ -35,7 +35,7 @@ module Spec
|
|
35
35
|
|
36
36
|
def method_missing(sym, *args, &block)
|
37
37
|
if expectation = find_matching_expectation(sym, *args)
|
38
|
-
expectation.
|
38
|
+
expectation.invoke(args, block)
|
39
39
|
else
|
40
40
|
begin
|
41
41
|
# act as null object if method is missing and we ignore them. return value too!
|
data/lib/spec/runner.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'spec/runner/formatter'
|
1
2
|
require 'spec/runner/instance_exec'
|
2
3
|
require 'spec/runner/context'
|
3
4
|
require 'spec/runner/specification'
|
@@ -6,9 +7,4 @@ require 'spec/runner/context_runner'
|
|
6
7
|
require 'spec/runner/option_parser'
|
7
8
|
require 'spec/runner/backtrace_tweaker'
|
8
9
|
require 'spec/runner/reporter'
|
9
|
-
require 'spec/runner/base_text_formatter'
|
10
|
-
require 'spec/runner/progress_bar_formatter'
|
11
|
-
require 'spec/runner/rdoc_formatter'
|
12
|
-
require 'spec/runner/specdoc_formatter'
|
13
|
-
require 'spec/runner/html_formatter'
|
14
10
|
require 'spec/runner/spec_matcher'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Spec
|
2
|
+
module Runner
|
3
|
+
module Formatter
|
4
|
+
# Baseclass for text-based formatters. Can in fact be used for
|
5
|
+
# non-text based ones too - just ignore the +output+ constructor
|
6
|
+
# argument.
|
7
|
+
class BaseTextFormatter
|
8
|
+
def initialize(output, dry_run=false)
|
9
|
+
@dry_run = dry_run
|
10
|
+
@output = output
|
11
|
+
end
|
12
|
+
|
13
|
+
# This method is invoked before any specs are run, right after
|
14
|
+
# they have all been collected. This can be useful for special
|
15
|
+
# formatters that need to provide progress on feedback (graphical ones)
|
16
|
+
#
|
17
|
+
# This method will only be invoked once, and the next one to be invoked
|
18
|
+
# is #add_context
|
19
|
+
def start(spec_count)
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method is invoked at the beginning of the execution of each context.
|
23
|
+
# +name+ is the name of the context and +first+ is true if it is the
|
24
|
+
# first context - otherwise it's false.
|
25
|
+
#
|
26
|
+
# The next method to be invoked after this is #spec_started
|
27
|
+
def add_context(name, first)
|
28
|
+
end
|
29
|
+
|
30
|
+
# This method is invoked right before a spec is executed.
|
31
|
+
# The next method to be invoked after this one is one of #spec_failed
|
32
|
+
# or #spec_passed.
|
33
|
+
def spec_started(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
# This method is invoked when a spec fails, i.e. an exception occurred
|
37
|
+
# inside it (such as a failed should or other exception). +name+ is the name
|
38
|
+
# of the specification. +counter+ is the sequence number of the failure
|
39
|
+
# (starting at 1) and +failure+ is the associated Failure object.
|
40
|
+
def spec_failed(name, counter, failure)
|
41
|
+
end
|
42
|
+
|
43
|
+
# This method is invoked when a spec passes. +name+ is the name of the
|
44
|
+
# specification.
|
45
|
+
def spec_passed(name)
|
46
|
+
end
|
47
|
+
|
48
|
+
# This method is invoked after all of the specs have executed. The next method
|
49
|
+
# to be invoked after this one is #dump_failure (once for each failed spec),
|
50
|
+
def start_dump
|
51
|
+
end
|
52
|
+
|
53
|
+
# Dumps detailed information about a spec failure.
|
54
|
+
# This method is invoked for each failed spec after all specs have run. +counter+ is the sequence number
|
55
|
+
# of the associated spec. +failure+ is a Failure object, which contains detailed
|
56
|
+
# information about the failure.
|
57
|
+
def dump_failure(counter, failure)
|
58
|
+
@output << "\n"
|
59
|
+
@output << counter.to_s << ")\n"
|
60
|
+
@output << "#{failure.header}\n"
|
61
|
+
@output << "#{failure.message}\n"
|
62
|
+
@output << "#{failure.backtrace}\n"
|
63
|
+
@output.flush
|
64
|
+
end
|
65
|
+
|
66
|
+
# This method is invoked at the very end.
|
67
|
+
def dump_summary(duration, spec_count, failure_count)
|
68
|
+
return if @dry_run
|
69
|
+
@output << "\n"
|
70
|
+
@output << "Finished in " << (duration).to_s << " seconds\n\n"
|
71
|
+
@output << "#{spec_count} specification#{'s' unless spec_count == 1}, "
|
72
|
+
@output << "#{failure_count} failure#{'s' unless failure_count == 1}"
|
73
|
+
@output << "\n"
|
74
|
+
@output.flush
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Spec
|
2
|
+
module Runner
|
3
|
+
module Formatter
|
4
|
+
class HtmlFormatter < BaseTextFormatter
|
5
|
+
def initialize(output, dry_run=false)
|
6
|
+
super
|
7
|
+
@current_count = 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def start(spec_count)
|
11
|
+
@spec_count = spec_count
|
12
|
+
|
13
|
+
@output.puts HEADER
|
14
|
+
@output.flush
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_context(name, first)
|
18
|
+
unless first
|
19
|
+
@output.puts " </ul>"
|
20
|
+
@output.puts "</div>"
|
21
|
+
end
|
22
|
+
@output.puts "<div class=\"context\">"
|
23
|
+
@output.puts " <div>#{name}</div>"
|
24
|
+
@output.puts " <ul>"
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_dump
|
28
|
+
@output.puts " </ul>"
|
29
|
+
@output.puts "</div>"
|
30
|
+
@output.flush
|
31
|
+
end
|
32
|
+
|
33
|
+
def spec_started(name)
|
34
|
+
@current_spec = name
|
35
|
+
@current_count += 1
|
36
|
+
end
|
37
|
+
|
38
|
+
def spec_passed(name)
|
39
|
+
@output.puts "<li class=\"spec passed\">#{escape(@current_spec)}</li>"
|
40
|
+
end
|
41
|
+
|
42
|
+
def spec_failed(name, counter, failure)
|
43
|
+
@output.puts "<li class=\"spec failed\" onclick=\"toggle('failure_#{counter}');return false;\">"
|
44
|
+
@output.puts " <div>#{escape(@current_spec)}</div>"
|
45
|
+
@output.puts " <div class=\"failure\" id=\"failure_#{counter}\" style=\"display:none\">"
|
46
|
+
@output.puts " <div><pre>#{escape(failure.header)}</pre></div>" unless failure.header == ""
|
47
|
+
@output.puts " <div><pre>#{escape(failure.message)}</pre></div>" unless failure.message == ""
|
48
|
+
@output.puts " <div><pre>#{escape(failure.backtrace)}</pre></div>" unless failure.backtrace == ""
|
49
|
+
@output.puts " </div>"
|
50
|
+
@output.puts "</li>"
|
51
|
+
@output.flush
|
52
|
+
end
|
53
|
+
|
54
|
+
def escape(string)
|
55
|
+
string.gsub(/&/n, '&').gsub(/\"/n, '"').gsub(/>/n, '>').gsub(/</n, '<')
|
56
|
+
end
|
57
|
+
|
58
|
+
def dump_failure(counter, failure)
|
59
|
+
# @output << "\n"
|
60
|
+
# @output << counter.to_s << ")\n"
|
61
|
+
# @output << "#{failure.header}\n"
|
62
|
+
# @output << "#{failure.message}\n"
|
63
|
+
# @output << "#{failure.backtrace}\n"
|
64
|
+
# @output.flush
|
65
|
+
end
|
66
|
+
|
67
|
+
def dump_summary(duration, spec_count, failure_count)
|
68
|
+
@output << "</body>"
|
69
|
+
@output << "</html>"
|
70
|
+
@output.flush
|
71
|
+
end
|
72
|
+
|
73
|
+
HEADER = <<-HEADER
|
74
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
75
|
+
<!DOCTYPE html
|
76
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
77
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
78
|
+
|
79
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
80
|
+
<head>
|
81
|
+
<title>RSpec results</title>
|
82
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
83
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
84
|
+
<style type="text/css">
|
85
|
+
body {
|
86
|
+
font-size: 10pt;
|
87
|
+
font: "lucida grande";
|
88
|
+
width: 85%;
|
89
|
+
}
|
90
|
+
|
91
|
+
ul {
|
92
|
+
padding-left: 8px;
|
93
|
+
}
|
94
|
+
|
95
|
+
li.passed {
|
96
|
+
background-color: #DDFFDD;
|
97
|
+
}
|
98
|
+
|
99
|
+
li {
|
100
|
+
list-style-type: none;
|
101
|
+
margin: 0;
|
102
|
+
}
|
103
|
+
|
104
|
+
li.failed {
|
105
|
+
background-color: #FFBBBB;
|
106
|
+
font-weight: bold;
|
107
|
+
}
|
108
|
+
|
109
|
+
li.failed:hover {
|
110
|
+
color: #FFFFFF;
|
111
|
+
background-color: #FF0000;
|
112
|
+
}
|
113
|
+
|
114
|
+
li.failed .failure {
|
115
|
+
font-weight: normal;
|
116
|
+
font-size: 9pt;
|
117
|
+
}
|
118
|
+
|
119
|
+
div.context {
|
120
|
+
padding:4px;
|
121
|
+
border:1px solid #000000;
|
122
|
+
margin-top:4px;
|
123
|
+
}
|
124
|
+
|
125
|
+
</style>
|
126
|
+
<script type="text/javascript">
|
127
|
+
// <![CDATA[
|
128
|
+
|
129
|
+
function toggle( id ) {
|
130
|
+
if ( document.getElementById )
|
131
|
+
elem = document.getElementById( id );
|
132
|
+
else if ( document.all )
|
133
|
+
elem = eval( "document.all." + id );
|
134
|
+
else
|
135
|
+
return false;
|
136
|
+
|
137
|
+
elemStyle = elem.style;
|
138
|
+
|
139
|
+
if ( elemStyle.display != "block" ) {
|
140
|
+
elemStyle.display = "block"
|
141
|
+
} else {
|
142
|
+
elemStyle.display = "none"
|
143
|
+
}
|
144
|
+
|
145
|
+
return true;
|
146
|
+
}
|
147
|
+
// ]]>
|
148
|
+
</script>
|
149
|
+
|
150
|
+
</head>
|
151
|
+
<body>
|
152
|
+
HEADER
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|