rspec-html-formatter 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +34 -0
- data/LICENSE +21 -0
- data/README.md +14 -0
- data/lib/splithtml_formatter.rb +243 -0
- data/lib/splithtml_printer.rb +468 -0
- data/spec/sample_spec.rb +77 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
data.tar.gz: 0dd65d1010a89ba0f5ebb54f14b40099310af6bf3be752aaa93173675f5e32988c698be05af7e0d49c38140649a44c0d35b07e20295b5ceb1c24c3318fa61f21
|
4
|
+
metadata.gz: d5060bf391258f7f076e66fe1a115904591ce627b10982b5dfe264fe0ebb48d4aa71a517c774630d7975a48a39cd6eaa674da0ce0e4a798dfe7004d5cb59fe5b
|
5
|
+
SHA1:
|
6
|
+
data.tar.gz: ff4abded4f4c8a74dfac637847b09f7b270ef9ae
|
7
|
+
metadata.gz: 8c3d3802576d723af7fb84ab36f96388aec5435c
|
data/.gitignore
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Chen Hai Quan
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
rspec-html-formator
|
2
|
+
===================
|
3
|
+
|
4
|
+
Extended html formator for rspec. It create seperate html file for each rspec test script.
|
5
|
+
It is useful when you have large number of rspec testcases with different owners.
|
6
|
+
|
7
|
+
### how to use
|
8
|
+
```
|
9
|
+
gem install rspec-html-formatter
|
10
|
+
rspec spec/sample_spec.rb -f SplithtmlFormatter -r splithtml_formatter -r splithtml_printer
|
11
|
+
```
|
12
|
+
|
13
|
+
### Dependence
|
14
|
+
rspec 2.14
|
@@ -0,0 +1,243 @@
|
|
1
|
+
require 'rspec/core/formatters/base_text_formatter'
|
2
|
+
|
3
|
+
PREFIX = "spec"
|
4
|
+
|
5
|
+
class FileOutput
|
6
|
+
|
7
|
+
def initialize(file_name)
|
8
|
+
@f = File.open(file_name, "w")
|
9
|
+
end
|
10
|
+
|
11
|
+
def puts(text)
|
12
|
+
@f.puts(text)
|
13
|
+
end
|
14
|
+
|
15
|
+
def flush()
|
16
|
+
@f.flush()
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
class SplithtmlFormatter < RSpec::Core::Formatters::BaseTextFormatter
|
22
|
+
|
23
|
+
def initialize(output)
|
24
|
+
super(output)
|
25
|
+
@example_group_number = 0
|
26
|
+
@example_number = 0
|
27
|
+
@failure_number = 0
|
28
|
+
@pending_number = 0
|
29
|
+
@header_red = nil
|
30
|
+
@run_time = 0.0
|
31
|
+
@test_file_name = ""
|
32
|
+
@start_time = 0.0
|
33
|
+
@end_time = 0.0
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def method_missing(m, *a, &b)
|
39
|
+
end
|
40
|
+
|
41
|
+
def new_html(description)
|
42
|
+
debug_print("description:" + description)
|
43
|
+
basename = "#{description.gsub(/[^a-zA-Z0-9]+/, '-')}"
|
44
|
+
max_filename_size = (ENV['MAX_FILENAME_SIZE'] || 2**8).to_i
|
45
|
+
basename = basename[0..max_filename_size] if basename.length > max_filename_size
|
46
|
+
debug_print("basename:" + basename)
|
47
|
+
basedir = ENV['HTML_REPORTS'] || File.expand_path("#{Dir.getwd}/#{PREFIX.downcase}/reports")
|
48
|
+
debug_print("basedir:" + basedir)
|
49
|
+
FileUtils.mkdir_p(basedir)
|
50
|
+
full_path = "#{basedir}/#{PREFIX.upcase}-#{basename}"
|
51
|
+
debug_print("full_path:" + full_path)
|
52
|
+
suffix = "html"
|
53
|
+
filename = [full_path, suffix].join(".")
|
54
|
+
i = 0
|
55
|
+
while File.exists?(filename) && i < 2**15
|
56
|
+
filename = [full_path, i, suffix].join(".")
|
57
|
+
i += 1
|
58
|
+
end
|
59
|
+
debug_print("filename:" + filename)
|
60
|
+
file_out_put = FileOutput.new(filename)
|
61
|
+
return SplitHtmlPrinter.new(file_out_put)
|
62
|
+
end
|
63
|
+
|
64
|
+
public
|
65
|
+
|
66
|
+
def message(message)
|
67
|
+
end
|
68
|
+
|
69
|
+
def start(example_count)
|
70
|
+
super(example_count)
|
71
|
+
end
|
72
|
+
|
73
|
+
def example_group_started(example_group)
|
74
|
+
super(example_group)
|
75
|
+
@start_time = Time.now().to_f()
|
76
|
+
@example_number = 0
|
77
|
+
@failure_number = 0
|
78
|
+
@pending_number = 0
|
79
|
+
@header_red = false
|
80
|
+
@run_time = 0.0
|
81
|
+
@example_group_red = false
|
82
|
+
@example_group_number += 1
|
83
|
+
test_file_name = File.basename(example_group.metadata[:example_group][:file_path])
|
84
|
+
@printer = new_html(example_group.description.to_s)
|
85
|
+
@printer.print_html_start(test_file_name)
|
86
|
+
@printer.print_example_group_start(example_group.description)
|
87
|
+
@printer.flush()
|
88
|
+
debug_print("start:" + @printer.object_id.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
def example_group_finished(example_group)
|
92
|
+
super(example_group)
|
93
|
+
@printer.print_example_group_end()
|
94
|
+
test_file_path = File.expand_path(example_group.metadata[:example_group][:file_path])
|
95
|
+
@end_time = Time.now().to_f()
|
96
|
+
@printer.print_summary(false, @run_time, @example_number, @failure_number, @pending_number, test_file_path, @start_time, @end_time)
|
97
|
+
@printer.flush()
|
98
|
+
debug_print("finished:" + @printer.object_id.to_s)
|
99
|
+
end
|
100
|
+
|
101
|
+
def example_started(example)
|
102
|
+
super(example)
|
103
|
+
@example_number += 1
|
104
|
+
@printer.print_example_start()
|
105
|
+
end
|
106
|
+
|
107
|
+
def example_passed(example)
|
108
|
+
@printer.move_progress(100)
|
109
|
+
@printer.print_example_passed( example.description, example.execution_result[:run_time] )
|
110
|
+
@printer.flush()
|
111
|
+
@run_time += example.execution_result[:run_time]
|
112
|
+
end
|
113
|
+
|
114
|
+
def example_failed(example)
|
115
|
+
super(example)
|
116
|
+
|
117
|
+
unless @header_red
|
118
|
+
@header_red = true
|
119
|
+
@printer.make_header_red
|
120
|
+
end
|
121
|
+
|
122
|
+
unless @example_group_red
|
123
|
+
@example_group_red = true
|
124
|
+
@printer.make_example_group_header_red(0)
|
125
|
+
end
|
126
|
+
|
127
|
+
@printer.move_progress(100)
|
128
|
+
|
129
|
+
exception = example.metadata[:execution_result][:exception]
|
130
|
+
exception_details = if exception
|
131
|
+
{
|
132
|
+
:message => exception.message,
|
133
|
+
:backtrace => format_backtrace(exception.backtrace, example).join("\n")
|
134
|
+
}
|
135
|
+
else
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
extra = extra_failure_content(exception)
|
140
|
+
|
141
|
+
@printer.print_example_failed(
|
142
|
+
example.execution_result[:pending_fixed],
|
143
|
+
example.description,
|
144
|
+
example.execution_result[:run_time],
|
145
|
+
@failed_examples.size,
|
146
|
+
exception_details,
|
147
|
+
(extra == "") ? false : extra,
|
148
|
+
true
|
149
|
+
)
|
150
|
+
|
151
|
+
@printer.flush()
|
152
|
+
@failure_number += 1
|
153
|
+
@run_time += example.execution_result[:run_time]
|
154
|
+
end
|
155
|
+
|
156
|
+
def example_pending(example)
|
157
|
+
@printer.make_header_yellow unless @header_red
|
158
|
+
@printer.make_example_group_header_yellow(example_group_number) unless @example_group_red
|
159
|
+
@printer.move_progress(100)
|
160
|
+
@printer.print_example_pending( example.description, example.metadata[:execution_result][:pending_message] )
|
161
|
+
@printer.flush()
|
162
|
+
@pending_number += 1
|
163
|
+
@run_time += example.execution_result[:run_time]
|
164
|
+
end
|
165
|
+
|
166
|
+
def example_step_started(example, type, message, options)
|
167
|
+
example_started(example)
|
168
|
+
end
|
169
|
+
|
170
|
+
def example_step_passed(example, type, message, options)
|
171
|
+
@printer.move_progress(100)
|
172
|
+
@printer.print_example_passed( type.to_s().upcase() + ' ' + message, 0 )
|
173
|
+
@printer.flush()
|
174
|
+
end
|
175
|
+
|
176
|
+
def example_step_failed(example, type, message, options)
|
177
|
+
|
178
|
+
unless @header_red
|
179
|
+
@header_red = true
|
180
|
+
@printer.make_header_red
|
181
|
+
end
|
182
|
+
|
183
|
+
unless @example_group_red
|
184
|
+
@example_group_red = true
|
185
|
+
@printer.make_example_group_header_red(0)
|
186
|
+
end
|
187
|
+
|
188
|
+
@printer.move_progress(100)
|
189
|
+
|
190
|
+
exception = example.metadata[:execution_result][:exception]
|
191
|
+
exception_details = if exception
|
192
|
+
{
|
193
|
+
:message => exception.message,
|
194
|
+
:backtrace => format_backtrace(exception.backtrace, example).join("\n")
|
195
|
+
}
|
196
|
+
else
|
197
|
+
false
|
198
|
+
end
|
199
|
+
|
200
|
+
@printer.print_example_failed(
|
201
|
+
example.execution_result[:pending_fixed],
|
202
|
+
type.to_s().upcase() + ' ' + message,
|
203
|
+
0,
|
204
|
+
@failed_examples.size,
|
205
|
+
exception_details,
|
206
|
+
false,
|
207
|
+
true
|
208
|
+
)
|
209
|
+
|
210
|
+
@printer.flush()
|
211
|
+
@failure_number += 1
|
212
|
+
end
|
213
|
+
|
214
|
+
def example_step_pending(example, type, message, options)
|
215
|
+
@printer.make_header_yellow unless @header_red
|
216
|
+
@printer.make_example_group_header_yellow(example_group_number) unless @example_group_red
|
217
|
+
@printer.move_progress(100)
|
218
|
+
@printer.print_example_pending( type.to_s().upcase() + ' ' + message, '')
|
219
|
+
@printer.flush()
|
220
|
+
@pending_number += 1
|
221
|
+
end
|
222
|
+
|
223
|
+
def extra_failure_content(exception)
|
224
|
+
require 'rspec/core/formatters/snippet_extractor'
|
225
|
+
backtrace = exception.backtrace.map {|line| backtrace_line(line)}
|
226
|
+
backtrace.compact!
|
227
|
+
@snippet_extractor ||= RSpec::Core::Formatters::SnippetExtractor.new
|
228
|
+
" <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(backtrace)}</code></pre>"
|
229
|
+
end
|
230
|
+
|
231
|
+
def start_dump
|
232
|
+
end
|
233
|
+
|
234
|
+
def dump_failures
|
235
|
+
end
|
236
|
+
|
237
|
+
def dump_pending
|
238
|
+
end
|
239
|
+
|
240
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
@@ -0,0 +1,468 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'delegate'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
DEBUG = 0
|
6
|
+
|
7
|
+
def debug_print(msg)
|
8
|
+
if DEBUG == 1
|
9
|
+
STDOUT.puts "DEBUG: " + msg
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class SplitHtmlPrinter
|
14
|
+
|
15
|
+
include ERB::Util # for the #h method
|
16
|
+
def initialize(output)
|
17
|
+
@output = output
|
18
|
+
end
|
19
|
+
|
20
|
+
public
|
21
|
+
|
22
|
+
def print_html_start(test_file_name)
|
23
|
+
@output.puts HTML_HEADER
|
24
|
+
@output.puts "<div class=\"rspec-report\">"
|
25
|
+
@output.puts "<div id=\"rspec-header\">"
|
26
|
+
@output.puts " <div id=\"label\">"
|
27
|
+
@output.puts " <h1>#{test_file_name}</h1>"
|
28
|
+
@output.puts " </div>"
|
29
|
+
@output.puts REPORT_HEADER
|
30
|
+
end
|
31
|
+
|
32
|
+
def print_example_group_start(description)
|
33
|
+
@output.puts "<div id=\"div_group_0\" class=\"example_group passed\">"
|
34
|
+
@output.puts " <dl #{indentation_style(1)}>"
|
35
|
+
@output.puts " <dt id=\"example_group_0\" class=\"passed\">#{h(description)}</dt>"
|
36
|
+
|
37
|
+
@captured_io = StringIO.new()
|
38
|
+
$stdout = @captured_io
|
39
|
+
$stderr = @captured_io
|
40
|
+
end
|
41
|
+
|
42
|
+
def print_example_group_end()
|
43
|
+
logs = @captured_io.string
|
44
|
+
unless logs.empty?
|
45
|
+
@output.puts " <dd class=\"example passed\">"
|
46
|
+
@output.puts " <span class=\"\">after(:all)</span>"
|
47
|
+
@output.puts " <div class=\"console_log\">"
|
48
|
+
@output.puts " <pre>#{logs}</pre>"
|
49
|
+
@output.puts " </div>"
|
50
|
+
@output.puts " </dd>"
|
51
|
+
end
|
52
|
+
|
53
|
+
@output.puts " </dl>"
|
54
|
+
@output.puts "</div>"
|
55
|
+
end
|
56
|
+
|
57
|
+
def print_example_start()
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def print_example_end()
|
62
|
+
@captured_io.flush()
|
63
|
+
@captured_io.string = @captured_io.string.gsub(/</, '<')
|
64
|
+
@captured_io.string = @captured_io.string.gsub(/>/, '>')
|
65
|
+
logs = @captured_io.string.dup
|
66
|
+
@captured_io.truncate(0)
|
67
|
+
@captured_io.seek(0)
|
68
|
+
return logs
|
69
|
+
end
|
70
|
+
|
71
|
+
def print_example_passed( description, run_time )
|
72
|
+
formatted_run_time = sprintf("%.5f", run_time) if run_time
|
73
|
+
@output.puts " <dd class=\"example passed\">"
|
74
|
+
@output.puts " <span class=\"passed_spec_name\">#{h(description)}</span>"
|
75
|
+
@output.puts " <span class=\"duration\">#{formatted_run_time}s</span>"
|
76
|
+
@output.puts " <div class=\"console_log\">"
|
77
|
+
@output.puts " <pre>#{print_example_end()}</pre>"
|
78
|
+
@output.puts " </div>"
|
79
|
+
@output.puts " </dd>"
|
80
|
+
end
|
81
|
+
|
82
|
+
def print_example_failed( pending_fixed, description, run_time, failure_id, exception, extra_content, escape_backtrace = false )
|
83
|
+
formatted_run_time = 0
|
84
|
+
formatted_run_time = sprintf("%.5f", run_time) if run_time
|
85
|
+
|
86
|
+
@output.puts " <dd class=\"example #{pending_fixed ? 'pending_fixed' : 'failed'}\">"
|
87
|
+
@output.puts " <span class=\"failed_spec_name\">#{h(description)}</span>"
|
88
|
+
@output.puts " <span class=\"duration\">#{formatted_run_time}s</span>"
|
89
|
+
|
90
|
+
@output.puts " <div class=\"console_log\">"
|
91
|
+
@output.puts " <pre>#{print_example_end()}</pre>"
|
92
|
+
@output.puts " </div>"
|
93
|
+
|
94
|
+
@output.puts " <div class=\"failure\" id=\"failure_#{failure_id}\">"
|
95
|
+
if exception
|
96
|
+
@output.puts " <div class=\"message\"><pre>#{h(exception[:message])}</pre></div>"
|
97
|
+
if escape_backtrace
|
98
|
+
@output.puts " <div class=\"backtrace\"><pre>#{h exception[:backtrace]}</pre></div>"
|
99
|
+
else
|
100
|
+
@output.puts " <div class=\"backtrace\"><pre>#{exception[:backtrace]}</pre></div>"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
@output.puts extra_content if extra_content
|
104
|
+
@output.puts " </div>"
|
105
|
+
@output.puts " </dd>"
|
106
|
+
end
|
107
|
+
|
108
|
+
def print_example_pending( description, pending_message )
|
109
|
+
@output.puts " <dd class=\"example not_implemented\">"
|
110
|
+
@output.puts " <span class=\"not_implemented_spec_name\">#{h(description)} (PENDING: #{h(pending_message)})</span>"
|
111
|
+
@output.puts " <div class=\"console_log\">"
|
112
|
+
@output.puts " <pre>#{print_example_end()}</pre>"
|
113
|
+
@output.puts " </div>"
|
114
|
+
@output.puts " </dd>"
|
115
|
+
end
|
116
|
+
|
117
|
+
def print_summary( was_dry_run, duration, example_count, failure_count, pending_count, test_path, start_time, end_time)
|
118
|
+
totals = "#{example_count} example#{'s' unless example_count == 1}, "
|
119
|
+
totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
|
120
|
+
totals << ", #{pending_count} pending" if pending_count > 0
|
121
|
+
formatted_duration = sprintf("%.5f", duration)
|
122
|
+
@output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{formatted_duration} seconds</strong>\";</script>"
|
123
|
+
@output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
|
124
|
+
|
125
|
+
if failure_count != 0
|
126
|
+
@output.puts "<p status=\"failed\"><span style=\"visibility:hidden\">#{failure_count}</span></p>"
|
127
|
+
elsif pending_count != 0
|
128
|
+
@output.puts "<p status=\"pending\"><span style=\"visibility:hidden\">#{pending_count}</span></p>"
|
129
|
+
else
|
130
|
+
@output.puts "<p status=\"passed\"><span style=\"visibility:hidden\">#{example_count}</span></p>"
|
131
|
+
end
|
132
|
+
@output.puts "<p test_file_path=#{test_path}><span style=\"visibility:hidden\"></span></p>"
|
133
|
+
print_start_time(start_time)
|
134
|
+
print_end_time(end_time)
|
135
|
+
@output.puts "</div>"
|
136
|
+
@output.puts "</div>"
|
137
|
+
@output.puts "</body>"
|
138
|
+
@output.puts "</html>"
|
139
|
+
end
|
140
|
+
|
141
|
+
def print_start_time(time)
|
142
|
+
@output.puts "<p time=\"start_time\"><span style=\"visibility:hidden\">#{time}</span></p>"
|
143
|
+
end
|
144
|
+
|
145
|
+
def print_end_time(time)
|
146
|
+
@output.puts "<p time=\"end_time\"><span style=\"visibility:hidden\">#{time}</span></p>"
|
147
|
+
end
|
148
|
+
|
149
|
+
def flush
|
150
|
+
@output.flush
|
151
|
+
end
|
152
|
+
|
153
|
+
def move_progress( percent_done )
|
154
|
+
@output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
|
155
|
+
@output.flush
|
156
|
+
end
|
157
|
+
|
158
|
+
def make_header_red
|
159
|
+
@output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>"
|
160
|
+
end
|
161
|
+
|
162
|
+
def make_header_yellow
|
163
|
+
@output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>"
|
164
|
+
end
|
165
|
+
|
166
|
+
def make_example_group_header_red(group_id)
|
167
|
+
@output.puts " <script type=\"text/javascript\">makeRed('div_group_#{group_id}');</script>"
|
168
|
+
@output.puts " <script type=\"text/javascript\">makeRed('example_group_#{group_id}');</script>"
|
169
|
+
end
|
170
|
+
|
171
|
+
def make_example_group_header_yellow(group_id)
|
172
|
+
@output.puts " <script type=\"text/javascript\">makeYellow('div_group_#{group_id}');</script>"
|
173
|
+
@output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{group_id}');</script>"
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def indentation_style( number_of_parents )
|
179
|
+
"style=\"margin-left: #{(number_of_parents - 1) * 15}px;\""
|
180
|
+
end
|
181
|
+
|
182
|
+
REPORT_HEADER = <<-EOF
|
183
|
+
<div id="display-filters">
|
184
|
+
<input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="1" /> <label for="passed_checkbox">Passed</label>
|
185
|
+
<input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="2" /> <label for="failed_checkbox">Failed</label>
|
186
|
+
<input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked="checked" onchange="apply_filters()" value="3" /> <label for="pending_checkbox">Pending</label>
|
187
|
+
</div>
|
188
|
+
|
189
|
+
<div id="summary">
|
190
|
+
<p id="totals"> </p>
|
191
|
+
<p id="duration"> </p>
|
192
|
+
</div>
|
193
|
+
</div>
|
194
|
+
|
195
|
+
|
196
|
+
<div class="results">
|
197
|
+
EOF
|
198
|
+
|
199
|
+
GLOBAL_SCRIPTS = <<-EOF
|
200
|
+
|
201
|
+
function addClass(element_id, classname) {
|
202
|
+
document.getElementById(element_id).className += (" " + classname);
|
203
|
+
}
|
204
|
+
|
205
|
+
function removeClass(element_id, classname) {
|
206
|
+
var elem = document.getElementById(element_id);
|
207
|
+
var classlist = elem.className.replace(classname,'');
|
208
|
+
elem.className = classlist;
|
209
|
+
}
|
210
|
+
|
211
|
+
function moveProgressBar(percentDone) {
|
212
|
+
document.getElementById("rspec-header").style.width = percentDone +"%";
|
213
|
+
}
|
214
|
+
|
215
|
+
function makeRed(element_id) {
|
216
|
+
removeClass(element_id, 'passed');
|
217
|
+
removeClass(element_id, 'not_implemented');
|
218
|
+
addClass(element_id,'failed');
|
219
|
+
}
|
220
|
+
|
221
|
+
function makeYellow(element_id) {
|
222
|
+
var elem = document.getElementById(element_id);
|
223
|
+
if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed
|
224
|
+
if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented
|
225
|
+
removeClass(element_id, 'passed');
|
226
|
+
addClass(element_id,'not_implemented');
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
function apply_filters() {
|
232
|
+
var passed_filter = document.getElementById('passed_checkbox').checked;
|
233
|
+
var failed_filter = document.getElementById('failed_checkbox').checked;
|
234
|
+
var pending_filter = document.getElementById('pending_checkbox').checked;
|
235
|
+
|
236
|
+
assign_display_style("example passed", passed_filter);
|
237
|
+
assign_display_style("example failed", failed_filter);
|
238
|
+
assign_display_style("example not_implemented", pending_filter);
|
239
|
+
|
240
|
+
}
|
241
|
+
|
242
|
+
function get_display_style(display_flag) {
|
243
|
+
var style_mode = 'none';
|
244
|
+
if (display_flag == true) {
|
245
|
+
style_mode = 'block';
|
246
|
+
}
|
247
|
+
return style_mode;
|
248
|
+
}
|
249
|
+
|
250
|
+
function assign_display_style(classname, display_flag) {
|
251
|
+
var style_mode = get_display_style(display_flag);
|
252
|
+
var elems = document.getElementsByClassName(classname)
|
253
|
+
for (var i=0; i<elems.length;i++) {
|
254
|
+
elems[i].style.display = style_mode;
|
255
|
+
}
|
256
|
+
}
|
257
|
+
|
258
|
+
EOF
|
259
|
+
|
260
|
+
GLOBAL_STYLES = <<-EOF
|
261
|
+
#rspec-header {
|
262
|
+
background: #65C400; color: #fff; height: 4em;
|
263
|
+
}
|
264
|
+
|
265
|
+
.rspec-report h1 {
|
266
|
+
margin: 0px 10px 0px 10px;
|
267
|
+
padding: 10px;
|
268
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
269
|
+
font-size: 1.8em;
|
270
|
+
position: absolute;
|
271
|
+
}
|
272
|
+
|
273
|
+
#label {
|
274
|
+
float:left;
|
275
|
+
}
|
276
|
+
|
277
|
+
#display-filters {
|
278
|
+
float:left;
|
279
|
+
padding: 28px 0 0 40%;
|
280
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
281
|
+
}
|
282
|
+
|
283
|
+
#summary {
|
284
|
+
float:right;
|
285
|
+
padding: 5px 10px;
|
286
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
287
|
+
text-align: right;
|
288
|
+
}
|
289
|
+
|
290
|
+
#summary p {
|
291
|
+
margin: 0 0 0 2px;
|
292
|
+
}
|
293
|
+
|
294
|
+
#summary #totals {
|
295
|
+
font-size: 1.2em;
|
296
|
+
}
|
297
|
+
|
298
|
+
.example_group {
|
299
|
+
margin: 0 10px 5px;
|
300
|
+
background: #fff;
|
301
|
+
}
|
302
|
+
|
303
|
+
dl {
|
304
|
+
margin: 0; padding: 0 0 5px;
|
305
|
+
font: normal 11px "Lucida Grande", Helvetica, sans-serif;
|
306
|
+
}
|
307
|
+
|
308
|
+
dt {
|
309
|
+
padding: 3px;
|
310
|
+
background: #65C400;
|
311
|
+
color: #fff;
|
312
|
+
font-weight: bold;
|
313
|
+
}
|
314
|
+
|
315
|
+
dd {
|
316
|
+
margin: 5px 0 5px 5px;
|
317
|
+
padding: 3px 3px 3px 18px;
|
318
|
+
font-size: 12px;
|
319
|
+
}
|
320
|
+
|
321
|
+
dd .duration {
|
322
|
+
padding-left: 5px;
|
323
|
+
text-align: right;
|
324
|
+
right: 0px;
|
325
|
+
float:right;
|
326
|
+
}
|
327
|
+
|
328
|
+
dd .console_log {
|
329
|
+
background-color:#000000;
|
330
|
+
color: #FFFFFF;
|
331
|
+
font-size: 9px;
|
332
|
+
}
|
333
|
+
|
334
|
+
dd.example.passed {
|
335
|
+
border-left: 5px solid #65C400;
|
336
|
+
border-bottom: 1px solid #65C400;
|
337
|
+
background: #DBFFB4; color: #3D7700;
|
338
|
+
}
|
339
|
+
|
340
|
+
dd.example.not_implemented {
|
341
|
+
border-left: 5px solid #FAF834;
|
342
|
+
border-bottom: 1px solid #FAF834;
|
343
|
+
background: #FCFB98; color: #131313;
|
344
|
+
}
|
345
|
+
|
346
|
+
dd.example.pending_fixed {
|
347
|
+
border-left: 5px solid #0000C2;
|
348
|
+
border-bottom: 1px solid #0000C2;
|
349
|
+
color: #0000C2; background: #D3FBFF;
|
350
|
+
}
|
351
|
+
|
352
|
+
dd.example.failed {
|
353
|
+
border-left: 5px solid #C20000;
|
354
|
+
border-bottom: 1px solid #C20000;
|
355
|
+
color: #C20000; background: #FFFBD3;
|
356
|
+
}
|
357
|
+
|
358
|
+
|
359
|
+
dt.not_implemented {
|
360
|
+
color: #000000; background: #FAF834;
|
361
|
+
}
|
362
|
+
|
363
|
+
dt.pending_fixed {
|
364
|
+
color: #FFFFFF; background: #C40D0D;
|
365
|
+
}
|
366
|
+
|
367
|
+
dt.failed {
|
368
|
+
color: #FFFFFF; background: #C40D0D;
|
369
|
+
}
|
370
|
+
|
371
|
+
|
372
|
+
#rspec-header.not_implemented {
|
373
|
+
color: #000000; background: #FAF834;
|
374
|
+
}
|
375
|
+
|
376
|
+
#rspec-header.pending_fixed {
|
377
|
+
color: #FFFFFF; background: #C40D0D;
|
378
|
+
}
|
379
|
+
|
380
|
+
#rspec-header.failed {
|
381
|
+
color: #FFFFFF; background: #C40D0D;
|
382
|
+
}
|
383
|
+
|
384
|
+
|
385
|
+
.backtrace {
|
386
|
+
color: #000;
|
387
|
+
font-size: 12px;
|
388
|
+
}
|
389
|
+
|
390
|
+
a {
|
391
|
+
color: #BE5C00;
|
392
|
+
}
|
393
|
+
|
394
|
+
pre {
|
395
|
+
white-space: pre-wrap; /* css-3 */
|
396
|
+
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
397
|
+
white-space: -pre-wrap; /* Opera 4-6 */
|
398
|
+
white-space: -o-pre-wrap; /* Opera 7 */
|
399
|
+
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
400
|
+
}
|
401
|
+
|
402
|
+
/* Ruby code, style similar to vibrant ink */
|
403
|
+
.ruby {
|
404
|
+
font-size: 12px;
|
405
|
+
font-family: monospace;
|
406
|
+
color: white;
|
407
|
+
background-color: black;
|
408
|
+
padding: 0.1em 0 0.2em 0;
|
409
|
+
}
|
410
|
+
|
411
|
+
.ruby .keyword { color: #FF6600; }
|
412
|
+
.ruby .constant { color: #339999; }
|
413
|
+
.ruby .attribute { color: white; }
|
414
|
+
.ruby .global { color: white; }
|
415
|
+
.ruby .module { color: white; }
|
416
|
+
.ruby .class { color: white; }
|
417
|
+
.ruby .string { color: #66FF00; }
|
418
|
+
.ruby .ident { color: white; }
|
419
|
+
.ruby .method { color: #FFCC00; }
|
420
|
+
.ruby .number { color: white; }
|
421
|
+
.ruby .char { color: white; }
|
422
|
+
.ruby .comment { color: #9933CC; }
|
423
|
+
.ruby .symbol { color: white; }
|
424
|
+
.ruby .regex { color: #44B4CC; }
|
425
|
+
.ruby .punct { color: white; }
|
426
|
+
.ruby .escape { color: white; }
|
427
|
+
.ruby .interp { color: white; }
|
428
|
+
.ruby .expr { color: white; }
|
429
|
+
|
430
|
+
.ruby .offending { background-color: gray; }
|
431
|
+
.ruby .linenum {
|
432
|
+
width: 75px;
|
433
|
+
padding: 0.1em 1em 0.2em 0;
|
434
|
+
color: #000000;
|
435
|
+
background-color: #FFFBD3;
|
436
|
+
}
|
437
|
+
EOF
|
438
|
+
|
439
|
+
HTML_HEADER = <<-EOF
|
440
|
+
<!DOCTYPE html>
|
441
|
+
<html lang='en'>
|
442
|
+
<head>
|
443
|
+
<title>RSpec results</title>
|
444
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
445
|
+
<meta http-equiv="Expires" content="-1" />
|
446
|
+
<meta http-equiv="Pragma" content="no-cache" />
|
447
|
+
<style type="text/css">
|
448
|
+
body {
|
449
|
+
margin: 0;
|
450
|
+
padding: 0;
|
451
|
+
background: #fff;
|
452
|
+
font-size: 80%;
|
453
|
+
}
|
454
|
+
</style>
|
455
|
+
<script type="text/javascript">
|
456
|
+
// <![CDATA[
|
457
|
+
#{GLOBAL_SCRIPTS}
|
458
|
+
// ]]>
|
459
|
+
</script>
|
460
|
+
<style type="text/css">
|
461
|
+
#{GLOBAL_STYLES}
|
462
|
+
</style>
|
463
|
+
</head>
|
464
|
+
<body>
|
465
|
+
EOF
|
466
|
+
|
467
|
+
end
|
468
|
+
|
data/spec/sample_spec.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
describe "All passed cases test" do
|
4
|
+
before(:all) do
|
5
|
+
puts "this line must exist before all test in All passed cases test"
|
6
|
+
end
|
7
|
+
it "passed test1" do
|
8
|
+
puts "this line from passed test1"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "passed test2" do
|
12
|
+
puts "this line from passed test2"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "Two failed cases test" do
|
18
|
+
|
19
|
+
it "failed test1" do
|
20
|
+
puts "this line from failed test1"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "failed test2" do
|
24
|
+
puts "this line from failed test2"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "passed test2" do
|
28
|
+
puts "this line from passed test2"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "after and before" do
|
34
|
+
after(:all) do
|
35
|
+
puts "this line must exist after all test"
|
36
|
+
end
|
37
|
+
|
38
|
+
before(:all) do
|
39
|
+
puts "this line must exist before all test"
|
40
|
+
end
|
41
|
+
|
42
|
+
after(:each) do
|
43
|
+
puts "this line must exist after each test"
|
44
|
+
end
|
45
|
+
|
46
|
+
before(:each) do
|
47
|
+
puts "this line must exist before each test"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "passed test4" do
|
51
|
+
puts "this line from passed test4"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "passed test5" do
|
55
|
+
puts "this line from passed test5"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "Logger test" do
|
61
|
+
|
62
|
+
before(:all) do
|
63
|
+
@log = Logger.new($stdout)
|
64
|
+
@log.level = Logger::INFO
|
65
|
+
end
|
66
|
+
|
67
|
+
it "passed test6" do
|
68
|
+
puts "this line from passed test6"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "passed test7" do
|
72
|
+
puts "this line from passed test7"
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-html-formatter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- chenhaiq
|
8
|
+
- Zhang Yuan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2014-09-16 00:00:00 Z
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Extended html formator for rspec. It create seperate html file for each rspec test script.
|
17
|
+
email: chocean@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- LICENSE
|
27
|
+
- README.md
|
28
|
+
- lib/splithtml_formatter.rb
|
29
|
+
- lib/splithtml_printer.rb
|
30
|
+
- spec/sample_spec.rb
|
31
|
+
homepage: https://github.com/chenhaiq/rspec-html-formatter
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
metadata: {}
|
35
|
+
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- &id001
|
44
|
+
- ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- *id001
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 2.0.14
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: create seperate html file for each rspec script
|
57
|
+
test_files: []
|
58
|
+
|