puppet7 0.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,292 @@
1
+ # coding: utf-8
2
+ require "erb"
3
+ require "puppet7/common"
4
+
5
+ module Puppet7
6
+ def self.report
7
+ @report ||= Puppet7::PuppetReport.new
8
+ end
9
+
10
+ class PuppetReport
11
+ include ERB::Util
12
+
13
+ def initialize
14
+ @top_level = []
15
+ @current_example_group = nil
16
+ @cur_depth = 0
17
+ @max_depth = 0
18
+
19
+ @image_errors = {}
20
+ @js_errors = {}
21
+ @undefined_object = {}
22
+
23
+ # summary
24
+ @example_summary = {total: 0, passed: 0, failed: 0, pending: 0}
25
+ @test_summary = {total: 0, passed: 0, failed: 0, not_tested: 0, partial_passed: 0, automation_rate: 0, pass_rate: 0}
26
+
27
+ # for print
28
+ @example_group_stack = []
29
+ end
30
+
31
+
32
+ def write_report output
33
+ make_summary
34
+ output.write apply_template :puppet_report, binding
35
+ end
36
+
37
+ def start_example_group example_group
38
+ @cur_depth += 1
39
+
40
+ siblings = []
41
+ if @current_example_group
42
+ siblings.concat @current_example_group.example_groups.select{|exg| exg.description == example_group.description}
43
+ else
44
+ siblings.concat @top_level.select{|exg| exg.description == example_group.description}
45
+ end
46
+
47
+ if siblings.empty?
48
+ ex_group = ExampleGroup.new(example_group, @current_example_group, @cur_depth)
49
+ @top_level << ex_group unless @current_example_group
50
+ else
51
+ ex_group = siblings.first
52
+ end
53
+ @current_example_group = ex_group
54
+ @max_depth = [@max_depth, @cur_depth].max
55
+ end
56
+
57
+ def end_example_group example_group
58
+ unless example_group.description == @current_example_group.description
59
+ raise "Nested Example Groups are something wrong!"
60
+ end
61
+ @current_example_group = @current_example_group.parent_group
62
+ @cur_depth -= 1
63
+ end
64
+
65
+ def add_example example
66
+ Example.new(example, @current_example_group)
67
+ end
68
+
69
+ def add_image_errors page_url, image_urls
70
+ @image_errors[page_url.to_sym] ||= []
71
+ @image_errors[page_url.to_sym].concat(image_urls)
72
+ @image_errors[page_url.to_sym].uniq!
73
+ end
74
+
75
+ def add_js_errors page_url, js_errors
76
+ js_errors.select! {|err| err[:url] and err[:line]}
77
+ return if js_errors.empty?
78
+ @js_errors[page_url.to_sym] ||= []
79
+ @js_errors[page_url.to_sym].concat(js_errors)
80
+ @js_errors[page_url.to_sym].uniq!
81
+ end
82
+
83
+ def add_undefined_object type, name
84
+ @undefined_object[type.to_sym] ||= []
85
+ @undefined_object[type.to_sym] << name
86
+ @undefined_object[type.to_sym].uniq!
87
+ end
88
+
89
+ private
90
+ def make_summary
91
+ leaf_ex_groups = @top_level.collect{|exg| exg.get_leaf_example_groups}.flatten
92
+ leaf_ex_groups.each do |exg|
93
+ @test_summary[:total] += 1
94
+ @test_summary[exg.status] +=1
95
+ end
96
+
97
+ @test_summary[:automation_rate] =
98
+ (@test_summary[:total]-@test_summary[:not_tested]) * 100 / @test_summary[:total] if @test_summary[:total] > 0
99
+ @test_summary[:pass_rate] =
100
+ (@test_summary[:passed]) * 100 / (@test_summary[:total]-@test_summary[:not_tested]) if (@test_summary[:total]-@test_summary[:not_tested]) > 0
101
+
102
+ @top_level.collect{|exg| exg.all_examples}.flatten.each do |ex|
103
+ @example_summary[:total] += 1
104
+ @example_summary[ex.status] += 1
105
+ end
106
+ end
107
+
108
+ def example_group_result example_group
109
+ begin
110
+ @example_group_stack << example_group
111
+ apply_template :_example_group, binding
112
+ ensure
113
+ @example_group_stack.pop
114
+ end
115
+ end
116
+
117
+ def example_results
118
+ apply_template :_examples, binding
119
+ end
120
+
121
+ def apply_template template_name, _binding
122
+ template = ERB.new(read_template template_name)
123
+ template.result(_binding)
124
+ end
125
+
126
+ def read_template name
127
+ template_file = File.join(File.dirname(__FILE__), "report", "#{name}.erb")
128
+ if File.exist?(template_file)
129
+ File.read(template_file)
130
+ else
131
+ raise "Can't find the report template file : #{template_file}"
132
+ end
133
+ end
134
+ end
135
+
136
+ class ExampleGroup
137
+ attr_reader :description, :example_groups, :examples, :parent_group, :depth, :status, :no
138
+ @@no = 0
139
+ def self.no
140
+ @@no
141
+ end
142
+ def initialize example_group, parent_group, depth
143
+ @description = example_group.description
144
+ @example_groups = []
145
+ @examples = []
146
+ @parent_group = parent_group
147
+ @parent_group.example_groups << self if @parent_group
148
+ @depth = depth
149
+ @no = @@no += 1
150
+ end
151
+
152
+ def has_examples?
153
+ not @examples.empty?
154
+ end
155
+
156
+ def has_example_groups?
157
+ not @example_groups.empty?
158
+ end
159
+
160
+ def all_examples
161
+ examples = []
162
+ if has_example_groups?
163
+ @example_groups.each do |exg|
164
+ examples.concat exg.all_examples
165
+ end
166
+ else
167
+ examples.concat @examples
168
+ end
169
+ examples
170
+ end
171
+
172
+ def first?
173
+ if @parent_group
174
+ @parent_group.example_groups.first == self
175
+ else
176
+ true
177
+ end
178
+ end
179
+
180
+ def row_count
181
+ cnt = 0
182
+ @example_groups.each do |exg|
183
+ cnt += exg.row_count
184
+ end
185
+ [cnt, 1].max
186
+ end
187
+
188
+ def get_leaf_example_groups
189
+ if has_example_groups?
190
+ rv = []
191
+ @example_groups.each {|exg| rv.concat(exg.get_leaf_example_groups)}
192
+ rv
193
+ else
194
+ [self]
195
+ end
196
+ end
197
+
198
+ def status
199
+ return @status if @status
200
+ if has_examples?
201
+ summary = {passed: 0, failed: 0, pending:0}
202
+ @examples.inject(summary) {|r, ex| summary[ex.status] += 1}
203
+ if summary[:passed] == @examples.length
204
+ @status = :passed
205
+ elsif summary[:failed]> 0
206
+ @status = :failed
207
+ elsif summary[:passed] > 0
208
+ @status = :partial_passed
209
+ else
210
+ @status = :not_tested
211
+ end
212
+ elsif has_example_groups?
213
+ summary = {passed: 0, failed: 0, not_tested:0, partial_passed:0}
214
+ @example_groups.inject(summary) {|r,exg| summary[exg.status] +=1 }
215
+ if summary[:passed] == @example_groups.length
216
+ @status = :passed
217
+ elsif summary[:failed] > 0
218
+ @status = :failed
219
+ elsif summary[:passed] + summary[:partial_passed] > 0
220
+ @status = :partial_passed
221
+ else
222
+ @status = :not_tested
223
+ end
224
+ else
225
+ @status = :not_tested
226
+ end
227
+ @status
228
+ end
229
+
230
+ end
231
+
232
+ class Example
233
+ attr_reader :description, :status, :pending_message, :parent_group, :no
234
+ @@no = 0
235
+ def self.no
236
+ @@no
237
+ end
238
+
239
+ def initialize example, parent_group
240
+ @example = example
241
+ @description = example.description
242
+ @parent_group = parent_group
243
+ @parent_group.examples << self
244
+ @no = @@no += 1
245
+ end
246
+
247
+ def code_where
248
+ "in #{@example.metadata[:file_path]}:#{@example.metadata[:line_number]}"
249
+ end
250
+
251
+ def source_code
252
+ src_file = @example.metadata[:file_path]
253
+ line = @example.metadata[:line_number]
254
+ if File.file?(src_file)
255
+ lines = File.open(src_file).read.split("\n")
256
+ min = [0, line-1].max
257
+ unless lines[min].chomp.end_with?("do")
258
+ return "#{min+1}:#{lines[min]}"
259
+ end
260
+ indents = indent_cnt lines[min]
261
+ ln = min + 1
262
+ while indents != indent_cnt(lines[ln]) and ln < lines.length do
263
+ ln += 1
264
+ end
265
+ lines[min..ln].collect {|l| "#{min+=1}:" + l}.join("\n")
266
+ else
267
+ "# Couldn't get source code : #{src_file}"
268
+ end
269
+ end
270
+
271
+ def status
272
+ @example.metadata[:execution_result][:status].to_sym
273
+ end
274
+
275
+ def pending_message
276
+ @example.metadata[:execution_result][:pending_message]
277
+ end
278
+
279
+ def exception_message
280
+ @example.metadata[:execution_result][:exception]
281
+ end
282
+
283
+ private
284
+ def indent_cnt line
285
+ if line =~ /^(\s*)[^\s]/
286
+ $1.length
287
+ else
288
+ 0
289
+ end
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,24 @@
1
+ <%# coding: utf-8%>
2
+ <% exgroup = @example_group_stack.last %>
3
+ <%unless exgroup.first? and exgroup.depth != 1%>
4
+ <tr>
5
+ <%end%>
6
+ <% (@max_depth - exgroup.depth).times do %>
7
+ <td class="<%=exgroup.status%>_result"> &nbsp; </td>
8
+ <%end unless exgroup.has_example_groups?%>
9
+ <td rowspan="<%=exgroup.row_count%>" class="<%=exgroup.status%>_result">
10
+ <%=h(exgroup.description)%>
11
+ <% if exgroup.has_example_groups? %>
12
+ </td>
13
+ <%# print sub example group %>
14
+ <% exgroup.example_groups.each do |ex_group|%>
15
+ <%=example_group_result(ex_group)%>
16
+ <%end%>
17
+ <%else%>
18
+ <%# print examples%>
19
+ <%=example_results%>
20
+ </td>
21
+ <%end%>
22
+ <%unless exgroup.has_example_groups? and exgroup.depth != 1%>
23
+ </tr>
24
+ <%end%>
@@ -0,0 +1,22 @@
1
+ <%# coding: utf-8%>
2
+ <% exgroup = @example_group_stack.last %>
3
+ <table class="examples_table">
4
+ <% exgroup.examples.each do |ex| %>
5
+ <tr>
6
+ <td class="<%=ex.status%>">
7
+ # <%=h(ex.description)%>
8
+ <%if ex.status == :pending %>
9
+ (PENDING: <%=h ex.pending_message%>)
10
+ <%end%>
11
+ <span class="view_script_btn" id="viewbutton<%=ex.no%>"></span>
12
+ <div class="test_script" id="testscript<%=ex.no%>" style="display:<%= ex.status == :failed ? "":"none"%>">
13
+ <code class="code_where">
14
+ <%=h ex.code_where%>
15
+ <pre><%=h ex.exception_message%></pre>
16
+ </code>
17
+ <pre class="source_code"><%=h ex.source_code%></pre>
18
+ </div>
19
+ </td>
20
+ </tr>
21
+ <% end %>
22
+ </table>
@@ -0,0 +1,187 @@
1
+ <%# codnig: utf-8%>
2
+ <?xml version="1.0" encoding="UTF-8"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Checklist & Test Result</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
10
+ <meta http-equiv="Expires" content="-1" />
11
+ <meta http-equiv="Pragma" content="no-cache" />
12
+ <style type="text/css">
13
+ * {margin:0;padding:0;font-size:9pt;}
14
+ h1 {font-size: 2em; font-weight:bold; font-family:serif}
15
+ h2 {font-size: 1.5em; font-weight:bold; font-family:serif; color: red}
16
+ #header {margin: 1em;}
17
+ #content {margin: 1em;}
18
+ #control {}
19
+ #test_result {}
20
+ #footer {margin: 1em;text-align: right}
21
+ #summary {margin: 0.5em 1em;}
22
+
23
+ .cont {color:#0033FF}
24
+
25
+ .question {color: #FF3300; font-style:italic;font-weight: bold;}
26
+ .confirm {color: #0033FF; font-style:italic;font-weight: bold;}
27
+ .show_tc {color: #888; font-style:italic;}
28
+
29
+ .pending {background-color: #FFFF99; color:black;font-size: 0.9em;}
30
+ .passed {background-color: #ddFFaa; color:black;font-size: 0.9em;}
31
+ .failed {background-color: #FFaa99; color:black;font-size: 0.9em;}
32
+
33
+ .summary {font-weight: bold; color:black; padding: 2px;line-height: 1.5em;}
34
+
35
+ .passed_result {background-color: #ddFFaa; }
36
+ .failed_result {background-color: #FFaa99; }
37
+ .partial_passed_result {background-color: #FFFFDD; }
38
+ .not_tested_result {background-color: #EDEDED; }
39
+
40
+ .passed_text {color: #33aa33; }
41
+ .failed_text {color: #FF3300; }
42
+ .pending_text {color: #444444;}
43
+
44
+ .view_script_btn {color: #337; font-style: italic; cursor: pointer}
45
+ .code_where {display: block;background-color:#ace;color:#337; padding: 3px;margin-top:3px;}
46
+ .source_code {background-color:black;color:#aaa;padding: 3px;margin-bottom:-4px;}
47
+
48
+ table {width:100%; border-collapse:collapse;cellspacing:0; cellpadding:0;padding:0;margin:0;}
49
+ th {border:1px solid gray; padding: 3px 1em; font-weight:bold; background-color:#AAA}
50
+ td {border:1px solid gray; padding: 3px 1em;}
51
+
52
+ td.exgrp_title {padding: 3px 1.5em; border-bottom:0;}
53
+ td.exgrp_detail {border-top:0;width: 10px;text-align:center; font-size:0.9em;}
54
+ td.exgrp_child {width: 10px; border:0;}
55
+ td.ex_result {padding:3px; }
56
+ td.ex_desc {padding: 3px 10px;background-color: #FDFDFD}
57
+
58
+ table.examples_table {
59
+ margin: 3px 0 -4px 0;
60
+ }
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <div id="header">
65
+ <h1>Checklist &amp; Test Result</h1>
66
+ </div>
67
+ <div id="content">
68
+ <div id="control"></div>
69
+ <div id="test_result">
70
+ <div id="summary">
71
+ <span class="summary">Automation rate: <%=@test_summary[:automation_rate]%> %</span>
72
+ <span class="summary">Pass rate: <%=@test_summary[:pass_rate]%> %</span>
73
+ <br/>
74
+ <span class="summary">Checklist Total: <%=@test_summary[:total]%> </span> (
75
+ <span class="summary passed_result"> Passed:<%=@test_summary[:passed]%> </span>
76
+ <span class="summary failed_result"> Failed:<%=@test_summary[:failed]%> </span>
77
+ <span class="summary partial_passed_result"> Partial passed:<%=@test_summary[:partial_passed]%> </span>
78
+ <span class="summary not_tested_result"> Not Tested:<%=@test_summary[:not_tested]%> </span> )
79
+ <br/>
80
+ <span class="summary">Example Total: <%=@example_summary[:total]%> </span> (
81
+ <span class="summary passed"> Passed:<%=@example_summary[:passed]%> </span>
82
+ <span class="summary failed"> Failed:<%=@example_summary[:failed]%> </span>
83
+ <span class="summary pending"> Pending:<%=@example_summary[:pending]%> </span>)
84
+ </div>
85
+ <table>
86
+ <tr><!--# Table Header -->
87
+ <%@max_depth.times do |i| %><th>LEVEL<%=i%></th><%end%>
88
+ </tr>
89
+ <%@top_level.each do |ex_group|%>
90
+ <%=example_group_result(ex_group)%>
91
+ <%end%>
92
+ </table>
93
+ </div>
94
+ <div class="etc_errors">
95
+ <%unless @undefined_object.empty? %>
96
+ <h2> Undefined Page Objects </h2>
97
+ <table>
98
+ <tr>
99
+ <th>Type</th><th>Undefined object and property</th>
100
+ </tr>
101
+ <%@undefined_object.each do |type, names|%>
102
+ <tr>
103
+ <td><%=h type%></td>
104
+ <td><%=h names.join("<br/>")%></td>
105
+ </tr>
106
+ <%end%>
107
+ </table>
108
+ <%end%>
109
+ </div>
110
+ <div class="etc_errors">
111
+ <%unless @image_errors.empty? %>
112
+ <h2> Loading Image Errors </h2>
113
+ <table>
114
+ <tr>
115
+ <th>Page URL</th><th>Image URLs</th>
116
+ </tr>
117
+ <%@image_errors.each do |page, images|%>
118
+ <tr>
119
+ <td><%=h page%></td>
120
+ <td><%=h images.join("<br/>")%></td>
121
+ </tr>
122
+ <%end%>
123
+ </table>
124
+ <%end%>
125
+ </div>
126
+ <div class="etc_errors">
127
+ <%unless @js_errors.empty? %>
128
+ <h2> Javascript Errors </h2>
129
+ <table>
130
+ <tr>
131
+ <th>Page URL</th><th>Error message</th>
132
+ </tr>
133
+ <%@js_errors.each do |page, errors|%>
134
+ <tr>
135
+ <td><%=h page%></td>
136
+ <td><%=errors.collect{|e| h "#{e['msg']} : file:#{e['url']}(#{e['line']})"}.join("<br/>")%></td>
137
+ </tr>
138
+ <%end%>
139
+ </table>
140
+ <%end%>
141
+ </div>
142
+ </div>
143
+
144
+ <div id="footer">Powered by <strong>puppet7</strong>. made by yunsang.choi@nhn.com</div>
145
+
146
+ <script type="text/javascript">
147
+ var exg_cnt = <%=ExampleGroup.no%>;
148
+ var ex_cnt = <%=Example.no%>;
149
+
150
+ for(var i=1; i <= ex_cnt; i++) {
151
+ var content = document.getElementById('testscript'+i);
152
+ if(content == null) continue ;
153
+ var btn = document.getElementById('viewbutton'+i);
154
+ if(content.style.display == "none") {
155
+ btn.innerHTML = "[show script]";
156
+ btn.onclick = get_show_script_func(i, true);
157
+ } else {
158
+ btn.innerHTML = "[hide script]";
159
+ btn.onclick = get_show_script_func(i, false);
160
+ }
161
+ }
162
+
163
+ function get_show_script_func(no, view) {
164
+ return function(){show_script(no, view);}
165
+ }
166
+
167
+ function show_script(no, view) {
168
+ if(no > ex_cnt) {alert(no);}
169
+ if(view == null) view = true;
170
+
171
+ var content = document.getElementById('testscript'+no);
172
+ var btn = document.getElementById('viewbutton'+no);
173
+
174
+ if (view) {
175
+ content.style.display = "";
176
+ btn.innerHTML = "[hide script]";
177
+ btn.onclick = get_show_script_func(no, false);
178
+ } else {
179
+ content.style.display = "none";
180
+ btn.innerHTML = "[show script]";
181
+ btn.onclick = get_show_script_func(no, true);
182
+ }
183
+ }
184
+
185
+ </script>
186
+ </body>
187
+ </html>
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ require "selenium/client"
4
+ require "json"
5
+
6
+ module Puppet7
7
+ module SeleniumActions
8
+ def get_stored_var name
9
+ JSON.parse get_eval("storedVars.#{name}.toJSONString();")
10
+ end
11
+
12
+ def set_stored_var name, value
13
+ get_eval("storedVars.#{name} = #{JSON.generate([value])}[0];")
14
+ end
15
+ end
16
+ end
17
+
18
+ class Selenium::Client::Driver
19
+ include Puppet7::SeleniumActions
20
+ end