soda 1.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/SodaSuite +8 -1
- data/lib/Soda.rb +66 -47
- data/lib/SodaCSV.rb +1 -0
- data/lib/SodaFireFox.rb +138 -0
- data/lib/SodaReportSummery.rb +5 -17
- data/lib/SodaReporter.rb +11 -10
- data/lib/SodaSuiteSummary.rb +545 -527
- data/lib/fields/SodaField.rb +10 -3
- data/lib/sodainfo.rb +1 -1
- metadata +5 -5
data/bin/SodaSuite
CHANGED
@@ -130,7 +130,7 @@ class SodaSuite
|
|
130
130
|
result = soda.RunAllSuites(suites)
|
131
131
|
|
132
132
|
return result
|
133
|
-
end
|
133
|
+
end
|
134
134
|
|
135
135
|
###############################################################################
|
136
136
|
# Execute -- Medhod
|
@@ -247,6 +247,8 @@ Optional Flags:
|
|
247
247
|
|
248
248
|
--help: Prints this message and exits.
|
249
249
|
|
250
|
+
--nonzippytext: This turns on zippy text entry for Watir.
|
251
|
+
|
250
252
|
--version: Print the Soda Version string.
|
251
253
|
|
252
254
|
HLP
|
@@ -472,6 +474,7 @@ def Main
|
|
472
474
|
test_files = []
|
473
475
|
hijacks = {}
|
474
476
|
params = {
|
477
|
+
'nonzippytext' => false,
|
475
478
|
'sugarwait' => false,
|
476
479
|
'verbose' => false,
|
477
480
|
'browser' => nil,
|
@@ -534,6 +537,7 @@ def Main
|
|
534
537
|
[ '--restarttest', '-2', GetoptLong::OPTIONAL_ARGUMENT],
|
535
538
|
[ '--reruntest', '-3', GetoptLong::OPTIONAL_ARGUMENT ],
|
536
539
|
[ '--skipcsserrors', '-4', GetoptLong::OPTIONAL_ARGUMENT],
|
540
|
+
[ '--nonzippytext', '-6', GetoptLong::OPTIONAL_ARGUMENT],
|
537
541
|
[ '--version', '-5', GetoptLong::OPTIONAL_ARGUMENT]
|
538
542
|
)
|
539
543
|
|
@@ -578,6 +582,8 @@ def Main
|
|
578
582
|
rerun_test_script = arg
|
579
583
|
when "--skipcsserrors"
|
580
584
|
params['errorskip'].push("css")
|
585
|
+
when "--nonzippytext"
|
586
|
+
params['nonzippytext'] = true
|
581
587
|
when "--version"
|
582
588
|
print "(*)SODA Version: #{SODA_GEM_VERSION}\n\n"
|
583
589
|
return 0
|
@@ -614,6 +620,7 @@ def Main
|
|
614
620
|
SodaUtils.PrintSoda("SodaSuite Settings:\n--)Browser:" +
|
615
621
|
" #{params['browser']}\n--)Debug: #{params['debug']}\n--)Verbose:"+
|
616
622
|
" #{params['verbose']}\n" +
|
623
|
+
"--)NonZippyText: #{params['nonzippytext']}\n" +
|
617
624
|
"--)Watir Version: #{Watir::VERSION}\n")
|
618
625
|
SodaUtils.PrintSoda("Starting testing...\n")
|
619
626
|
|
data/lib/Soda.rb
CHANGED
@@ -99,6 +99,7 @@ class Soda
|
|
99
99
|
@currentTestFile = ""
|
100
100
|
@exceptionExit = false
|
101
101
|
@ieHwnd = 0
|
102
|
+
@nonzippytext = false
|
102
103
|
$global_time = Time.now()
|
103
104
|
$mutex = Mutex.new()
|
104
105
|
@whiteList = []
|
@@ -124,6 +125,7 @@ class Soda
|
|
124
125
|
@sugarFlavor = params['flavor'] if (params.key?('flavor'))
|
125
126
|
@resultsDir = params['resultsdir'] if (params.key?('resultsdir'))
|
126
127
|
@globalVars = params['gvars'] if (params.key?('gvars'))
|
128
|
+
@nonzippytext = params['nonzippytext'] if (params.key?('nonzippytext'))
|
127
129
|
|
128
130
|
if (@globalVars.key?('scriptsdir'))
|
129
131
|
blocked_file_list = "#{@globalVars['scriptsdir']}/modules/" +
|
@@ -408,12 +410,16 @@ class Soda
|
|
408
410
|
if (value.instance_of?(Hash))
|
409
411
|
msg << " Hash:{"
|
410
412
|
value.each do |k ,v|
|
411
|
-
|
413
|
+
tmp_k = k.gsub("\n", '\n')
|
414
|
+
tmp_v = v.gsub("\n", '\n')
|
415
|
+
msg << "'#{tmp_k}'=>'#{tmp_v}',"
|
412
416
|
end
|
413
417
|
msg = msg.chop()
|
414
418
|
msg << "}\n"
|
415
419
|
else
|
416
|
-
|
420
|
+
tmp_value = "#{value}"
|
421
|
+
tmp_value = tmp_value.gsub("\n", '\n')
|
422
|
+
msg << " \"#{tmp_value}\"\n"
|
417
423
|
end
|
418
424
|
|
419
425
|
PrintDebug(msg)
|
@@ -483,7 +489,9 @@ class Soda
|
|
483
489
|
" \"#{val}\" to \"#{@hiJacks["#{org_name}"]}\"\n")
|
484
490
|
val = @hiJacks["#{org_name}"]
|
485
491
|
else
|
486
|
-
|
492
|
+
tmp_val = "#{val}"
|
493
|
+
tmp_val = tmp_val.gsub("\n", '\n')
|
494
|
+
PrintDebug("Value for \"#{tmp_name}\" => \"#{tmp_val}\".\n")
|
487
495
|
end
|
488
496
|
|
489
497
|
val = "" if (val == nil) # default it to be an empty string. #
|
@@ -820,11 +828,19 @@ class Soda
|
|
820
828
|
|
821
829
|
if (@non_lib_test_count >= @restart_count)
|
822
830
|
@rep.log("Restarting browser.\n")
|
823
|
-
|
824
|
-
|
831
|
+
|
832
|
+
begin
|
833
|
+
@browser.close()
|
834
|
+
sleep(1)
|
835
|
+
rescue Exception => e
|
836
|
+
end
|
825
837
|
|
826
838
|
RestartGlobalTime()
|
827
839
|
|
840
|
+
if (@params['browser'] =~ /firefox/i)
|
841
|
+
SodaFireFox.KillProcesses()
|
842
|
+
end
|
843
|
+
|
828
844
|
err = NewBrowser()
|
829
845
|
if (err != 0)
|
830
846
|
@rep.ReportFailure("Failed to restart browser!\n")
|
@@ -1055,7 +1071,11 @@ class Soda
|
|
1055
1071
|
end
|
1056
1072
|
|
1057
1073
|
if (org_str != str)
|
1058
|
-
|
1074
|
+
tmp_org_str = "#{org_str}"
|
1075
|
+
tmp_org_str = tmp_org_str.gsub("\n", '\n')
|
1076
|
+
tmp_str = "#{str}"
|
1077
|
+
tmp_str = tmp_str.gsub("\n", '\n')
|
1078
|
+
PrintDebug("Replacing string '#{tmp_org_str}' with '#{tmp_str}'\n")
|
1059
1079
|
end
|
1060
1080
|
|
1061
1081
|
return str
|
@@ -2128,7 +2148,7 @@ JSCode
|
|
2128
2148
|
foundaction = event['do']
|
2129
2149
|
end
|
2130
2150
|
|
2131
|
-
if (event.key?("alert")
|
2151
|
+
if (event.key?("alert"))
|
2132
2152
|
if (event['alert'] =~ /true/i)
|
2133
2153
|
@rep.log("Enabling Alert Hack\n")
|
2134
2154
|
fieldType.alertHack(true, true)
|
@@ -2144,7 +2164,7 @@ JSCode
|
|
2144
2164
|
js = replaceVars(event['jscriptevent'])
|
2145
2165
|
end
|
2146
2166
|
|
2147
|
-
case foundaction
|
2167
|
+
case (foundaction)
|
2148
2168
|
when "append"
|
2149
2169
|
result = fieldType.append(@curEl, replaceVars(event['append']))
|
2150
2170
|
if (result != 0)
|
@@ -2213,8 +2233,12 @@ JSCode
|
|
2213
2233
|
end
|
2214
2234
|
end
|
2215
2235
|
when "set"
|
2216
|
-
|
2217
|
-
|
2236
|
+
if (@curEl.class.to_s =~ /textfield/i)
|
2237
|
+
result = fieldType.set(@curEl, event['set'], @nonzippytext)
|
2238
|
+
else
|
2239
|
+
result = fieldType.set(@curEl, event['set'])
|
2240
|
+
end
|
2241
|
+
|
2218
2242
|
if (result != 0)
|
2219
2243
|
event['current_test_file'] = @currentTestFile
|
2220
2244
|
e_dump = SodaUtils.DumpEvent(event)
|
@@ -2674,22 +2698,31 @@ JSCode
|
|
2674
2698
|
# file: The Soda test file.
|
2675
2699
|
# rerun: true/false, this tells soda that this tests is a rerun of a
|
2676
2700
|
# failed test.
|
2701
|
+
# suitename: The name of the suite to group the results into.
|
2677
2702
|
#
|
2678
2703
|
# Results:
|
2679
2704
|
# returns a SodaReport object.
|
2680
2705
|
#
|
2681
2706
|
###############################################################################
|
2682
|
-
def run(file, rerun = false, genhtml = true)
|
2707
|
+
def run(file, rerun = false, genhtml = true, suitename = nil)
|
2683
2708
|
result = 0
|
2684
2709
|
master_result = 0
|
2685
2710
|
thread_soda = nil
|
2686
2711
|
thread_timeout = (60 * 10) # 10 minutes #
|
2687
2712
|
time_check = nil
|
2713
|
+
resultsdir = nil
|
2714
|
+
|
2715
|
+
if (suitename != nil)
|
2716
|
+
resultsdir = "#{@resultsDir}/#{suitename}"
|
2717
|
+
else
|
2718
|
+
resultsdir = @resultsDir
|
2719
|
+
end
|
2688
2720
|
|
2689
2721
|
@currentTestFile = file
|
2690
2722
|
@exceptionExit = false
|
2691
2723
|
@fileStack.push(file)
|
2692
|
-
|
2724
|
+
|
2725
|
+
@rep = SodaReporter.new(file, @saveHtml, resultsdir, 0, nil, rerun);
|
2693
2726
|
SetGlobalVars()
|
2694
2727
|
|
2695
2728
|
script = getScript(file)
|
@@ -2818,12 +2851,11 @@ JSCode
|
|
2818
2851
|
def RunSuite(suitefile)
|
2819
2852
|
parser = nil
|
2820
2853
|
doc = nil
|
2854
|
+
test_order = 0
|
2821
2855
|
result = {}
|
2822
2856
|
tests = []
|
2823
|
-
|
2824
|
-
|
2825
|
-
setup_results = 0
|
2826
|
-
|
2857
|
+
suite_name = File.basename(suitefile, ".xml")
|
2858
|
+
|
2827
2859
|
begin
|
2828
2860
|
parser = LibXML::XML::Parser.file(suitefile)
|
2829
2861
|
doc = parser.parse()
|
@@ -2838,7 +2870,7 @@ JSCode
|
|
2838
2870
|
tests.push(attrs['file'])
|
2839
2871
|
elsif (attrs.key?('fileset'))
|
2840
2872
|
files = File.join(attrs['fileset'], "*.xml")
|
2841
|
-
files = Dir.glob(files)
|
2873
|
+
files = Dir.glob(files).sort_by{|f| File.stat(f).mtime}
|
2842
2874
|
files.each do |f|
|
2843
2875
|
tests.push(f)
|
2844
2876
|
end
|
@@ -2851,39 +2883,26 @@ JSCode
|
|
2851
2883
|
ensure
|
2852
2884
|
end
|
2853
2885
|
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2886
|
+
tests.each do |test|
|
2887
|
+
test_order += 1
|
2888
|
+
tmp_result = {}
|
2889
|
+
tmp_result['result'] = run(test, false, true, suite_name)
|
2890
|
+
tmp_result['Test_Order'] = test_order
|
2891
|
+
tmp_result.merge!(@rep.GetRawResults)
|
2892
|
+
tmp_result['Real_Test_Name'] = test
|
2893
|
+
test_basename = File.basename(test, ".xml")
|
2894
|
+
logfile = tmp_result['Test Log File']
|
2895
|
+
if (logfile =~ /#{test_basename}-\d+/)
|
2896
|
+
test =~ /(.*\/)#{test_basename}/
|
2897
|
+
ran_test_name = $1
|
2898
|
+
ran_test_name << File.basename(logfile, ".log")
|
2899
|
+
ran_test_name << ".xml"
|
2861
2900
|
else
|
2862
|
-
|
2863
|
-
result[setup_test] = {'result' => 0}
|
2901
|
+
ran_test_name = test
|
2864
2902
|
end
|
2865
|
-
else
|
2866
|
-
setup_result = true
|
2867
|
-
end
|
2868
2903
|
|
2869
|
-
|
2870
|
-
|
2871
|
-
result[test] = {}
|
2872
|
-
result[test]['result'] = run(test, false)
|
2873
|
-
result[test].merge!(@rep.GetRawResults)
|
2874
|
-
@rep.ZeroTestResults()
|
2875
|
-
end
|
2876
|
-
end
|
2877
|
-
|
2878
|
-
if (cleanup_test != nil)
|
2879
|
-
cleanup_result = run(cleanup_test, false, false)
|
2880
|
-
if (cleanup_result != 0)
|
2881
|
-
SodaUtils.PrintSoda("Failed calling cleanup test: "+
|
2882
|
-
"'#{cleanup_test}'!\n", SodaUtils::ERROR)
|
2883
|
-
result[cleanup_test] = {'result' => -1}
|
2884
|
-
else
|
2885
|
-
result[cleanup_test] = {'result' => 0}
|
2886
|
-
end
|
2904
|
+
result[ran_test_name] = tmp_result
|
2905
|
+
@rep.ZeroTestResults()
|
2887
2906
|
end
|
2888
2907
|
|
2889
2908
|
return result
|
data/lib/SodaCSV.rb
CHANGED
data/lib/SodaFireFox.rb
CHANGED
@@ -116,5 +116,143 @@ JS
|
|
116
116
|
|
117
117
|
end
|
118
118
|
|
119
|
+
###############################################################################
|
120
|
+
# KillProcessWindows -- function
|
121
|
+
# This function find all running firefox processes and then tries to
|
122
|
+
# kill them.
|
123
|
+
#
|
124
|
+
# Input:
|
125
|
+
# None.
|
126
|
+
#
|
127
|
+
# Output:
|
128
|
+
# returns -1 on error else 0 on success.
|
129
|
+
#
|
130
|
+
###############################################################################
|
131
|
+
def SodaFireFox.KillProcessWindows()
|
132
|
+
firefox = []
|
133
|
+
tmp = nil
|
134
|
+
result = 0
|
135
|
+
|
136
|
+
tmp = Kernel.open("| tasklist /NH")
|
137
|
+
lines = tmp.readlines()
|
138
|
+
tmp.close()
|
139
|
+
|
140
|
+
lines.each do |l|
|
141
|
+
l = l.chomp()
|
142
|
+
if (l =~ /firefox/i)
|
143
|
+
hash = {
|
144
|
+
'pid' => nil,
|
145
|
+
'name' => nil
|
146
|
+
}
|
147
|
+
data = l.split(/\s+/)
|
148
|
+
hash['name'] = data[0]
|
149
|
+
hash['pid'] = data[1].to_i()
|
150
|
+
firefox.push(hash)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
if (firefox.length < 1)
|
155
|
+
$curSoda.rep.log("No firefox processes to kill, browser closed clean.\n")
|
156
|
+
end
|
157
|
+
|
158
|
+
firefox.each do |hash|
|
159
|
+
begin
|
160
|
+
$curSoda.rep.log("Killing Process ID: #{hash['pid']}, Name:"+
|
161
|
+
"#{hash['name']}\n")
|
162
|
+
Process.kill("KILL", hash['pid'])
|
163
|
+
rescue Exception => e
|
164
|
+
$curSoda.rep.ReportException(e, true, false)
|
165
|
+
result = -1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
return result
|
170
|
+
end
|
171
|
+
|
172
|
+
###############################################################################
|
173
|
+
# KillProcessUnix -- function
|
174
|
+
# This function find all running firefox processes and then tries to
|
175
|
+
# kill them.
|
176
|
+
#
|
177
|
+
# Input:
|
178
|
+
# None.
|
179
|
+
#
|
180
|
+
# Output:
|
181
|
+
# returns -1 on error else 0 on success.
|
182
|
+
#
|
183
|
+
###############################################################################
|
184
|
+
def SodaFireFox.KillProcessUnix()
|
185
|
+
firefox = []
|
186
|
+
tmp = nil
|
187
|
+
result = 0
|
188
|
+
|
189
|
+
tmp = Kernel.open("| ps -e")
|
190
|
+
lines = tmp.readlines()
|
191
|
+
tmp.close()
|
192
|
+
|
193
|
+
lines.shift()
|
194
|
+
lines.each do |l|
|
195
|
+
l = l.chomp()
|
196
|
+
l = l.gsub(/^\s+/, "")
|
197
|
+
|
198
|
+
if (l =~ /firefox/i)
|
199
|
+
print "(*)#{l}\n"
|
200
|
+
hash = {
|
201
|
+
'pid' => nil,
|
202
|
+
'name' => nil
|
203
|
+
}
|
204
|
+
|
205
|
+
data = l.split(/\s+/)
|
206
|
+
hash['pid'] = data[0].to_i()
|
207
|
+
hash['name'] = data[3]
|
208
|
+
firefox.push(hash)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
if (firefox.length < 1)
|
213
|
+
$curSoda.rep.log("No firefox processes to kill, browser closed clean.\n")
|
214
|
+
end
|
215
|
+
|
216
|
+
firefox.each do |hash|
|
217
|
+
begin
|
218
|
+
$curSoda.rep.log("Killing Process ID: #{hash['pid']}, Name:"+
|
219
|
+
"#{hash['name']}\n")
|
220
|
+
Process.kill("KILL", hash['pid'])
|
221
|
+
rescue Exception => e
|
222
|
+
$curSoda.rep.ReportException(e, true, false)
|
223
|
+
result = -1
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
return result
|
228
|
+
end
|
229
|
+
|
230
|
+
###############################################################################
|
231
|
+
# KillProcesses -- function
|
232
|
+
# This function kills all firefox processes.
|
233
|
+
#
|
234
|
+
# Input:
|
235
|
+
# None.
|
236
|
+
#
|
237
|
+
# Output:
|
238
|
+
# returns -1 on error else 0 on success.
|
239
|
+
#
|
240
|
+
###############################################################################
|
241
|
+
def SodaFireFox.KillProcesses()
|
242
|
+
os = nil
|
243
|
+
err = 0
|
244
|
+
|
245
|
+
os = SodaUtils.GetOsType()
|
246
|
+
case (os)
|
247
|
+
when /linux/i
|
248
|
+
err = KillProcessUnix()
|
249
|
+
when /windows/i
|
250
|
+
err = KillProcessWindows()
|
251
|
+
end
|
252
|
+
|
253
|
+
return err
|
254
|
+
|
255
|
+
end
|
256
|
+
|
119
257
|
end # end module #
|
120
258
|
|
data/lib/SodaReportSummery.rb
CHANGED
@@ -198,7 +198,6 @@ def GenerateReportData(files)
|
|
198
198
|
|
199
199
|
return test_info
|
200
200
|
end
|
201
|
-
|
202
201
|
private :GenerateReportData
|
203
202
|
|
204
203
|
###############################################################################
|
@@ -330,16 +329,13 @@ table
|
|
330
329
|
<tr class="tr_header">
|
331
330
|
\t<td>Test File:<br>
|
332
331
|
\tClick link for full report</td>
|
333
|
-
\t<td>Test Count:</td>
|
334
|
-
\t<td>Test Skip Count:</td>
|
335
|
-
\t<td>Failure Count:</td>
|
332
|
+
\t<td>Test Failure Count:</td>
|
336
333
|
\t<td>CSS Error Count:</td>
|
337
334
|
\t<td>JavaScript Error Count:</td>
|
338
335
|
\t<td>Assert Failures:</td>
|
339
336
|
\t<td>Event Count:</td>
|
340
337
|
\t<td>Assert Count:</td>
|
341
338
|
\t<td>Exceptions:</td>
|
342
|
-
\t<td>Major Exceptions:</td>
|
343
339
|
\t<td>Running Time:<br>(hh:mm:ss):</td>
|
344
340
|
</tr>
|
345
341
|
HTML
|
@@ -361,8 +357,6 @@ HTML
|
|
361
357
|
rpt['report_hash']['Test Assert Count'].to_i()
|
362
358
|
totals['Test Exceptions'] +=
|
363
359
|
rpt['report_hash']['Test Exceptions'].to_i()
|
364
|
-
totals['Test Major Exceptions'] +=
|
365
|
-
rpt['report_hash']['Test Major Exceptions'].to_i()
|
366
360
|
totals['Test Count'] += rpt['report_hash']['Test Count'].to_i()
|
367
361
|
totals['Test Skip Count'] += rpt['report_hash']['Test Skip Count'].to_i()
|
368
362
|
|
@@ -407,8 +401,6 @@ HTML
|
|
407
401
|
"onMouseOver=\"this.className='highlight'\" "+
|
408
402
|
"onMouseOut=\"this.className='tr_normal'\">\n" +
|
409
403
|
"\t<td class=\"td_file\">#{log_file_td}</td>\n" +
|
410
|
-
"\t<td>#{rpt['report_hash']['Test Count']}</td>\n"+
|
411
|
-
"\t<td>#{rpt['report_hash']['Test Skip Count']}</td>\n"+
|
412
404
|
"\t<td>#{rpt['report_hash']['Test Failure Count']}</td>\n"+
|
413
405
|
"\t<td>#{rpt['report_hash']['Test CSS Error Count']}</td>\n" +
|
414
406
|
"\t<td>#{rpt['report_hash']['Test JavaScript Error Count']}</td>\n" +
|
@@ -416,7 +408,6 @@ HTML
|
|
416
408
|
"\t<td>#{rpt['report_hash']['Test Event Count']}</td>\n" +
|
417
409
|
"\t<td>#{rpt['report_hash']['Test Assert Count']}</td>\n" +
|
418
410
|
"\t<td>#{rpt['report_hash']['Test Exceptions']}</td>\n" +
|
419
|
-
"\t<td>#{rpt['report_hash']['Test Major Exceptions']}</td>\n" +
|
420
411
|
"\t<td>#{hours}:#{minutes}:#{seconds}</td>\n</tr>\n"
|
421
412
|
fd.write(str)
|
422
413
|
end
|
@@ -440,8 +431,6 @@ HTML
|
|
440
431
|
test_totals = totals['Test Count'] + totals['Test Skip Count']
|
441
432
|
sub_totals = "<tr class=\"tr_header\">\n"+
|
442
433
|
"\t<td>Totals:</td>\n"+
|
443
|
-
"\t<td>#{totals['Test Count']}</td>\n"+
|
444
|
-
"\t<td>#{totals['Test Skip Count']}</td>\n"+
|
445
434
|
"\t<td>#{totals['Test Failure Count']}</td>\n"+
|
446
435
|
"\t<td>#{totals['Test CSS Error Count']}</td>\n"+
|
447
436
|
"\t<td>#{totals['Test JavaScript Error Count']}</td>\n"+
|
@@ -449,12 +438,11 @@ HTML
|
|
449
438
|
"\t<td>#{totals['Test Event Count']}</td>\n"+
|
450
439
|
"\t<td>#{totals['Test Assert Count']}</td>\n"+
|
451
440
|
"\t<td>#{totals['Test Exceptions']}</td>\n"+
|
452
|
-
"\t<td>#{totals['Test Major Exceptions']}</td>\n"+
|
453
441
|
"\t<td>#{hours}:#{minutes}:#{seconds}</td>\n"+
|
454
|
-
"</tr>\n"
|
455
|
-
"<tr class=\"tr_header\">\n"+
|
456
|
-
"\t<td>Total Test Count:</td>\n"+
|
457
|
-
"\t<td colspan=\"2\">#{test_totals}</td>\n</tr>\n"
|
442
|
+
"</tr>\n"
|
443
|
+
# "<tr class=\"tr_header\">\n"+
|
444
|
+
# "\t<td>Total Test Count:</td>\n"+
|
445
|
+
# "\t<td colspan=\"2\">#{test_totals}</td>\n</tr>\n"
|
458
446
|
|
459
447
|
fd.write(sub_totals)
|
460
448
|
fd.write("</table>\n</body>\n</html>\n")
|