soda 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1129 @@
1
+ ###############################################################################
2
+ # Copyright (c) 2010, SugarCRM, Inc.
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ # * Redistributions of source code must retain the above copyright
8
+ # notice, this list of conditions and the following disclaimer.
9
+ # * Redistributions in binary form must reproduce the above copyright
10
+ # notice, this list of conditions and the following disclaimer in the
11
+ # documentation and/or other materials provided with the distribution.
12
+ # * Neither the name of SugarCRM, Inc. nor the
13
+ # names of its contributors may be used to endorse or promote products
14
+ # derived from this software without specific prior written permission.
15
+ #
16
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ # ARE DISCLAIMED. IN NO EVENT SHALL SugarCRM, Inc. BE LIABLE FOR ANY
20
+ # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
+ ###############################################################################
27
+
28
+ ###############################################################################
29
+ # Needed Ruby libs:
30
+ ###############################################################################
31
+ require 'rubygems'
32
+ require 'getoptlong'
33
+ require 'date'
34
+ require 'libxml'
35
+ require 'pp'
36
+ require 'SodaReportSummery'
37
+
38
+ class SodaSuiteSummary
39
+
40
+ ###############################################################################
41
+ # initialize -- constructor
42
+ # This is the class constructor. Really this does all the needed work.
43
+ #
44
+ # Params:
45
+ # dir: This is the dorectory with raw soda logs in it.
46
+ # outfile: This is the new summery html file to create.
47
+ # create_links: This will create links to the soda report files in the
48
+ # summery.
49
+ #
50
+ # Results:
51
+ # Creates a new class and html summery file. Will raise and exception on
52
+ # any errors.
53
+ #
54
+ ###############################################################################
55
+ def initialize(dir ="", outfile = "", create_links = false)
56
+ log_files = nil
57
+ report_data = nil
58
+ result = 0
59
+ html_tmp_file = ""
60
+ timout = true
61
+
62
+ if (dir.empty?)
63
+ raise "Empty 'dir' param!\n"
64
+ elsif (outfile.empty?)
65
+ raise "Empty 'outfile param!"
66
+ end
67
+
68
+ html_tmp_file = File.dirname(outfile)
69
+ html_tmp_file += "/summery.tmp"
70
+
71
+ for i in 0..120
72
+ if (!File.exist?(html_tmp_file))
73
+ timeout = false
74
+ break
75
+ end
76
+
77
+ timeout = true
78
+ sleep(1)
79
+ end
80
+
81
+ # This should go back into production after moving away from our
82
+ # internal nfs sever we are using for reporting...
83
+ #
84
+ # if (timeout != false)
85
+ # raise "Timed out waiting for lock to be released on file:"+
86
+ # " \"#{html_tmp_file}\"!\n"
87
+ # end
88
+
89
+ log_files = GetLogFiles(dir)
90
+ if ( (log_files == nil) || (log_files.length < 1) )
91
+ raise "Failed calling: GetLogFiles(#{dir})!"
92
+ end
93
+
94
+ report_data = GenerateReportData(log_files)
95
+ if (report_data.length < 1)
96
+ raise "No report data found when calling: GenerateReportData()!"
97
+ end
98
+
99
+ result = GenHtmlReport(report_data, html_tmp_file, create_links)
100
+ if (result != 0)
101
+ raise "Failed calling: GenHtmlReport()!"
102
+ end
103
+
104
+ File.rename(html_tmp_file, outfile)
105
+
106
+ end
107
+
108
+ ###############################################################################
109
+ # GetLogFiles -- method
110
+ # This function gets all the log files in a given dir puts them in a list.
111
+ #
112
+ # Params:
113
+ # dir: this is the directory that holds the log files.
114
+ #
115
+ # Results:
116
+ # returns nil on error, else a list of all the log files in the dir.
117
+ #
118
+ ###############################################################################
119
+ def GetLogFiles(dir)
120
+ files = nil
121
+
122
+ if (!File.directory?(dir))
123
+ print "(!)Error: #{dir} is not a directory!\n"
124
+ return nil
125
+ end
126
+
127
+ files = File.join("#{dir}", "*.xml")
128
+ files = Dir.glob(files)
129
+ files = files.sort()
130
+ return files
131
+ end
132
+
133
+ private :GetLogFiles
134
+
135
+ ###############################################################################
136
+ #
137
+ ###############################################################################
138
+ def GetTestInfo(kids)
139
+ test_info = {}
140
+
141
+ kids.each do |kid|
142
+ next if (kid.name =~ /text/i)
143
+ name = kid.name
144
+ name = name.gsub("_", " ")
145
+ test_info[name] = kid.content()
146
+ end
147
+
148
+ return test_info
149
+ end
150
+
151
+ ###############################################################################
152
+ # GenerateReportData -- method
153
+ # This function generates needed data from each file passed in.
154
+ #
155
+ # Params:
156
+ # files: This is a list of files to read data from.
157
+ #
158
+ # Results:
159
+ # returns an array of hashed data.
160
+ #
161
+ ###############################################################################
162
+ def GenerateReportData(files)
163
+ test_info = {}
164
+
165
+ files.each do |f|
166
+ print "(*)Opening file: #{f}\n"
167
+
168
+ begin
169
+ parser = LibXML::XML::Parser.file(f)
170
+ doc = parser.parse()
171
+ rescue Exception => e
172
+ print "(!)Error: Failed trying to parse XML file: '#{f}'!\n"
173
+ print "--)Exception: #{e.message}\n\n"
174
+ exit(1)
175
+ ensure
176
+ end
177
+
178
+ suites = []
179
+ doc.root.each do |suite|
180
+ next if (suite.name !~ /suite/)
181
+ suites.push(suite)
182
+ end
183
+
184
+ suites.each do |suite|
185
+ tmp_hash = {'tests' => []}
186
+ suite.children.each do |kid|
187
+ case (kid.name)
188
+ when "suitefile"
189
+ tmp_hash['suitefile'] = kid.content()
190
+ when "test"
191
+ tmp_test_data = GetTestInfo(kid.children)
192
+ tmp_hash['tests'].push(tmp_test_data)
193
+ end # end case #
194
+ end
195
+
196
+ base_name = File.basename(tmp_hash['suitefile'])
197
+ test_info[base_name] = tmp_hash
198
+ end
199
+ end
200
+
201
+ return test_info
202
+ end
203
+
204
+ private :GenerateReportData
205
+
206
+ ###############################################################################
207
+ # GenHtmlReport -- method
208
+ # This function generates an html report from an array of hashed data.
209
+ #
210
+ # Params:
211
+ # data: A hash of suites, and their test info.
212
+ # reportfile: This is the html file to create.
213
+ #
214
+ # Results:
215
+ # Creates an html report file. Retruns -1 on error, else 0 on success.
216
+ #
217
+ ###############################################################################
218
+ def GenHtmlReport(data, reportfile, create_links = false)
219
+ fd = nil
220
+ result = 0
221
+ totals = {}
222
+ log_file_td = ""
223
+ report_file = ""
224
+ now = nil
225
+ suite_totals = {}
226
+ total_failure_count = 0
227
+ total_non_ran_count = 0
228
+
229
+ begin
230
+ fd = File.new(reportfile, "w+")
231
+ rescue Exception => e
232
+ fd = nil
233
+ result = -1
234
+ print "Error: trying to open file!\n"
235
+ print "Exception: #{e.message}\n"
236
+ print "StackTrace: #{e.backtrace.join("\n")}\n"
237
+ ensure
238
+ if (result != 0)
239
+ return -1
240
+ end
241
+ end
242
+
243
+ now = Time.now.getlocal()
244
+ html_header = <<HTML
245
+ <html>
246
+ <style type="text/css">
247
+
248
+ .highlight {
249
+ background-color: #8888FF;
250
+ }
251
+
252
+ .unhighlight {
253
+ background: #FFFFFF;
254
+ }
255
+
256
+ .td_header_master {
257
+ whitw-space: nowrap;
258
+ background: #99CCFF;
259
+ text-align: center;
260
+ font-family: Arial;
261
+ font-weight: bold;
262
+ font-size: 12px;
263
+ border-left: 0px solid black;
264
+ border-right: 2px solid black;
265
+ border-bottom: 2px solid black;
266
+ }
267
+
268
+ .td_header_sub {
269
+ whitw-space: nowrap;
270
+ background: #99CCFF;
271
+ text-align: center;
272
+ font-family: Arial;
273
+ font-weight: bold;
274
+ font-size: 12px;
275
+ border-left: 1px solid black;
276
+ border-right: 0px solid black;
277
+ border-bottom: 2px solid black;
278
+ }
279
+
280
+ .td_header_skipped {
281
+ whitw-space: nowrap;
282
+ background: #99CCFF;
283
+ text-align: center;
284
+ font-family: Arial;
285
+ font-weight: bold;
286
+ font-size: 12px;
287
+ border-left: 1px solid black;
288
+ border-right: 2px solid black;
289
+ border-bottom: 2px solid black;
290
+ }
291
+
292
+ .td_header_watchdog {
293
+ whitw-space: nowrap;
294
+ background: #99CCFF;
295
+ text-align: center;
296
+ font-family: Arial;
297
+ font-weight: bold;
298
+ font-size: 12px;
299
+ border-left: 0px solid black;
300
+ border-right: 0px solid black;
301
+ border-bottom: 2px solid black;
302
+ }
303
+
304
+ table {
305
+ width: 100%;
306
+ border: 2px solid black;
307
+ border-collapse: collapse;
308
+ padding: 0px;
309
+ background: #FFFFFF;
310
+ }
311
+
312
+ .td_file_data {
313
+ whitw-space: nowrap;
314
+ text-align: left;
315
+ font-family: Arial;
316
+ font-weight: bold;
317
+ font-size: 12px;
318
+ border-left: 0px solid black;
319
+ border-right: 2px solid black;
320
+ border-bottom: 2px solid black;
321
+ }
322
+
323
+ .td_run_data {
324
+ whitw-space: nowrap;
325
+ text-align: center;
326
+ font-family: Arial;
327
+ font-weight: bold;
328
+ font-size: 12px;
329
+ border-left: 0px solid black;
330
+ border-right: 0px solid black;
331
+ border-bottom: 0px solid black;
332
+ }
333
+
334
+ .td_run_data_error {
335
+ whitw-space: nowrap;
336
+ text-align: center;
337
+ font-family: Arial;
338
+ font-weight: bold;
339
+ color: #FF0000;
340
+ font-size: 12px;
341
+ border-left: 0px solid black;
342
+ border-right: 0px solid black;
343
+ border-bottom: 0px solid black;
344
+ }
345
+
346
+ .td_passed_data {
347
+ whitw-space: nowrap;
348
+ text-align: center;
349
+ font-family: Arial;
350
+ font-weight: bold;
351
+ color: #00FF00;
352
+ font-size: 12px;
353
+ border-left: 0px solid black;
354
+ border-right: 0px solid black;
355
+ border-bottom: 0px solid black;
356
+ }
357
+
358
+ .td_failed_data {
359
+ whitw-space: nowrap;
360
+ text-align: center;
361
+ font-family: Arial;
362
+ font-weight: bold;
363
+ color: #FF0000;
364
+ font-size: 12px;
365
+ border-left: 0px solid black;
366
+ border-right: 0px solid black;
367
+ border-bottom: 0px solid black;
368
+ }
369
+
370
+ .td_blocked_data {
371
+ whitw-space: nowrap;
372
+ text-align: center;
373
+ font-family: Arial;
374
+ font-weight: bold;
375
+ color: #FFCF10;
376
+ font-size: 12px;
377
+ border-left: 0px solid black;
378
+ border-right: 0px solid black;
379
+ border-bottom: 0px solid black;
380
+ }
381
+
382
+ .td_skipped_data {
383
+ whitw-space: nowrap;
384
+ text-align: center;
385
+ font-family: Arial;
386
+ font-weight: bold;
387
+ color: #D9D9D9;
388
+ font-size: 12px;
389
+ border-left: 0px solid black;
390
+ border-right: 2px solid black;
391
+ border-bottom: 0px solid black;
392
+ }
393
+
394
+ .td_watchdog_data {
395
+ whitw-space: nowrap;
396
+ text-align: center;
397
+ font-family: Arial;
398
+ font-weight: normal;
399
+ font-size: 12px;
400
+ border-left: 0px solid black;
401
+ border-right: 0px solid black;
402
+ border-bottom: 0px solid black;
403
+ }
404
+
405
+ .td_watchdog_error_data {
406
+ whitw-space: nowrap;
407
+ color: #FF0000;
408
+ text-align: center;
409
+ font-family: Arial;
410
+ font-weight: bold;
411
+ font-size: 12px;
412
+ border-left: 0px solid black;
413
+ border-right: 0px solid black;
414
+ border-bottom: 0px solid black;
415
+ }
416
+
417
+ .td_exceptions_data {
418
+ whitw-space: nowrap;
419
+ text-align: center;
420
+ font-family: Arial;
421
+ font-weight: normal;
422
+ font-size: 12px;
423
+ border-left: 0px solid black;
424
+ border-right: 0px solid black;
425
+ border-bottom: 0px solid black;
426
+ }
427
+
428
+ .td_exceptions_error_data {
429
+ whitw-space: nowrap;
430
+ text-align: center;
431
+ font-family: Arial;
432
+ font-weight: bold;
433
+ color: #FF0000;
434
+ font-size: 12px;
435
+ border-left: 0px solid black;
436
+ border-right: 0px solid black;
437
+ border-bottom: 0px solid black;
438
+ }
439
+
440
+ .td_javascript_data {
441
+ whitw-space: nowrap;
442
+ text-align: center;
443
+ font-family: Arial;
444
+ font-weight: normal;
445
+ font-size: 12px;
446
+ border-left: 0px solid black;
447
+ border-right: 0px solid black;
448
+ border-bottom: 0px solid black;
449
+ }
450
+
451
+ .td_javascript_error_data {
452
+ whitw-space: nowrap;
453
+ text-align: center;
454
+ font-family: Arial;
455
+ font-weight: bold;
456
+ color: #FF0000;
457
+ font-size: 12px;
458
+ border-left: 0px solid black;
459
+ border-right: 0px solid black;
460
+ border-bottom: 0px solid black;
461
+ }
462
+
463
+ .td_assert_data {
464
+ whitw-space: nowrap;
465
+ text-align: center;
466
+ font-family: Arial;
467
+ font-weight: normal;
468
+ font-size: 12px;
469
+ border-left: 0px solid black;
470
+ border-right: 0px solid black;
471
+ border-bottom: 0px solid black;
472
+ }
473
+
474
+ .td_assert_error_data {
475
+ whitw-space: nowrap;
476
+ text-align: center;
477
+ font-family: Arial;
478
+ font-weight: bold;
479
+ color: #FF0000;
480
+ font-size: 12px;
481
+ border-left: 0px solid black;
482
+ border-right: 0px solid black;
483
+ border-bottom: 0px solid black;
484
+ }
485
+
486
+ .td_other_data {
487
+ whitw-space: nowrap;
488
+ text-align: center;
489
+ font-family: Arial;
490
+ font-weight: normal;
491
+ font-size: 12px;
492
+ border-left: 0px solid black;
493
+ border-right: 0px solid black;
494
+ border-bottom: 0px solid black;
495
+ }
496
+
497
+ .td_other_error_data {
498
+ whitw-space: nowrap;
499
+ text-align: center;
500
+ font-family: Arial;
501
+ font-weight: bold;
502
+ color: #FF0000;
503
+ font-size: 12px;
504
+ border-left: 0px solid black;
505
+ border-right: 0px solid black;
506
+ border-bottom: 0px solid black;
507
+ }
508
+
509
+ .td_total_data {
510
+ whitw-space: nowrap;
511
+ text-align: center;
512
+ font-family: Arial;
513
+ font-weight: normal;
514
+ font-size: 12px;
515
+ border-left: 0px solid black;
516
+ border-right: 2px solid black;
517
+ border-bottom: 0px solid black;
518
+ }
519
+
520
+ .td_total_error_data {
521
+ whitw-space: nowrap;
522
+ text-align: center;
523
+ font-family: Arial;
524
+ font-weight: bold;
525
+ color: #FF0000;
526
+ font-size: 12px;
527
+ border-left: 0px solid black;
528
+ border-right: 2px solid black;
529
+ border-bottom: 0px solid black;
530
+ }
531
+
532
+ .td_css_data {
533
+ whitw-space: nowrap;
534
+ text-align: center;
535
+ font-family: Arial;
536
+ font-weight: normal;
537
+ font-size: 12px;
538
+ border-left: 0px solid black;
539
+ border-right: 0px solid black;
540
+ border-bottom: 0px solid black;
541
+ }
542
+
543
+ .td_sodawarnings_data {
544
+ whitw-space: nowrap;
545
+ text-align: center;
546
+ font-family: Arial;
547
+ font-weight: normal;
548
+ font-size: 12px;
549
+ border-left: 0px solid black;
550
+ border-right: 2px solid black;
551
+ border-bottom: 0px solid black;
552
+ }
553
+
554
+ .td_time_data {
555
+ whitw-space: nowrap;
556
+ text-align: center;
557
+ font-family: Arial;
558
+ font-weight: normal;
559
+ font-size: 12px;
560
+ border-left: 0px solid black;
561
+ border-right: 1px solid black;
562
+ border-bottom: 0px solid black;
563
+ }
564
+
565
+ .td_footer_run {
566
+ whitw-space: nowrap;
567
+ background: #99CCFF;
568
+ text-align: center;
569
+ font-family: Arial;
570
+ font-weight: bold;
571
+ font-size: 12px;
572
+ color: #000000;
573
+ border-top: 2px solid black;
574
+ border-left: 0px solid black;
575
+ border-right: 2px solid black;
576
+ border-bottom: 2px solid black;
577
+ }
578
+
579
+ .td_footer_passed {
580
+ whitw-space: nowrap;
581
+ background: #99CCFF;
582
+ text-align: center;
583
+ font-family: Arial;
584
+ font-weight: bold;
585
+ font-size: 12px;
586
+ color: #00FF00;
587
+ border-top: 2px solid black;
588
+ border-left: 0px solid black;
589
+ border-right: 0px solid black;
590
+ border-bottom: 2px solid black;
591
+ }
592
+
593
+ .td_footer_failed {
594
+ whitw-space: nowrap;
595
+ background: #99CCFF;
596
+ text-align: center;
597
+ font-family: Arial;
598
+ font-weight: bold;
599
+ font-size: 12px;
600
+ color: #FF0000;
601
+ border-top: 2px solid black;
602
+ border-left: 0px solid black;
603
+ border-right: 2px solid black;
604
+ border-bottom: 2px solid black;
605
+ }
606
+
607
+ .td_footer_blocked {
608
+ whitw-space: nowrap;
609
+ background: #99CCFF;
610
+ text-align: center;
611
+ font-family: Arial;
612
+ font-weight: bold;
613
+ font-size: 12px;
614
+ color: #FFCF10;
615
+ border-top: 2px solid black;
616
+ border-left: 0px solid black;
617
+ border-right: 0px solid black;
618
+ border-bottom: 2px solid black;
619
+ }
620
+
621
+ .td_footer_skipped {
622
+ whitw-space: nowrap;
623
+ background: #99CCFF;
624
+ text-align: center;
625
+ font-family: Arial;
626
+ font-weight: bold;
627
+ font-size: 12px;
628
+ color: #D9D9D9;
629
+ border-top: 2px solid black;
630
+ border-left: 0px solid black;
631
+ border-right: 2px solid black;
632
+ border-bottom: 2px solid black;
633
+ }
634
+
635
+ .td_footer_watchdog {
636
+ whitw-space: nowrap;
637
+ background: #99CCFF;
638
+ text-align: center;
639
+ font-family: Arial;
640
+ font-weight: bold;
641
+ font-size: 12px;
642
+ color: #FF0000;
643
+ border-top: 2px solid black;
644
+ border-left: 0px solid black;
645
+ border-right: 0px solid black;
646
+ border-bottom: 2px solid black;
647
+ }
648
+
649
+ .td_footer_exceptions {
650
+ whitw-space: nowrap;
651
+ background: #99CCFF;
652
+ text-align: center;
653
+ font-family: Arial;
654
+ font-weight: bold;
655
+ font-size: 12px;
656
+ color: #FF0000;
657
+ border-top: 2px solid black;
658
+ border-left: 0px solid black;
659
+ border-right: 0px solid black;
660
+ border-bottom: 2px solid black;
661
+ }
662
+
663
+ .td_footer_javascript {
664
+ whitw-space: nowrap;
665
+ background: #99CCFF;
666
+ text-align: center;
667
+ font-family: Arial;
668
+ font-weight: bold;
669
+ font-size: 12px;
670
+ color: #FF0000;
671
+ border-top: 2px solid black;
672
+ border-left: 0px solid black;
673
+ border-right: 0px solid black;
674
+ border-bottom: 2px solid black;
675
+ }
676
+
677
+ .td_footer_assert {
678
+ whitw-space: nowrap;
679
+ background: #99CCFF;
680
+ text-align: center;
681
+ font-family: Arial;
682
+ font-weight: bold;
683
+ font-size: 12px;
684
+ color: #FF0000;
685
+ border-top: 2px solid black;
686
+ border-left: 0px solid black;
687
+ border-right: 0px solid black;
688
+ border-bottom: 2px solid black;
689
+ }
690
+
691
+ .td_footer_other {
692
+ whitw-space: nowrap;
693
+ background: #99CCFF;
694
+ text-align: center;
695
+ font-family: Arial;
696
+ font-weight: bold;
697
+ font-size: 12px;
698
+ color: #FF0000;
699
+ border-top: 2px solid black;
700
+ border-left: 0px solid black;
701
+ border-right: 0px solid black;
702
+ border-bottom: 2px solid black;
703
+ }
704
+
705
+ .td_footer_total {
706
+ whitw-space: nowrap;
707
+ background: #99CCFF;
708
+ text-align: center;
709
+ font-family: Arial;
710
+ font-weight: bold;
711
+ font-size: 12px;
712
+ color: #FF0000;
713
+ border-top: 2px solid black;
714
+ border-left: 2px solid black;
715
+ border-right: 2px solid black;
716
+ border-bottom: 2px solid black;
717
+ }
718
+
719
+ .td_footer_css {
720
+ whitw-space: nowrap;
721
+ background: #99CCFF;
722
+ text-align: center;
723
+ font-family: Arial;
724
+ font-weight: bold;
725
+ font-size: 12px;
726
+ color: #000000;
727
+ border-top: 2px solid black;
728
+ border-left: 0px solid black;
729
+ border-right: 0px solid black;
730
+ border-bottom: 2px solid black;
731
+ }
732
+
733
+ .td_footer_sodawarnings {
734
+ whitw-space: nowrap;
735
+ background: #99CCFF;
736
+ text-align: center;
737
+ font-family: Arial;
738
+ font-weight: bold;
739
+ font-size: 12px;
740
+ color: #000000;
741
+ border-top: 2px solid black;
742
+ border-left: 0px solid black;
743
+ border-right: 0px solid black;
744
+ border-bottom: 2px solid black;
745
+ }
746
+
747
+ .td_footer_times {
748
+ whitw-space: nowrap;
749
+ background: #99CCFF;
750
+ text-align: center;
751
+ font-family: Arial;
752
+ font-weight: bold;
753
+ font-size: 12px;
754
+ color: #000000;
755
+ border-top: 2px solid black;
756
+ border-left: 2px solid black;
757
+ border-right: 0px solid black;
758
+ border-bottom: 2px solid black;
759
+ }
760
+ </style>
761
+ <body>
762
+ <table>
763
+ <tr>
764
+ <td class="td_header_master" rowspan="2">Suite</br>
765
+ (click link for full report)</td>
766
+ <td class="td_header_master" colspan="5">Tests</td>
767
+ <td class="td_header_master" colspan="6">Failures</td>
768
+ <td class="td_header_master" colspan="2">Warnings</td>
769
+ <td class="td_header_master" rowspan="2">Run Time</br>(hh:mm:ss)</td>
770
+ </tr>
771
+ <tr>
772
+ <td class="td_header_sub">Run</td>
773
+ <td class="td_header_sub">Passed</td>
774
+ <td class="td_header_sub">Failed</td>
775
+ <td class="td_header_sub">Blocked</td>
776
+ <td class="td_header_skipped">Skipped</td>
777
+ <td class="td_header_watchdog">Watchdogs</td>
778
+ <td class="td_header_sub">Exceptions</td>
779
+ <td class="td_header_sub">JavaScript</br>Errors</td>
780
+ <td class="td_header_sub">Assert</br>Failures</td>
781
+ <td class="td_header_sub">Other</br>Failures</td>
782
+ <td class="td_header_skipped">Total</br>Failures</td>
783
+ <td class="td_header_watchdog">CSS Errors</td>
784
+ <td class="td_header_skipped">Soda</br>Warnings</td>
785
+ </tr>
786
+ HTML
787
+
788
+ fd.write(html_header)
789
+
790
+ data.each do |suite, suite_hash|
791
+ totals[suite] = Hash.new()
792
+ totals[suite]['Test Failure Count'] = 0
793
+ totals[suite]['Test Passed Count'] = 0
794
+ totals[suite]['Total Time'] = nil
795
+
796
+ suite_hash.each do |k, v|
797
+ next if (k !~ /tests/)
798
+ totals[suite]['Test Count'] = v.length()
799
+
800
+ v.each do |test|
801
+ time_set = false
802
+ if (test['result'].to_i != 0)
803
+ totals[suite]['Test Failure Count'] += 1
804
+ total_failure_count += 1
805
+ else
806
+ totals[suite]['Test Passed Count'] += 1
807
+ end
808
+
809
+ if (!time_set)
810
+ time_set = true
811
+ stop = test['Test Stop Time']
812
+ start = DateTime.strptime("#{test['Test Start Time']}",
813
+ "%m/%d/%Y-%H:%M:%S")
814
+ stop = DateTime.strptime("#{test['Test Stop Time']}",
815
+ "%m/%d/%Y-%H:%M:%S")
816
+
817
+ diff = (stop - start)
818
+ if (totals[suite]['Total Time'] == nil)
819
+ totals[suite]['Total Time'] = diff
820
+ else
821
+ totals[suite]['Total Time'] += diff
822
+ end
823
+ end
824
+
825
+ test.each do |test_k, test_v|
826
+ if (!totals[suite].key?(test_k))
827
+ totals[suite][test_k] = 0
828
+ else
829
+ totals[suite][test_k] += test_v.to_i if (test_k !~ /time/i)
830
+ end
831
+ end
832
+ end
833
+ end
834
+ end
835
+
836
+ totals.each do |suite, suite_hash|
837
+ suite_hash.each do |k, v|
838
+ if (!suite_totals.key?(k))
839
+ suite_totals[k] = 0
840
+ end
841
+
842
+ if (k =~ /Total Time/)
843
+ suite_totals[k] += v
844
+ else
845
+ suite_totals[k] += v.to_i()
846
+ end
847
+ end
848
+ end
849
+
850
+ row_id = 0
851
+ totals.each do |suite_name, suite_hash|
852
+ next if (suite_name =~ /Total\sFailure\sCount/i)
853
+ row_id += 1
854
+ report_file = "#{suite_name}"
855
+ hours,minutes,seconds,frac =
856
+ Date.day_fraction_to_time(suite_hash['Total Time'])
857
+
858
+ if (hours < 10)
859
+ hours = "0#{hours}"
860
+ end
861
+
862
+ if (minutes < 10)
863
+ minutes = "0#{minutes}"
864
+ end
865
+
866
+ if (seconds < 10)
867
+ seconds = "0#{seconds}"
868
+ end
869
+
870
+ suite_hash['Test Other Failures'] = 0
871
+
872
+ test_run_class = "td_run_data"
873
+ if (suite_hash['Test Assert Failures'] > 0 ||
874
+ suite_hash['Test Exceptions'] > 0)
875
+ test_run_class = "td_run_data_error"
876
+ end
877
+
878
+ exceptions_td = "td_exceptions_data"
879
+ if (suite_hash['Test Exceptions'] > 0)
880
+ exceptions_td = "td_exceptions_error_data"
881
+ end
882
+
883
+ asserts_td = "td_assert_data"
884
+ if (suite_hash['Test Assert Failures'] > 0)
885
+ asserts_td = "td_assert_error_data"
886
+ end
887
+
888
+ watchdog_td = "td_watchdog_data"
889
+ if (suite_hash['Test WatchDog Count'] > 0)
890
+ watchdog_td = "td_watchdog_error_data"
891
+ end
892
+
893
+ jscript_td = "td_javascript_data"
894
+ if (suite_hash['Test JavaScript Error Count'] > 0)
895
+ jscript_td = "td_javascript_error_data"
896
+ end
897
+
898
+ t_passedcount = suite_hash['Test Count']
899
+ t_passedcount -= suite_hash['Test Failure Count']
900
+ total_failures = 0
901
+ # total_failures += suite_hash['Test Failure Count']
902
+ total_failures += suite_hash['Test WatchDog Count']
903
+ total_failures += suite_hash['Test Assert Failures']
904
+ total_failures += suite_hash['Test Other Failures']
905
+ total_failures += suite_hash['Test JavaScript Error Count']
906
+ # total_failure_count += total_failures
907
+
908
+ ran_count = suite_hash['Test Count'].to_i()
909
+ ran_count -= suite_hash['Test WatchDog Count']
910
+ ran_count -= suite_hash['Test Blocked Count']
911
+
912
+ total_non_ran_count += suite_hash['Test WatchDog Count']
913
+ total_non_ran_count += suite_hash['Test Blocked Count']
914
+
915
+ reportdir = File.dirname(reportfile)
916
+ suite_mini_file = GenSuiteMiniSummary(data[suite_name], reportdir)
917
+
918
+ str = "<tr id=\"#{row_id}\" class=\"unhighlight\" "+
919
+ "onMouseOver=\"this.className='highlight'\" "+
920
+ "onMouseOut=\"this.className='unhighlight'\">\n"+
921
+ "\t<td class=\"td_file_data\"><a href=\"#{suite_mini_file}\">"+
922
+ "#{suite_name}</a></td>\n"+
923
+ "\t<td class=\"#{test_run_class}\">"+
924
+ "#{ran_count}/#{suite_hash['Test Count']}</td>\n"+
925
+ "\t<td class=\"td_passed_data\">"+
926
+ "#{suite_hash['Test Passed Count']}</td>\n"+
927
+ "\t<td class=\"td_failed_data\">"+
928
+ "#{suite_hash['Test Failure Count']}</td>\n"+
929
+ "\t<td class=\"td_blocked_data\">"+
930
+ "#{suite_hash['Test Blocked Count']}</td>\n"+
931
+ "\t<td class=\"td_skipped_data\">"+
932
+ "#{suite_hash['Test Skip Count']}</td>\n"+
933
+ "\t<td class=\"#{watchdog_td}\">"+
934
+ "#{suite_hash['Test WatchDog Count']}</td>\n"+
935
+ "\t<td class=\"#{exceptions_td}\">"+
936
+ "#{suite_hash['Test Exceptions']}</td>\n"+
937
+ "\t<td class=\"#{jscript_td}\">"+
938
+ "#{suite_hash['Test JavaScript Error Count']}</td>\n"+
939
+ "\t<td class=\"#{asserts_td}\">"+
940
+ "#{suite_hash['Test Assert Failures']}</td>\n"+
941
+ "\t<td class=\"td_other_data\">"+
942
+ "0</td>\n"+
943
+ "\t<td class=\"td_total_data\">#{total_failures}</td>\n"+
944
+ "\t<td class=\"td_css_data\">"+
945
+ "#{suite_hash['Test CSS Error Count']}</td>\n"+
946
+ "\t<td class=\"td_sodawarnings_data\">"+
947
+ "#{suite_hash['Test Warning Count']}</td>\n"+
948
+ "\t<td class=\"td_time_data\">"+
949
+ "#{hours}:#{minutes}:#{seconds}</td>\n</tr>\n"
950
+ fd.write(str)
951
+ end
952
+
953
+ test_totals = suite_totals['Test Count']
954
+ test_totals += suite_totals['Test Skip Count']
955
+ test_totals += suite_totals['Test Blocked Count']
956
+
957
+ hours,minutes,seconds,frac =
958
+ Date.day_fraction_to_time(suite_totals['Total Time'])
959
+ if (hours < 10)
960
+ hours = "0#{hours}"
961
+ end
962
+
963
+ if (minutes < 10)
964
+ minutes = "0#{minutes}"
965
+ end
966
+
967
+ if (seconds < 10)
968
+ seconds = "0#{seconds}"
969
+ end
970
+
971
+ sub_totals = "<tr id=\"totals\">\n"+
972
+ "\t<td class=\"td_header_master\">Totals:</td>\n"+
973
+ "\t<td class=\"td_footer_run\">#{suite_totals['Test Count']}"+
974
+ "/#{test_totals}</td>\n"+
975
+ "\t<td class=\"td_footer_passed\">#{suite_totals['Test Passed Count']}"+
976
+ "</td>\n"+
977
+ "\t<td class=\"td_footer_failed\">"+
978
+ "#{suite_totals['Test Failure Count']}</td>\n"+
979
+ "\t<td class=\"td_footer_blocked\">"+
980
+ "#{suite_totals['Test Blocked Count']}</td>\n"+
981
+ "\t<td class=\"td_footer_skipped\">"+
982
+ "#{suite_totals['Test Skip Count']}</td>\n"+
983
+ "\t<td class=\"td_footer_watchdog\">"+
984
+ "#{suite_totals['Test WatchDog Count']}</td>\n"+
985
+ "\t<td class=\"td_footer_exceptions\">"+
986
+ "#{suite_totals['Test Exceptions']}</td>\n"+
987
+ "\t<td class=\"td_footer_javascript\">"+
988
+ "#{suite_totals['Test JavaScript Error Count']}</td>\n"+
989
+ "\t<td class=\"td_footer_assert\">"+
990
+ "#{suite_totals['Test Assert Failures']}</td>\n"+
991
+ "\t<td class=\"td_footer_other\">0</td>\n"+
992
+ "\t<td class=\"td_footer_total\">"+
993
+ "#{total_failure_count}</td>\n"+
994
+ "\t<td class=\"td_footer_css\">"+
995
+ "#{suite_totals['Test CSS Error Count']}</td>\n"+
996
+ "\t<td class=\"td_footer_sodawarnings\">"+
997
+ "#{suite_totals['Test Warning Count']}</td>\n"+
998
+ "\t<td class=\"td_footer_times\">"+
999
+ "#{hours}:#{minutes}:#{seconds}</td>\n"+
1000
+ "</tr>\n"
1001
+ fd.write(sub_totals)
1002
+ fd.write("</table>\n</body>\n</html>\n")
1003
+ fd.close()
1004
+
1005
+ return 0
1006
+
1007
+ end
1008
+ private :GenHtmlReport
1009
+
1010
+ def GenSuiteMiniSummary(suite_hash, reportdir)
1011
+ suite_file = suite_hash['suitefile']
1012
+ suite_file = File.basename(suite_file, ".xml")
1013
+ suite_file << ".html"
1014
+ suite_file = "#{reportdir}/#{suite_file}"
1015
+
1016
+ html = <<HTML
1017
+ <html>
1018
+ <style type="text/css">
1019
+ table {
1020
+ width: 100%;
1021
+ border: 2px solid black;
1022
+ border-collapse: collapse;
1023
+ padding: 0px;
1024
+ background: #FFFFFF;
1025
+ }
1026
+ .td_header_master {
1027
+ whitw-space: nowrap;
1028
+ background: #99CCFF;
1029
+ text-align: center;
1030
+ font-family: Arial;
1031
+ font-weight: bold;
1032
+ font-size: 12px;
1033
+ border-left: 0px solid black;
1034
+ border-right: 2px solid black;
1035
+ border-bottom: 2px solid black;
1036
+ }
1037
+ .td_file_data {
1038
+ whitw-space: nowrap;
1039
+ text-align: left;
1040
+ font-family: Arial;
1041
+ font-weight: bold;
1042
+ font-size: 12px;
1043
+ border-left: 0px solid black;
1044
+ border-right: 2px solid black;
1045
+ border-bottom: 2px solid black;
1046
+ }
1047
+ .td_passed_data {
1048
+ whitw-space: nowrap;
1049
+ text-align: center;
1050
+ font-family: Arial;
1051
+ font-weight: bold;
1052
+ color: #00FF00;
1053
+ font-size: 12px;
1054
+ border-left: 0px solid black;
1055
+ border-right: 0px solid black;
1056
+ border-bottom: 2px solid black;
1057
+ }
1058
+
1059
+ .td_failed_data {
1060
+ whitw-space: nowrap;
1061
+ text-align: center;
1062
+ font-family: Arial;
1063
+ font-weight: bold;
1064
+ color: #FF0000;
1065
+ font-size: 12px;
1066
+ border-left: 0px solid black;
1067
+ border-right: 0px solid black;
1068
+ border-bottom: 2px solid black;
1069
+ }
1070
+ .td_report_data {
1071
+ whitw-space: nowrap;
1072
+ text-align: center;
1073
+ font-family: Arial;
1074
+ font-weight: normal;
1075
+ font-size: 12px;
1076
+ border-left: 2px solid black;
1077
+ border-right: 1px solid black;
1078
+ border-bottom: 2px solid black;
1079
+ }
1080
+ </style>
1081
+ <body>
1082
+ <table id="tests">
1083
+ <tr id="header">
1084
+ <td class="td_header_master" colspan="3">
1085
+ Suite: #{suite_hash['suitefile']} Test Results
1086
+ </td>
1087
+ </tr>
1088
+ <tr id="header_key">
1089
+ <td class="td_header_master">Test File</td>
1090
+ <td class="td_header_master">Status</td>
1091
+ <td class="td_header_master">Report Log</td>
1092
+ </tr>
1093
+ HTML
1094
+
1095
+ fd = File.new(suite_file, "w+")
1096
+ fd.write(html)
1097
+ id = 0
1098
+ suite_hash['tests'].each do |test|
1099
+ id += 1
1100
+ test_report = test['testfile']
1101
+ test_report = File.basename(test_report, ".xml")
1102
+ test_report = "Report-#{test_report}.html"
1103
+
1104
+ str = "<tr id=\"#{id}\">\n"+
1105
+ "\t<td class=\"td_file_data\">#{test['testfile']}</td>\n"
1106
+
1107
+ if (test['result'].to_i != 0)
1108
+ str << "\t<td class=\"td_failed_data\">Failed</td>\n"
1109
+ else
1110
+ str << "\t<td class=\"td_passed_data\">Passed</td>\n"
1111
+ end
1112
+
1113
+ str << "\t<td class=\"td_report_data\">"
1114
+ str << "<a href=\"#{test_report}\">Report Log</a></td>\n"
1115
+ str << "</tr>\n"
1116
+ fd.write(str)
1117
+ end
1118
+
1119
+ fd.write("</table>\n</body>\n</html>\n")
1120
+ fd.close()
1121
+
1122
+ return suite_file
1123
+
1124
+ end
1125
+
1126
+
1127
+ end
1128
+
1129
+