friendly-cukes 0.0.1

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.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/DETAILED_DESCRIPTION.md +235 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +108 -0
  7. data/Rakefile +2 -0
  8. data/bin/build-extractor +69 -0
  9. data/bin/friendly-cukes +48 -0
  10. data/friendly-cukes.gemspec +41 -0
  11. data/lib/friendly/build_extractor.rb +647 -0
  12. data/lib/friendly/cukes.rb +29 -0
  13. data/lib/friendly/cukes/framework/Gemfile +16 -0
  14. data/lib/friendly/cukes/framework/Gemfile.lock +113 -0
  15. data/lib/friendly/cukes/framework/Rakefile.rb +19 -0
  16. data/lib/friendly/cukes/framework/config/config.yml +87 -0
  17. data/lib/friendly/cukes/framework/config/cucumber.yml +49 -0
  18. data/lib/friendly/cukes/framework/coverage/.last_run.json +5 -0
  19. data/lib/friendly/cukes/framework/coverage/.resultset.json +3519 -0
  20. data/lib/friendly/cukes/framework/coverage/.resultset.json.lock +0 -0
  21. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/jquery-1.3.2.min.js +19 -0
  22. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/jquery.tablesorter.min.js +15 -0
  23. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/print.css +12 -0
  24. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/rcov.js +42 -0
  25. data/lib/friendly/cukes/framework/coverage/rcov/assets/0.2.3/screen.css +270 -0
  26. data/lib/friendly/cukes/framework/coverage/rcov/index.html +392 -0
  27. data/lib/friendly/cukes/framework/coverage/rcov/library-app_init-app_driver_rb.html +98 -0
  28. data/lib/friendly/cukes/framework/coverage/rcov/library-app_utils-data_file_names_rb.html +65 -0
  29. data/lib/friendly/cukes/framework/coverage/rcov/library-app_utils-page_utils_rb.html +533 -0
  30. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-create_log_rb.html +521 -0
  31. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-custom_html_report_rb.html +2522 -0
  32. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-datetime_library_rb.html +296 -0
  33. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-file_library_rb.html +995 -0
  34. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-performance_report_rb.html +1613 -0
  35. data/lib/friendly/cukes/framework/coverage/rcov/library-generic-read_from_yml_rb.html +944 -0
  36. data/lib/friendly/cukes/framework/coverage/rcov/object_repository-desktop-gem_search_rb.html +773 -0
  37. data/lib/friendly/cukes/framework/coverage/rcov/object_repository-desktop-google_search_rb.html +230 -0
  38. data/lib/friendly/cukes/framework/coverage/rcov/object_repository-mobile-mobile_google_search_rb.html +230 -0
  39. data/lib/friendly/cukes/framework/coverage/rcov/step_definitions-desktop-gem_search_rb.html +188 -0
  40. data/lib/friendly/cukes/framework/coverage/rcov/step_definitions-desktop-google_search_steps_rb.html +167 -0
  41. data/lib/friendly/cukes/framework/coverage/rcov/step_definitions-mobile-mobile_google_search_steps_rb.html +167 -0
  42. data/lib/friendly/cukes/framework/coverage/rcov/support-browser_settings_rb.html +851 -0
  43. data/lib/friendly/cukes/framework/coverage/rcov/support-env_rb.html +242 -0
  44. data/lib/friendly/cukes/framework/coverage/rcov/support-hooks_rb.html +878 -0
  45. data/lib/friendly/cukes/framework/coverage/rcov/support-html_formatter_rb.html +230 -0
  46. data/lib/friendly/cukes/framework/features/desktop/google_search/google_search.feature +19 -0
  47. data/lib/friendly/cukes/framework/features/desktop/rubygems_search/gem_name_tc_04.yml +2 -0
  48. data/lib/friendly/cukes/framework/features/desktop/rubygems_search/gem_search.feature +37 -0
  49. data/lib/friendly/cukes/framework/features/desktop/test_data/gem_name.yml +2 -0
  50. data/lib/friendly/cukes/framework/features/mobile/google_search/mobile_google_search.feature +19 -0
  51. data/lib/friendly/cukes/framework/library/app_init/app_init.rb +13 -0
  52. data/lib/friendly/cukes/framework/library/app_utils/data_file_names.rb +2 -0
  53. data/lib/friendly/cukes/framework/library/app_utils/page_utils.rb +157 -0
  54. data/lib/friendly/cukes/framework/library/generic/app_logo_1.png +0 -0
  55. data/lib/friendly/cukes/framework/library/generic/create_log.rb +154 -0
  56. data/lib/friendly/cukes/framework/library/generic/custom_html_report.rb +852 -0
  57. data/lib/friendly/cukes/framework/library/generic/datetime_library.rb +79 -0
  58. data/lib/friendly/cukes/framework/library/generic/file_library.rb +311 -0
  59. data/lib/friendly/cukes/framework/library/generic/performance_report.rb +518 -0
  60. data/lib/friendly/cukes/framework/library/generic/read_from_yml.rb +294 -0
  61. data/lib/friendly/cukes/framework/object_repository/desktop/desktop_web_object_repo.rb +50 -0
  62. data/lib/friendly/cukes/framework/object_repository/mobile/mobile_web_object_repo.rb +22 -0
  63. data/lib/friendly/cukes/framework/page_objects/desktop/gem_search.rb +213 -0
  64. data/lib/friendly/cukes/framework/page_objects/desktop/google_search.rb +53 -0
  65. data/lib/friendly/cukes/framework/page_objects/mobile/mobile_google_search.rb +53 -0
  66. data/lib/friendly/cukes/framework/step_definitions/desktop/gem_search.rb +43 -0
  67. data/lib/friendly/cukes/framework/step_definitions/desktop/google_search_steps.rb +36 -0
  68. data/lib/friendly/cukes/framework/step_definitions/mobile/mobile_google_search_steps.rb +36 -0
  69. data/lib/friendly/cukes/framework/support/browser_settings.rb +264 -0
  70. data/lib/friendly/cukes/framework/support/env.rb +65 -0
  71. data/lib/friendly/cukes/framework/support/hooks.rb +274 -0
  72. data/lib/friendly/cukes/framework/support/html_formatter.rb +57 -0
  73. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/app_env.log +15 -0
  74. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/detailed_report/app_logo_1.png +0 -0
  75. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/detailed_report/desktop_gem_search.html +647 -0
  76. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/detailed_report/desktop_google_search.html +590 -0
  77. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/custom_report/report_home.html +593 -0
  78. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/desktop_rubygems_search.log +84 -0
  79. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/report_21_05_2015-11_04_54.html +472 -0
  80. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_33/report_21_05_2015-11_04_54.json +299 -0
  81. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/app_env.log +15 -0
  82. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/desktop_google_search.log +22 -0
  83. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/report_21_05_2015-11_03_49.html +472 -0
  84. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-11_03_37/report_21_05_2015-11_03_49.json +155 -0
  85. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/app_env.log +15 -0
  86. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/mobile_google_search.log +22 -0
  87. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/report_21_05_2015-17_29_26.html +472 -0
  88. data/lib/friendly/cukes/framework/test_result/test_report_21_05_2015-17_28_10/report_21_05_2015-17_29_26.json +143 -0
  89. data/lib/friendly/cukes/version.rb +61 -0
  90. metadata +309 -0
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'open-uri'
4
+ require 'irb'
5
+ require 'uri'
6
+ require 'rubygems'
7
+ require 'friendly/cukes'
8
+
9
+ encoding = nil
10
+
11
+ opts = OptionParser.new do |opts|
12
+ opts.banner = "Friendly-Cukes : a ready-to-use ruby-cucumber test automation framework for both web and mobile"
13
+ opts.define_head "Usage : friendly-cukes <uri|path> [options]"
14
+ opts.separator ""
15
+ opts.separator "Examples :"
16
+ opts.separator " test_cukes http://www.ruby-lang.org/"
17
+ opts.separator ""
18
+ opts.separator "The system and application requirements have to be setup before running the below command. Refer gem documentation for Ruby, Cucumber and Appium setup"
19
+ opts.separator ""
20
+ opts.separator "Syntax : friendly-cukes --new <test_framework_name>"
21
+ opts.separator " cd <test_framework_name>"
22
+ opts.separator " rake -T (run the rake task for executing default automation scripts else you can use the cucumber run command)"
23
+ opts.separator "Options :"
24
+
25
+ opts.on_tail("-v", "--version", "Show version") do
26
+ puts Friendly::Cukes::VersionInfo.new.version
27
+ exit
28
+ end
29
+
30
+ opts.on_tail("-?", "--help", "Show this message") do
31
+ puts opts
32
+ exit
33
+ end
34
+
35
+ opts.on_tail("-n", "--new APP", "Create new ruby-cucumber app") do |app|
36
+ Friendly::Cukes.create_app(app)
37
+ exit
38
+ end
39
+
40
+ end
41
+ opts.parse!
42
+
43
+ uri = ARGV.shift
44
+
45
+ if uri.to_s.strip.empty? && $stdin.tty?
46
+ puts opts
47
+ exit 1
48
+ end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'friendly/cukes/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "friendly-cukes"
8
+ spec.version = Friendly::Cukes::VERSION
9
+ spec.authors = ["Chandra sekaran", "Rajesh Kalaivanan"]
10
+ spec.email = ["profchan2k15@gmail.com"]
11
+ spec.summary = %q{Friendly-Cukes is a nice ruby-cucumber test automation framework for both web and mobile apps}
12
+ spec.description = %q{Friendly-Cukes is a ready-to-use ruby-cucumber automation framework for both web and mobile.
13
+ Its features includes Generic framework libraries, Object repository, Custom logging,
14
+ Custom execution reporting, Performance reporting, support for parallel execution etc}
15
+ spec.homepage = "https://github.com/Chan-Chan1/friendly-cukes"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+ spec.post_install_message = "friendly-cukes is a ready to use ruby-cucumber automation framework\nHappy testing!!!\n"
23
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.0.0")
24
+ spec.rubyforge_project = "Friendly-Cukes"
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("0.0.1")
27
+ spec.add_runtime_dependency(%q<simplecov>, ["= 0.9.2"])
28
+ spec.add_runtime_dependency(%q<page-object>, ["= 1.0.2"])
29
+ spec.add_runtime_dependency(%q<cucumber>, ["= 1.3.15"])
30
+ spec.add_runtime_dependency(%q<time_difference>, ["= 0.3.2"])
31
+ spec.add_runtime_dependency(%q<data_magic>, ["= 0.19"])
32
+ spec.add_runtime_dependency(%q<require_all>, ["= 1.3.2"])
33
+ spec.add_runtime_dependency(%q<nokogiri>, ["= 1.6.3.1"])
34
+ spec.add_runtime_dependency(%q<dbi>, ["= 0.4.5"])
35
+ spec.add_runtime_dependency(%q<dbd-sqlanywhere>, ["= 1.0.1"])
36
+ spec.add_runtime_dependency(%q<appium_lib>, ["= 4.1.0"])
37
+
38
+ spec.add_development_dependency "bundler", "~> 1.6"
39
+ spec.add_development_dependency "rake", "~> 10.0"
40
+ end
41
+ end
@@ -0,0 +1,647 @@
1
+ =begin
2
+ *Name : BuildExtractor
3
+ *Description : class that holds performance report data generator methods that works only with cucumber generated
4
+ json report files. It extracts the execution data from cucumber json files and move them into respective tables
5
+ so that those data can be populated as report for performance analysis
6
+ *Usage : -> for using this utility, the database and tables should created with the given relationships (refer doc for relations)
7
+ require 'friendly/build_extractor'
8
+ str_json_dir = './json_files'
9
+ -> the directory path separator should be '/' or '\\'
10
+ -> USE ONLY SINGLE QUOTES FOR SPECIFYING DIRECTORY PATH
11
+
12
+ str_connection_url = 'DBI:SQLAnywhere:SERVER=EHR2Aspire;DBN=PerformanceReport;UserName=dba;Password=sql'
13
+ -> here I have used SqlAnywhere as DB with Server name=E./HR2Aspire and DB name=PerformanceReport
14
+
15
+ test_execution_machine_name = 5
16
+ -> the HostData table should hold static values and it is the user who defines the execution environment
17
+ -> add host environment record manually to the HostData table and pass its primary key value as input
18
+ -> I have used primary key as host machine identifier
19
+
20
+ obj = BuildExtractor.new(str_connection_url, str_json_dir, test_execution_machine_name)
21
+ obj.save_build_data
22
+ *Author : Chandra sekaran
23
+ *Creation Date : 14/05/2015
24
+ *Updation Date :
25
+ =end
26
+
27
+ require "json"
28
+ require "dbi"
29
+
30
+ class BuildExtractor
31
+
32
+ # Description : invoked automatically when an object of the class type is created
33
+ # Author : Chandra sekaran
34
+ # Arguments :
35
+ # str_connection_url : connection url for DB
36
+ # str_directory_path : json report files directory path
37
+ # num_host_data_id : primary key of HostData table
38
+ #
39
+ def initialize(str_connection_url, str_directory_path, num_host_data_id)
40
+ @str_directory_path = str_directory_path
41
+ @num_build_duration = 0
42
+ @bool_build_passed = true
43
+ @num_feature_count = 0
44
+ @num_feature_pass_count = 0
45
+ @num_feature_fail_count = 0
46
+ @num_feature_skip_count = 0
47
+
48
+ @str_connection_url = ""
49
+ @str_user_name = ""
50
+ @str_password = ""
51
+ split_connection_url(str_connection_url)
52
+
53
+ @num_host_data_id = num_host_data_id
54
+ end
55
+
56
+ # Description : extracts connection url, username and password from the input connection url
57
+ # Author : Chandra sekaran
58
+ #
59
+ def split_connection_url(str_connection_url)
60
+ tmp_arr = str_connection_url.split(";")
61
+ num_count = 0
62
+ ["dbi"].each do |key|
63
+ if str_connection_url.downcase.include? key
64
+ tmp_arr.each do |ele|
65
+ @str_connection_url = ele.split(";").first.strip + ";" if ele.downcase.include? key
66
+ end
67
+ else num_count += 1
68
+ end
69
+ end
70
+ raise "Invalid connection url, it doesn't include dbi field : #{str_connection_url}" if num_count == ["dbi"].size
71
+ num_count = 0
72
+ ["dbn", "database", "dbname"].each do |key|
73
+ if str_connection_url.downcase.include? key
74
+ tmp_arr.each do |ele|
75
+ if ele.downcase.include? key
76
+ @str_connection_url << "DBN=" + ele.split("=").last.strip + ";"
77
+ @str_db = ele.split("=").last.strip
78
+ end
79
+ end
80
+ else num_count += 1
81
+ end
82
+ end
83
+ raise "Invalid connection url, it doesn't include database field : #{str_connection_url}" if num_count == ["dbi"].size
84
+ num_count = 0
85
+ ["uid", "userid", "username"].each do |key|
86
+ if str_connection_url.downcase.include? key
87
+ tmp_arr.each do |ele|
88
+ @str_user_name = ele.split("=").last.strip if ele.downcase.include? key
89
+ end
90
+ else num_count += 1
91
+ end
92
+ end
93
+ ["pwd", "password"].each do |key|
94
+ if str_connection_url.downcase.include? key
95
+ tmp_arr.each do |ele|
96
+ @str_password = ele.split("=").last.strip if ele.downcase.include? key
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ # Description : parses the json object saves the required execution data into Sybase DB
103
+ # Author : Chandra sekaran
104
+ #
105
+ def parse_json
106
+ @json.each_with_index do |json, index| # iterate each feature
107
+ str_feature_id, num_feature_result_id = set_feature(json["name"].to_s) # add feature name
108
+ @num_feature_count += 1
109
+ scenario_count = 0
110
+ feature_duration = 0
111
+ bool_feature_passed = true
112
+ num_scenario_pass_count = 0
113
+ num_scenario_fail_count = 0
114
+ num_scenario_skip_count = 0
115
+
116
+ json["elements"].each do |element|
117
+ # for including the first background steps duration to the first scenario background steps as Cucumber json
118
+ # report considers background for the first scenario and hence will have 0 duration for the background steps
119
+ # under first scenario and the actual duration for the background will be set for the subsequent scenarios
120
+ if index == 0
121
+ if element["keyword"] == "Background"
122
+ element["steps"].each do |step|
123
+ @arr_background_step_duration << step["result"]["duration"].to_i
124
+ @bool = true
125
+ end
126
+ end
127
+ end
128
+ num_step_pass_count = 0
129
+ num_step_fail_count = 0
130
+ num_step_skip_count = 0
131
+
132
+ if element["keyword"] == "Scenario" # take scenario for scenario level details
133
+ str_scenario_id, scenario_result_id = set_scenario(element["name"], element["tags"][0]["name"], str_feature_id) # add scenario name
134
+ # above element["tags"][0]["name"] takes the first tag which should be the scenario id (here @tc_<scenarioid>)
135
+
136
+ scenario_count += 1 # as it counts only 'Scenarios' and not 'Backgrounds'
137
+ step_count = 0
138
+ scenario_duration = 0
139
+ bool_scenario_passed = true
140
+
141
+ element["steps"].each_with_index do |step, indx| # iterate each steps of the current scenario
142
+ #num_step_id, num_step_result_id = set_step(step['keyword']+step['name'], str_scenario_id, scenario_result_id) # add step name
143
+ num_step_id = set_step(step['keyword']+step['name'], str_scenario_id, scenario_result_id) # add step name
144
+
145
+ step_count += 1
146
+ step_duration = 0
147
+ bool_step_passed = true
148
+ if (index == 0) && (indx < @arr_background_step_duration.size) && @bool
149
+ step_duration = @arr_background_step_duration[indx] # take duration from Background for the first scenario
150
+ else
151
+ step_duration = step['result']['duration'].to_i # take usual duration
152
+ @bool = false
153
+ end
154
+ scenario_duration += step_duration
155
+ if step['result']['status'] == "passed"
156
+ num_step_pass_count += 1
157
+ elsif step['result']['status'] == "failed"
158
+ num_step_fail_count += 1
159
+ elsif step['result']['status'] == "skipped"
160
+ num_step_skip_count += 1
161
+ end
162
+ bool_step_passed = ["passed", "pending"].include?(step['result']['status']) ? true : false
163
+ bool_scenario_passed &&= bool_step_passed
164
+ #puts "\t\t Step : #{step['keyword']+step['name']} - #{step_duration} - #{bool_step_passed}"
165
+ #reset_step_result(bool_step_passed, step_duration, num_step_result_id)
166
+ set_step_result_new(num_step_id, str_scenario_id, scenario_result_id, bool_step_passed, step_duration)
167
+ end
168
+ #puts "Scenario : #{element["tags"][0]["name"]} - #{element['name']} - #{scenario_duration} - #{bool_scenario_passed} - #{step_count}"
169
+ reset_scenario_result(scenario_result_id, scenario_duration, num_step_pass_count, num_step_fail_count, num_step_skip_count, bool_scenario_passed)
170
+ feature_duration += scenario_duration
171
+ bool_feature_passed &&= bool_scenario_passed
172
+
173
+ if bool_scenario_passed
174
+ num_scenario_pass_count += 1 # scenario pass count
175
+ else
176
+ if num_step_pass_count == 0 && num_step_fail_count == 0 && num_step_skip_count > 0
177
+ num_scenario_skip_count += 1 # scenario skip count
178
+ else
179
+ num_scenario_fail_count += 1 # scenario fail count
180
+ end
181
+ end
182
+
183
+ end
184
+ end
185
+ #puts "Feature : #{json['name']} - #{feature_duration} - #{bool_feature_passed} - #{scenario_count}"
186
+ reset_feature_result(feature_duration, num_scenario_pass_count, num_scenario_fail_count, num_scenario_skip_count, bool_feature_passed, num_feature_result_id)
187
+ @num_build_duration += feature_duration
188
+ @bool_build_passed &&= bool_feature_passed
189
+
190
+ if bool_feature_passed
191
+ @num_feature_pass_count += 1
192
+ else
193
+ @num_feature_fail_count += 1 # to do feature skip count
194
+ end
195
+ end
196
+ rescue Exception => ex
197
+ puts("Error while parsing JSON : #{ex}")
198
+ exit
199
+ end
200
+
201
+ # Description : sets the build data with default details into Sybase
202
+ # Author : Chandra sekaran
203
+ #
204
+ def set_build
205
+ num_host_id = get_host_data
206
+ build_name = Time.now.strftime("%d_%m_%Y-%H_%M_%S")
207
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
208
+ str_query = "insert into BuildData(BuildName,HostDataID) values (?,?)"
209
+ sth = dbh.prepare(str_query)
210
+ sth.execute(build_name, num_host_id)
211
+ sth.finish
212
+ dbh.commit
213
+ #puts "Added a record to BuildData table successfully"
214
+
215
+ str_query = "select BuildID from BuildData where BuildName='#{build_name}' and HostDataID=#{num_host_id}"
216
+ sth = dbh.prepare(str_query)
217
+ sth.execute()
218
+ @build_id = sth.fetch[0]
219
+ dbh.disconnect()
220
+ end
221
+ rescue Exception => ex
222
+ puts("Error in setting build data to BuildData table: #{ex}")
223
+ exit
224
+ end
225
+
226
+ # Description : gets the host data from Sybase based on current execution host
227
+ # Author : Chandra sekaran
228
+ # Return Arguments :
229
+ # num_host_id : primary key the host
230
+ #
231
+ def get_host_data
232
+ # as of now I took hostid primary key for getting the current host where the execution has been made
233
+ # and I took BROWSER for selecting under the assumption that each browser executes on different host machines
234
+ # if you are using some other parameter, kindly uncomment and update the required fields
235
+ #DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
236
+ # # str_query = "select HostDataID from HostData where HostName like '#{ENV['COMPUTERNAME'].downcase}' and OS like '#{ENV['OS'].downcase}' and Browser like '#{BROWSER.downcase}'"
237
+ # str_query = "select HostDataID from HostData where HostDataID=#{@num_host_data_id}"
238
+ # sth = dbh.prepare(str_query)
239
+ # sth.execute()
240
+ # num_host_id = sth.fetch[0]
241
+ # dbh.disconnect()
242
+ # $log.info("------------host id : #{num_host_id.nil?}")
243
+ # num_host_id.nil? ? 5 : num_host_id
244
+ #end
245
+ @num_host_data_id
246
+ rescue Exception => ex
247
+ puts("Error in getting host data from HostData table: #{ex}")
248
+ exit
249
+ end
250
+
251
+ # Description : resets the build data with execution details into Sybase
252
+ # Author : Chandra sekaran
253
+ # Arguments :
254
+ # num_run_length : total execution time in nanoseconds
255
+ # num_pass_count : number of features passed
256
+ # num_fail_count : number of features failed
257
+ # num_skip_count : number of features skipped
258
+ # bool_result : boolean value resembling the state of build result
259
+ #
260
+ def reset_build(num_run_length, num_pass_count, num_fail_count, num_skip_count, bool_result)
261
+ num_result = bool_result ? 1 : 0
262
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
263
+ sth = dbh.prepare("update BuildData set RunLength=?, Passes=?, Failures=?, Skips=?, Result=? where BuildID=?")
264
+ sth.execute(convert_duration(num_run_length), num_pass_count, num_fail_count, num_skip_count, num_result, @build_id)
265
+ sth.finish
266
+ dbh.commit
267
+ #puts "Updated a record (#{@build_id}) in BuildData table successfully"
268
+ dbh.disconnect()
269
+ end
270
+ rescue Exception => ex
271
+ puts("Error in resetting build data to BuildData table: #{ex}")
272
+ exit
273
+ end
274
+
275
+ # Description : sets the feature data with default details into Sybase
276
+ # Author : Chandra sekaran
277
+ # Arguments :
278
+ # str_feature_name : feature name
279
+ # Return Arguments :
280
+ # num_feature_id : primary key the feature
281
+ # num_feature_result_id : primary key of the feature result
282
+ #
283
+ def set_feature(str_feature_name)
284
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
285
+ str_query = "select TestFeatureID from TestFeature where FeatureName=?"
286
+ sth = dbh.prepare(str_query)
287
+ sth.execute(str_feature_name)
288
+
289
+ if sth.fetch.nil? # insert only if the data is not present in the table
290
+ sth = dbh.prepare("insert into TestFeature(FeatureName) values (?)")
291
+ sth.execute(str_feature_name)
292
+ dbh.commit
293
+ #puts "Added a record to TestFeature table successfully"
294
+ end
295
+ str_query = "select TestFeatureID from TestFeature where FeatureName='#{str_feature_name}'"
296
+ sth = dbh.prepare(str_query)
297
+ sth.execute()
298
+ num_feature_id = sth.fetch[0]
299
+ #puts "********** Record found with Primary key '#{num_feature_id}' in TestFeature *************"
300
+ dbh.disconnect()
301
+ num_feature_result_id = set_feature_result(num_feature_id)
302
+ return num_feature_id, num_feature_result_id # return the feature id and feature result id of the feature
303
+ end
304
+ rescue Exception => ex
305
+ puts("Error in setting feature data to TestFeature table : #{ex}")
306
+ exit
307
+ end
308
+
309
+ # Description : sets the feature result data with default details into Sybase
310
+ # Author : Chandra sekaran
311
+ # Arguments :
312
+ # str_feature_name : feature_id of the feature
313
+ # Return Arguments :
314
+ # num_feature_result_id : primary key of the feature result
315
+ #
316
+ def set_feature_result(num_feature_id)
317
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
318
+ str_query = "select TestFeatureResultID from TestFeatureResult where TestFeatureID=? and BuildID=?"
319
+ sth = dbh.prepare(str_query)
320
+ sth.execute(num_feature_id, @build_id)
321
+
322
+ if sth.fetch.nil? # insert only if the data is not present in the table
323
+ sth = dbh.prepare("insert into TestFeatureResult(TestFeatureID,BuildID) values (?,?)")
324
+ sth.execute(num_feature_id, @build_id)
325
+ dbh.commit
326
+ #puts "Added a record to TestFeatureResult table successfully"
327
+ end
328
+
329
+ str_query = "select TestFeatureResultID from TestFeatureResult where TestFeatureID=#{num_feature_id} and BuildID=#{@build_id}"
330
+ sth = dbh.prepare(str_query)
331
+ sth.execute()
332
+ num_feature_result_id = sth.fetch[0]
333
+ #puts "********** Record found with Primary key '#{num_feature_result_id}' in TestFeatureResult *************"
334
+ dbh.disconnect()
335
+ return num_feature_result_id # return the feature result id of the feature
336
+ end
337
+ rescue Exception => ex
338
+ puts("Error in setting feature result data to TestFeatureResult table : #{ex}")
339
+ exit
340
+ end
341
+
342
+ # Description : resets the feature result data with execution details into Sybase
343
+ # Author : Chandra sekaran
344
+ # Arguments :
345
+ # num_run_length : feature execution time in nanoseconds
346
+ # num_pass_count : number of scenarios passed
347
+ # num_fail_count : number of scenarios failed
348
+ # num_skip_count : number of scenarios skipped
349
+ # bool_result : boolean value resembling the state of build result
350
+ # num_feature_result_id : primary key of the TestFeatureResult table
351
+ #
352
+ def reset_feature_result(num_run_length, num_pass_count, num_fail_count, num_skip_count, bool_result, num_feature_result_id)
353
+ num_result = bool_result ? 1 : 0
354
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
355
+ sth = dbh.prepare("update TestFeatureResult set RunLength=?, Passes=?, Failures=?, Skips=?, Result=? where TestFeatureResultID=?")
356
+ sth.execute(convert_duration(num_run_length), num_pass_count, num_fail_count, num_skip_count, num_result, num_feature_result_id)
357
+ sth.finish
358
+ dbh.commit
359
+ #puts "Updated a record (#{num_feature_result_id}) in TestFeatureResult table successfully"
360
+ dbh.disconnect()
361
+ end
362
+ rescue Exception => ex
363
+ puts("Error in resetting feature result data to TestFeatureResult table : #{ex}")
364
+ exit
365
+ end
366
+
367
+ # Description : sets the scenario data with default details into Sybase
368
+ # Author : Chandra sekaran
369
+ # Arguments :
370
+ # str_scenario_name : scenario name
371
+ # str_qa_complete_id : QA Complete ID (Scenario ID) of the scenario
372
+ # str_feature_id : primary key of the feature
373
+ # Return Arguments :
374
+ # num_scenario_id : primary key of the scenario
375
+ # scenario_result_id : primary key of the scenario result
376
+ #
377
+ def set_scenario(str_scenario_name, str_qa_complete_id, str_feature_id)
378
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
379
+ str_query = "select TestScenarioID from TestScenario where ScenarioName=? and TestFeatureID=?"
380
+ sth = dbh.prepare(str_query)
381
+ sth.execute(str_scenario_name, str_feature_id.to_i)
382
+
383
+ if sth.fetch.nil? # insert only if the data is not present in the table
384
+ sth = dbh.prepare("insert into TestScenario(ScenarioName,QACompleteID,TestFeatureID) values (?,?,?)")
385
+ sth.execute(str_scenario_name, str_qa_complete_id, str_feature_id.to_i)
386
+ sth.finish
387
+ dbh.commit
388
+ #puts "Added a record to TestScenario table successfully"
389
+ end
390
+
391
+ str_query = "select TestScenarioID from TestScenario where ScenarioName='#{str_scenario_name}' and TestFeatureID=#{str_feature_id}"
392
+ sth = dbh.prepare(str_query)
393
+ sth.execute()
394
+ num_scenario_id = sth.fetch[0]
395
+ #puts "********** Record found with Primary key '#{num_scenario_id}' in TestScenario *************"
396
+ scenario_result_id = set_scenario_result(num_scenario_id, str_feature_id)
397
+ dbh.disconnect()
398
+ return num_scenario_id, scenario_result_id # return the scenario id and scenario result id of the scenario
399
+ end
400
+ rescue Exception => ex
401
+ puts("Error in setting scenario data to TestScenario table : #{ex}")
402
+ exit
403
+ end
404
+
405
+ # Description : sets the scenario result data with default details into Sybase
406
+ # Author : Chandra sekaran
407
+ # Arguments :
408
+ # num_scenario_id : primary key of the scenario
409
+ # num_feature_id : primary key of the feature
410
+ # Return Arguments :
411
+ # num_scenario_result_id : primary key of the scenario result
412
+ #
413
+ def set_scenario_result(num_scenario_id, num_feature_id)
414
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
415
+ sth = dbh.prepare("insert into TestScenarioResult(TestFeatureID,TestScenarioID,BuildID) values (?,?,?)")
416
+ sth.execute(num_feature_id, num_scenario_id, @build_id)
417
+ sth.finish
418
+ dbh.commit
419
+ #puts "Added a record to TestScenarioResult table successfully"
420
+
421
+ str_query = "select TestScenarioResultID from TestScenarioResult where TestFeatureID=#{num_feature_id} and TestScenarioID=#{num_scenario_id} and BuildID=#{@build_id}"
422
+ sth = dbh.prepare(str_query)
423
+ sth.execute()
424
+ num_scenario_result_id = sth.fetch[0]
425
+ #puts "********** Record found with Primary key '#{num_scenario_result_id}' in TestScenarioResult *************"
426
+ dbh.disconnect()
427
+ return num_scenario_result_id # return the scenario id of the scenario
428
+ end
429
+ rescue Exception => ex
430
+ puts("Error in setting scenario data to TestScenarioResult table : #{ex}")
431
+ exit
432
+ end
433
+
434
+ # Description : resets the scenario result data with execution details into Sybase
435
+ # Author : Chandra sekaran
436
+ # Arguments :
437
+ # num_scenario_result_id : primary key of the scenario result
438
+ # num_run_length : steps execution time in nanoseconds
439
+ # num_pass_count : number of steps passed
440
+ # num_fail_count : number of steps failed
441
+ # num_skip_count : number of steps skipped
442
+ # bool_result : boolean value resembling the state of steps result
443
+ #
444
+ def reset_scenario_result(num_scenario_result_id, num_run_length, num_pass_count, num_fail_count, num_skip_count, bool_result)
445
+ num_result = bool_result ? 1 : 0
446
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
447
+ sth = dbh.prepare("update TestScenarioResult set RunLength=?, Passes=?, Failures=?, Skips=?, Result=? where TestScenarioResultID=?")
448
+ sth.execute(convert_duration(num_run_length), num_pass_count, num_fail_count, num_skip_count, num_result, num_scenario_result_id)
449
+ sth.finish
450
+ dbh.commit
451
+ #puts "Updated a record (#{num_scenario_result_id}) in TestScenarioResult table successfully"
452
+ dbh.disconnect()
453
+ end
454
+ rescue Exception => ex
455
+ puts("Error in resetting scenario data to TestScenarioResult table : #{ex}")
456
+ exit
457
+ end
458
+
459
+ # Description : sets the step data with default details into Sybase
460
+ # Author : Chandra sekaran
461
+ # Arguments :
462
+ # str_step_name : step name
463
+ # str_scenario_id : primary key of scenario
464
+ # num_scenario_result_id : primary key of scenario result
465
+ # Return Arguments :
466
+ # num_step_id : primary key of step
467
+ # num_step_result_id : primary key of step result
468
+ #
469
+ def set_step(str_step_name, str_scenario_id, num_scenario_result_id)
470
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
471
+ str_query = "select TestStepID from TestStep where StepName=? and TestScenarioID=?"
472
+ sth = dbh.prepare(str_query)
473
+ sth.execute(str_step_name, str_scenario_id)
474
+
475
+ if sth.fetch.nil? # insert only if the data is not present in the table
476
+ sth = dbh.prepare("insert into TestStep(StepName,TestScenarioID) values (?,?)")
477
+ sth.execute(str_step_name, str_scenario_id)
478
+ dbh.commit
479
+ #puts "Added a record to TestStep table successfully"
480
+ end
481
+
482
+ str_query = "select TestStepID from TestStep where StepName='#{str_step_name}' and TestScenarioID=#{str_scenario_id}"
483
+ sth = dbh.prepare(str_query)
484
+ sth.execute()
485
+ num_step_id = sth.fetch[0]
486
+ #puts "********** Record found with Primary key '#{num_step_id}' in TestStep *************"
487
+ dbh.disconnect()
488
+ return num_step_id
489
+ end
490
+ rescue Exception => ex
491
+ puts("Error in setting step data to TestStep table : #{ex}")
492
+ exit
493
+ end
494
+
495
+ # Description : sets the step result data with execution details into Sybase
496
+ # Author : Chandra sekaran
497
+ # Arguments :
498
+ # num_step_id : primary key of step
499
+ # num_scenario_id : primary key of scenario
500
+ # num_scenario_result_id : primary key of scenario result
501
+ # bool_result : boolean value resembling the state of step result
502
+ # num_run_length : steps execution time in nanoseconds
503
+ #
504
+ def set_step_result_new(num_step_id, num_scenario_id, num_scenario_result_id, bool_result, num_run_length)
505
+ num_result = bool_result ? 1 : 0
506
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
507
+ sth = dbh.prepare("insert into TestStepResult(TestScenarioResultID,Result,RunLength,TestStepID,BuildID,TestScenarioID) values (?,?,?,?,?,?)")
508
+ sth.execute(num_scenario_result_id, num_result, convert_duration(num_run_length), num_step_id, @build_id, num_scenario_id)
509
+ dbh.commit
510
+ dbh.disconnect()
511
+ #puts "Added a record to TestStepResult table successfully"
512
+ end
513
+ rescue Exception => ex
514
+ puts("(set_step_result_new)Error in setting step data to TestStepResult table : #{ex}")
515
+ exit
516
+ end
517
+
518
+ # Description : sets the step result data with default details into Sybase
519
+ # Author : Chandra sekaran
520
+ # Arguments :
521
+ # num_step_id : primary key of step
522
+ # str_scenario_id : primary key of scenario
523
+ # num_scenario_result_id : primary key of scenario result
524
+ # Return Arguments :
525
+ # num_step_result_id : primary key of step result
526
+ #
527
+ def set_step_result(num_step_id, num_scenario_id, num_scenario_result_id)
528
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
529
+ sth = dbh.prepare("insert into TestStepResult(TestScenarioResultID,TestStepID,BuildID,TestScenarioID) values (?,?,?,?)")
530
+ sth.execute(num_scenario_result_id, num_step_id, @build_id, num_scenario_id)
531
+ dbh.commit
532
+ #puts "Added a record to TestStepResult table successfully"
533
+
534
+ str_query = "select TestStepResultID from TestStepResult where TestScenarioResultID=#{num_scenario_result_id} and TestStepID=#{num_step_id} and BuildID=#{@build_id} and TestScenarioID=#{num_scenario_id}"
535
+ sth = dbh.prepare(str_query)
536
+ sth.execute()
537
+ num_step_result_id = sth.fetch[0]
538
+ #puts "********** Record found with Primary key '#{num_step_result_id}' in TestStepResult *************"
539
+ dbh.disconnect()
540
+ return num_step_result_id # return the step result id of the step
541
+ end
542
+ rescue Exception => ex
543
+ puts("Error in setting step data to TestStep table : #{ex}")
544
+ exit
545
+ end
546
+
547
+ # Description : resets the step result data with execution details into Sybase
548
+ # Author : Chandra sekaran
549
+ # Arguments :
550
+ # bool_result : boolean value resembling the state of step result
551
+ # num_run_length : step execution time in nanoseconds
552
+ # num_step_result_id : primary key of step result
553
+ #
554
+ def reset_step_result(bool_result, num_run_length, num_step_result_id)
555
+ num_result = bool_result ? 1 : 0
556
+ DBI.connect(@str_connection_url, @str_user_name, @str_password) do |dbh|
557
+ sth = dbh.prepare("update TestStepResult set Result=?, RunLength=? where TestStepResultID=?")
558
+ sth.execute(num_result, convert_duration(num_run_length), num_step_result_id)
559
+ sth.finish
560
+ dbh.commit
561
+ #puts "Updated a record (#{num_step_result_id}) in TestStepResult table successfully"
562
+ dbh.disconnect()
563
+ end
564
+ rescue Exception => ex
565
+ puts("Error in resetting step results data in TestStepResult table : #{ex}")
566
+ exit
567
+ end
568
+
569
+ # Description : converts nanoseconds to seconds
570
+ # Author : Chandra sekaran
571
+ # Arguments :
572
+ # num_duration : time in nanoseconds
573
+ # Return Argument : time in seconds
574
+ #
575
+ def convert_duration(num_duration)
576
+ num_duration/(1000*1000*1000) #.to_f # convert nanosecond to second
577
+ end
578
+
579
+ # Description : function that creates performance report data and stores it in Sybase
580
+ # Author : Chandra sekaran
581
+ #
582
+ def save_build_data
583
+ puts "Extracting build data ...\nThis might take a moment, please wait"
584
+ set_build # set Build data only once for each execution (Single or Parallel)
585
+ Dir["#{format_file_path(@str_directory_path)}/*.json"].each do |path|
586
+ puts "Extracting build execution data from '#{path}'"
587
+ @arr_background_step_duration = []
588
+ file = File.read(path)
589
+ @json = JSON.parse(file)
590
+ parse_json # parse each json file and extract report data
591
+ end
592
+ #puts "Build duration : #{@num_build_duration} - #{@bool_build_passed} - #{@num_feature_count}"
593
+ reset_build(@num_build_duration, @num_feature_pass_count, @num_feature_fail_count, @num_feature_skip_count, @bool_build_passed) # Update the Build data with execution summary
594
+ puts "\nThe build execution data for the build ID=#{@build_id} are saved into #{@str_db} DataBase successfully"
595
+ rescue Exception => ex
596
+ puts("Error while creating report : #{ex}")
597
+ exit
598
+ end
599
+
600
+ # Description : formats the file path by replacing "\" with "/"
601
+ # Author : Chandra sekaran
602
+ # Arguments :
603
+ # str_fileabs_path : absolute path of file
604
+ # Return value :
605
+ # str_file_path : formatted absolute path of file
606
+ #
607
+ def format_file_path(str_fileabs_path)
608
+ str_file_path = str_fileabs_path
609
+ str_file_path.each_char do |letter| # replace all the escape sequences
610
+ case letter
611
+ when /[\a]/
612
+ str_file_path[letter] = "/a"
613
+ when /[\e]/
614
+ str_file_path[letter] = "/e"
615
+ when /[\b]/
616
+ str_file_path[letter] = "/b"
617
+ when /[\cx]/
618
+ str_file_path[letter] = "/cx"
619
+ when /[\f]/
620
+ str_file_path[letter] = "/f"
621
+ when /[\n]/
622
+ str_file_path[letter] = "/n"
623
+ when /[\nnn]/
624
+ #str_file_path[letter] = "/nnn" # not required as \n is given
625
+ when /[\r]/
626
+ str_file_path[letter] = "/r"
627
+ when /[\s]/
628
+ str_file_path[letter] = "/t" # it is taking "\t" as "\s"
629
+ when /[\t]/
630
+ str_file_path[letter] = "/t"
631
+ when "\\"
632
+ str_file_path[letter] = "/"
633
+ #when /[\v]/ # not required due to expression error
634
+ #str_file_path[letter] = "/v" # not required due to expression error
635
+ #when /[\x]/ # not required due to expression error
636
+ #str_file_path[letter] = "/x" # not required due to expression error
637
+ #when /[\xnn]/ # not required due to expression error
638
+ #str_file_path[letter] = "/xnn" # not required due to expression error
639
+ end
640
+ end
641
+ return str_file_path
642
+ rescue Exception => ex
643
+ puts("Error in formatting file path (#{str_file_path}) : #{ex}")
644
+ exit
645
+ end
646
+
647
+ end