friendly-cukes 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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