report_builder 0.0.6 → 0.0.7
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.
- checksums.yaml +4 -4
- data/README.md +20 -6
- data/bin/report_builder +2 -1
- data/lib/report_builder.rake +3 -4
- data/lib/report_builder.rb +189 -26
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 601a48967da3d12319d801c9febed718aa5a856a
|
4
|
+
data.tar.gz: 253cda6a5c4fc55185f11789ac6c8892296a0008
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: faa57482fbc784b5d48d30a64fd67b6533acff31077cd5d7e630d6a7689584871442f13b36061f531a6987a54471f6470d082bb78bde259e235ad6d48b3203e9
|
7
|
+
data.tar.gz: fcf99dddafcf2f6c177304bf4c52fde0197d4933e5c91bf5d3613eb992d70747ac41e4b21a46606227539d2c12a1aa3222ac420f11b096bb65f153aa77f20e48
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# ReportBuilder
|
2
|
+
[](https://badge.fury.io/rb/report_builder)
|
3
|
+
|
2
4
|
Ruby gem to merge Cucumber JSON reports and build single HTML Test Report
|
3
5
|
|
4
6
|
## Installation
|
@@ -23,10 +25,14 @@ gem install report_builder
|
|
23
25
|
require 'report_builder'
|
24
26
|
|
25
27
|
# 1
|
28
|
+
ReportBuilder.build_report()
|
26
29
|
ReportBuilder.build_report('path/of/json/files/dir')
|
30
|
+
ReportBuilder.build_report('path/of/json/files/dir','my_test_report_name','json_html')
|
31
|
+
ReportBuilder.build_report('path/of/json/files/dir','my_test_report_name','json')
|
32
|
+
ReportBuilder.build_report('path/of/json/files/dir','my_test_report_name','html')
|
27
33
|
|
28
34
|
# 2
|
29
|
-
ReportBuilder.build_report('path/of/json/cucumber.json'
|
35
|
+
ReportBuilder.build_report('path/of/json/cucumber.json')
|
30
36
|
|
31
37
|
# 3
|
32
38
|
ReportBuilder.build_report([
|
@@ -36,30 +42,38 @@ gem install report_builder
|
|
36
42
|
])
|
37
43
|
|
38
44
|
# 4
|
39
|
-
ReportBuilder.build_report()
|
40
|
-
|
41
|
-
# 5
|
42
45
|
ReportBuilder::COLOR[:passed] = '#ffffff'
|
46
|
+
ReportBuilder::COLOR[:failed] = '#000000'
|
43
47
|
ReportBuilder.build_report()
|
44
48
|
```
|
45
49
|
|
46
50
|
### Command Example:
|
47
51
|
|
48
52
|
```bash
|
53
|
+
report_builder
|
54
|
+
report_builder 'path/of/json/files/dir'
|
49
55
|
report_builder 'path/of/json/files/dir' 'report_file'
|
56
|
+
report_builder 'path/of/json/files/dir' 'report_file' 'json_html'
|
57
|
+
report_builder 'path/of/json/files/dir' 'report_file' 'json'
|
58
|
+
report_builder 'path/of/json/files/dir' 'report_file' 'html'
|
50
59
|
```
|
51
60
|
|
52
61
|
### Rake Example:
|
53
62
|
|
63
|
+
Add in Rakefile
|
54
64
|
```ruby
|
55
|
-
# Add in Rakefile
|
56
65
|
require 'report_builder'
|
57
66
|
load 'report_builder.rake'
|
58
|
-
# Then run rake task report_builder
|
59
67
|
```
|
68
|
+
Then run rake task report_builder
|
60
69
|
|
61
70
|
```bash
|
71
|
+
rake report_builder
|
72
|
+
rake report_builder ['path/of/json/files/dir']
|
62
73
|
rake report_builder ['path/of/json/files/dir','report_file']
|
74
|
+
rake report_builder ['path/of/json/files/dir','report_file','json_html']
|
75
|
+
rake report_builder ['path/of/json/files/dir','report_file','json']
|
76
|
+
rake report_builder ['path/of/json/files/dir','report_file','html']
|
63
77
|
```
|
64
78
|
|
65
79
|
## Contributing
|
data/bin/report_builder
CHANGED
data/lib/report_builder.rake
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
desc 'Rake task to build report'
|
2
|
-
task :report_builder, [:file_or_dir, :output_file_name] do |t, args|
|
3
|
-
args.with_defaults(:file_or_dir => nil, :output_file_name => 'test_report')
|
4
|
-
|
5
|
-
ReportBuilder.build_report args.file_or_dir, args.output_file_name
|
2
|
+
task :report_builder, [:file_or_dir, :output_file_name, :output_file_type] do |t, args|
|
3
|
+
args.with_defaults(:file_or_dir => nil, :output_file_name => 'test_report', :output_file_type => 'html')
|
4
|
+
ReportBuilder.build_report args.file_or_dir, args.output_file_name, args.output_file_type
|
6
5
|
end
|
data/lib/report_builder.rb
CHANGED
@@ -43,10 +43,21 @@ class ReportBuilder
|
|
43
43
|
|
44
44
|
# @param [Object] file_or_dir json file, array of json files or path, json files path
|
45
45
|
# @param [String] output_file_name Output file name, by default test_report
|
46
|
-
|
46
|
+
# @param [String] output_file_type Output file type, by default html, other options json and json_html
|
47
|
+
def self.build_report(file_or_dir = nil, output_file_name = 'test_report', output_file_type = 'html')
|
47
48
|
|
48
49
|
input = files file_or_dir
|
49
50
|
all_features = features input rescue (raise 'ReportBuilderParsingError')
|
51
|
+
|
52
|
+
if output_file_type.include? 'json'
|
53
|
+
File.open(output_file_name + '.json', "w") do |file|
|
54
|
+
file.write JSON.pretty_generate all_features
|
55
|
+
end
|
56
|
+
puts "JSON test report generated: '#{output_file_name}.json'"
|
57
|
+
end
|
58
|
+
|
59
|
+
return unless output_file_type.include? 'html'
|
60
|
+
|
50
61
|
all_scenarios = scenarios all_features
|
51
62
|
all_steps = steps all_scenarios
|
52
63
|
total_time = total_time all_features
|
@@ -129,7 +140,7 @@ class ReportBuilder
|
|
129
140
|
all_features.each_with_index do |feature, n|
|
130
141
|
builder.h3 do
|
131
142
|
builder.span(:class => feature['status']) do
|
132
|
-
builder << "<strong>#{feature['keyword']}</strong> #{feature['name']} (#{
|
143
|
+
builder << "<strong>#{feature['keyword']}</strong> #{feature['name']} (#{duration(feature['duration'])})"
|
133
144
|
end
|
134
145
|
end
|
135
146
|
builder.div do
|
@@ -137,16 +148,31 @@ class ReportBuilder
|
|
137
148
|
feature['elements'].each do |scenario|
|
138
149
|
builder.h3 do
|
139
150
|
builder.span(:class => scenario['status']) do
|
140
|
-
builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{
|
151
|
+
builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{duration(scenario['duration'])})"
|
141
152
|
end
|
142
153
|
end
|
143
154
|
builder.div do
|
155
|
+
scenario['before'].each do |before|
|
156
|
+
if before['status'] == 'failed'
|
157
|
+
builder << "<strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
158
|
+
error = before['result']['error_message'].split("\n")
|
159
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
160
|
+
error[0..-2].each do |line|
|
161
|
+
builder << line + '<br/>'
|
162
|
+
end
|
163
|
+
end
|
164
|
+
builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
|
165
|
+
end
|
166
|
+
end
|
144
167
|
scenario['steps'].each do |step|
|
145
168
|
builder.span(:class => step['status']) do
|
146
|
-
builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{
|
169
|
+
builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{duration(step['duration'])})"
|
147
170
|
end
|
148
|
-
|
149
|
-
builder << "<br
|
171
|
+
step['output'].each do |output|
|
172
|
+
builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
|
173
|
+
end if step['output'] && step['output'].is_a?(Array)
|
174
|
+
if step['status'] == 'failed' && step['result']['error_message']
|
175
|
+
builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
150
176
|
error = step['result']['error_message'].split("\n")
|
151
177
|
builder.span(:style => "color:#{COLOR[:failed]}") do
|
152
178
|
error[0..-3].each do |line|
|
@@ -156,8 +182,39 @@ class ReportBuilder
|
|
156
182
|
builder << "<strong>SD: </strong>#{error[-2]} <br/>"
|
157
183
|
builder << "<strong>FF: </strong>#{error[-1]}"
|
158
184
|
end
|
185
|
+
step['after'].each do |after|
|
186
|
+
after['output'].each do |output|
|
187
|
+
builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
|
188
|
+
end if after['output'] && after['output'].is_a?(Array)
|
189
|
+
if after['result']['error_message']
|
190
|
+
builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
191
|
+
error = after['result']['error_message'].split("\n")
|
192
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
193
|
+
(scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
|
194
|
+
builder << line + '<br/>'
|
195
|
+
end
|
196
|
+
end
|
197
|
+
builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
|
198
|
+
builder << "<strong>FF: </strong>#{error[-2]} <br/>"
|
199
|
+
end
|
200
|
+
end if step['after']
|
159
201
|
builder << '<br/>'
|
160
202
|
end
|
203
|
+
scenario['after'].each do |after|
|
204
|
+
after['output'].each do |output|
|
205
|
+
builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
|
206
|
+
end if after['output'] && after['output'].is_a?(Array)
|
207
|
+
if after['status'] == 'failed'
|
208
|
+
builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
209
|
+
error = after['result']['error_message'].split("\n")
|
210
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
211
|
+
error[0..-2].each do |line|
|
212
|
+
builder << line + '<br/>'
|
213
|
+
end
|
214
|
+
end
|
215
|
+
builder << "<strong>Hook: </strong>#{error[-1]}"
|
216
|
+
end
|
217
|
+
end
|
161
218
|
end
|
162
219
|
end
|
163
220
|
end
|
@@ -180,16 +237,31 @@ class ReportBuilder
|
|
180
237
|
data[1].each do |scenario|
|
181
238
|
builder.h3 do
|
182
239
|
builder.span(:class => data[0]) do
|
183
|
-
builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{
|
240
|
+
builder << "<strong>#{scenario['keyword']}</strong> #{scenario['name']} (#{duration(scenario['duration'])})"
|
184
241
|
end
|
185
242
|
end
|
186
243
|
builder.div do
|
244
|
+
scenario['before'].each do |before|
|
245
|
+
if before['status'] == 'failed'
|
246
|
+
builder << "<strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
247
|
+
error = before['result']['error_message'].split("\n")
|
248
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
249
|
+
error[0..-2].each do |line|
|
250
|
+
builder << line + '<br/>'
|
251
|
+
end
|
252
|
+
end
|
253
|
+
builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
|
254
|
+
end
|
255
|
+
end
|
187
256
|
scenario['steps'].each do |step|
|
188
257
|
builder.span(:class => step['status']) do
|
189
|
-
builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{
|
258
|
+
builder << "<strong>#{step['keyword']}</strong> #{step['name']} (#{duration(step['duration'])})"
|
190
259
|
end
|
191
|
-
|
192
|
-
builder << "<br
|
260
|
+
step['output'].each do |output|
|
261
|
+
builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
|
262
|
+
end if step['output'] && step['output'].is_a?(Array)
|
263
|
+
if step['status'] == 'failed' && step['result']['error_message']
|
264
|
+
builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
193
265
|
error = step['result']['error_message'].split("\n")
|
194
266
|
builder.span(:style => "color:#{COLOR[:failed]}") do
|
195
267
|
error[0..-3].each do |line|
|
@@ -199,8 +271,39 @@ class ReportBuilder
|
|
199
271
|
builder << "<strong>SD: </strong>#{error[-2]} <br/>"
|
200
272
|
builder << "<strong>FF: </strong>#{error[-1]}"
|
201
273
|
end
|
274
|
+
step['after'].each do |after|
|
275
|
+
after['output'].each do |output|
|
276
|
+
builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
|
277
|
+
end if after['output'] && after['output'].is_a?(Array)
|
278
|
+
if after['result']['error_message']
|
279
|
+
builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
280
|
+
error = after['result']['error_message'].split("\n")
|
281
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
282
|
+
(scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
|
283
|
+
builder << line + '<br/>'
|
284
|
+
end
|
285
|
+
end
|
286
|
+
builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
|
287
|
+
builder << "<strong>FF: </strong>#{error[-2]} <br/>"
|
288
|
+
end
|
289
|
+
end if step['after']
|
202
290
|
builder << '<br>'
|
203
291
|
end
|
292
|
+
scenario['after'].each do |after|
|
293
|
+
after['output'].each do |output|
|
294
|
+
builder << "<br/> <span style='color:#{COLOR[:skipped]}'>#{output}</span>"
|
295
|
+
end if after['output'] && after['output'].is_a?(Array)
|
296
|
+
if after['status'] == 'failed'
|
297
|
+
builder << "<br/><strong style=color:#{COLOR[:failed]}>Error: </strong>"
|
298
|
+
error = after['result']['error_message'].split("\n")
|
299
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
300
|
+
error[0..-2].each do |line|
|
301
|
+
builder << line + '<br/>'
|
302
|
+
end
|
303
|
+
end
|
304
|
+
builder << "<strong>Hook: </strong>#{error[-1]}"
|
305
|
+
end
|
306
|
+
end
|
204
307
|
end
|
205
308
|
end
|
206
309
|
end
|
@@ -212,17 +315,58 @@ class ReportBuilder
|
|
212
315
|
|
213
316
|
builder.div(:id => 'errorsTab') do
|
214
317
|
builder.ol do
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
318
|
+
all_scenarios.each do |scenario|
|
319
|
+
scenario['before'].each do |before|
|
320
|
+
next unless before['status'] == 'failed'
|
321
|
+
builder.li do
|
322
|
+
error = before['result']['error_message'].split("\n")
|
323
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
324
|
+
error[0..-2].each do |line|
|
325
|
+
builder << line + '<br/>'
|
326
|
+
end
|
222
327
|
end
|
328
|
+
builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
|
329
|
+
builder << "<strong>Scenario: </strong>#{scenario['name']}"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
scenario['steps'].each do |step|
|
333
|
+
step['after'].each do |after|
|
334
|
+
next unless after['status'] == 'failed'
|
335
|
+
builder.li do
|
336
|
+
error = after['result']['error_message'].split("\n")
|
337
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
338
|
+
(scenario['keyword'] == 'Scenario Outline' ? error[0..-6] : error[0..-4]).each do |line|
|
339
|
+
builder << line + '<br/>'
|
340
|
+
end
|
341
|
+
end
|
342
|
+
builder << "<strong>Hook: </strong>#{scenario['keyword'] == 'Scenario Outline' ? error[-5] : error[-3]} <br/>"
|
343
|
+
builder << "<strong>FF: </strong>#{error[-2]} <br/>"
|
344
|
+
end
|
345
|
+
end if step['after']
|
346
|
+
next unless step['status'] == 'failed' && step['result']['error_message']
|
347
|
+
builder.li do
|
348
|
+
error = step['result']['error_message'].split("\n")
|
349
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
350
|
+
error[0..-3].each do |line|
|
351
|
+
builder << line + '<br/>'
|
352
|
+
end
|
353
|
+
end
|
354
|
+
builder << "<strong>SD: </strong>#{error[-2]} <br/>"
|
355
|
+
builder << "<strong>FF: </strong>#{error[-1]}"
|
356
|
+
end
|
357
|
+
end
|
358
|
+
scenario['after'].each do |after|
|
359
|
+
next unless after['status'] == 'failed'
|
360
|
+
builder.li do
|
361
|
+
error = after['result']['error_message'].split("\n")
|
362
|
+
builder.span(:style => "color:#{COLOR[:failed]}") do
|
363
|
+
error[0..-2].each do |line|
|
364
|
+
builder << line + '<br/>'
|
365
|
+
end
|
366
|
+
end
|
367
|
+
builder << "<strong>Hook: </strong>#{error[-1]} <br/>"
|
368
|
+
builder << "<strong>Scenario: </strong>#{scenario['name']}"
|
223
369
|
end
|
224
|
-
builder << "<strong>SD: </strong>#{error[-2]} <br/>"
|
225
|
-
builder << "<strong>FF: </strong>#{error[-1]}"
|
226
370
|
end
|
227
371
|
end
|
228
372
|
end
|
@@ -242,7 +386,8 @@ class ReportBuilder
|
|
242
386
|
|
243
387
|
file.close
|
244
388
|
|
245
|
-
puts "
|
389
|
+
puts "HTML test report generated: '#{output_file_name}.html'"
|
390
|
+
[total_time, feature_data, scenario_data, step_data]
|
246
391
|
end
|
247
392
|
|
248
393
|
def self.features(files)
|
@@ -254,11 +399,29 @@ class ReportBuilder
|
|
254
399
|
features << group.first.except('elements').merge('elements' => group.map{|feature| feature['elements']}.flatten)
|
255
400
|
}.each{|feature|
|
256
401
|
feature['elements'].each { |scenario|
|
402
|
+
scenario['before'] ||= []
|
403
|
+
scenario['before'].each { |before|
|
404
|
+
before['result']['duration'] ||= 0
|
405
|
+
before.merge! 'status' => before['result']['status'], 'duration' => before['result']['duration']
|
406
|
+
}
|
257
407
|
scenario['steps'].each { |step|
|
258
408
|
step['result']['duration'] ||= 0
|
259
|
-
|
409
|
+
duration = step['result']['duration']
|
410
|
+
status = step['result']['status']
|
411
|
+
step['after'].each { |after|
|
412
|
+
after['result']['duration'] ||= 0
|
413
|
+
duration += after['result']['duration']
|
414
|
+
status = 'failed' if after['result']['status'] == 'failed'
|
415
|
+
after.merge! 'status' => after['result']['status'], 'duration' => after['result']['duration']
|
416
|
+
} if step['after']
|
417
|
+
step.merge! 'status' => status, 'duration' => duration
|
418
|
+
}
|
419
|
+
scenario['after'] ||= []
|
420
|
+
scenario['after'].each { |after|
|
421
|
+
after['result']['duration'] ||= 0
|
422
|
+
after.merge! 'status' => after['result']['status'], 'duration' => after['result']['duration']
|
260
423
|
}
|
261
|
-
scenario.merge! 'status' => scenario_status(scenario), 'duration' => total_time(scenario['steps'])
|
424
|
+
scenario.merge! 'status' => scenario_status(scenario), 'duration' => total_time(scenario['before']) + total_time(scenario['steps']) + total_time(scenario['after'])
|
262
425
|
}
|
263
426
|
feature.merge! 'status' => feature_status(feature), 'duration' => total_time(feature['elements'])
|
264
427
|
}
|
@@ -281,7 +444,7 @@ class ReportBuilder
|
|
281
444
|
end
|
282
445
|
|
283
446
|
def self.scenario_status(scenario)
|
284
|
-
scenario['steps'].each do |step|
|
447
|
+
(scenario['before'] + scenario['steps'] + scenario['after']).each do |step|
|
285
448
|
status = step['status']
|
286
449
|
return status unless status == 'passed'
|
287
450
|
end
|
@@ -312,9 +475,9 @@ class ReportBuilder
|
|
312
475
|
|
313
476
|
def self.data(all_data)
|
314
477
|
all_data.group_by{|db| db['status']}.map do |data|
|
315
|
-
|
316
|
-
|
317
|
-
|
478
|
+
{name: data[0],
|
479
|
+
count: data[1].size,
|
480
|
+
color: COLOR[data[0].to_sym]}
|
318
481
|
end
|
319
482
|
end
|
320
483
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: report_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rajat Thareja
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: builder
|