bucky-core 0.9.0

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 (100) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +66 -0
  3. data/.codeclimate.yml +48 -0
  4. data/.dockerignore +11 -0
  5. data/.gitignore +40 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +76 -0
  8. data/.rubocop_todo.yml +51 -0
  9. data/Dockerfile +38 -0
  10. data/Dockerfile.system-test +44 -0
  11. data/Gemfile +4 -0
  12. data/Gemfile.lock +115 -0
  13. data/LICENSE +201 -0
  14. data/README.md +246 -0
  15. data/Rakefile +8 -0
  16. data/bin/console +15 -0
  17. data/bin/setup +8 -0
  18. data/bucky-core.gemspec +47 -0
  19. data/docker-compose.dev-with-bm.yml +28 -0
  20. data/docker-compose.dev.yml +18 -0
  21. data/docker-compose.system-test.yml +21 -0
  22. data/docker/nginx/Dockerfile +7 -0
  23. data/docker/nginx/nginx.conf +22 -0
  24. data/docker/nginx/public/index.html +19 -0
  25. data/docker/nginx/public/test_page.html +12 -0
  26. data/exe/bucky +214 -0
  27. data/lib/bucky.rb +3 -0
  28. data/lib/bucky/core/database/db_connector.rb +29 -0
  29. data/lib/bucky/core/database/test_data_operator.rb +195 -0
  30. data/lib/bucky/core/exception/bucky_exception.rb +39 -0
  31. data/lib/bucky/core/report/screen_shot_generator.rb +24 -0
  32. data/lib/bucky/core/test_core/test_case_loader.rb +162 -0
  33. data/lib/bucky/core/test_core/test_class_generator.rb +129 -0
  34. data/lib/bucky/core/test_core/test_manager.rb +70 -0
  35. data/lib/bucky/core/test_core/test_result.rb +92 -0
  36. data/lib/bucky/test_equipment/evidence/evidence_generator.rb +36 -0
  37. data/lib/bucky/test_equipment/pageobject/base_pageobject.rb +55 -0
  38. data/lib/bucky/test_equipment/pageobject/pages.rb +61 -0
  39. data/lib/bucky/test_equipment/selenium_handler/webdriver_handler.rb +66 -0
  40. data/lib/bucky/test_equipment/test_case/abst_test_case.rb +49 -0
  41. data/lib/bucky/test_equipment/test_case/e2e_test_case.rb +70 -0
  42. data/lib/bucky/test_equipment/test_case/linkstatus_test_case.rb +28 -0
  43. data/lib/bucky/test_equipment/user_operation/user_operation_helper.rb +97 -0
  44. data/lib/bucky/test_equipment/user_operation/user_operation_logger.rb +15 -0
  45. data/lib/bucky/test_equipment/user_operation/user_operator.rb +61 -0
  46. data/lib/bucky/test_equipment/verifications/abst_verification.rb +13 -0
  47. data/lib/bucky/test_equipment/verifications/e2e_verification.rb +106 -0
  48. data/lib/bucky/test_equipment/verifications/js_error_checker.rb +23 -0
  49. data/lib/bucky/test_equipment/verifications/service_verifications.rb +62 -0
  50. data/lib/bucky/test_equipment/verifications/status_checker.rb +180 -0
  51. data/lib/bucky/tools/lint.rb +69 -0
  52. data/lib/bucky/utils/bucky_logger.rb +25 -0
  53. data/lib/bucky/utils/bucky_output.rb +23 -0
  54. data/lib/bucky/utils/config.rb +55 -0
  55. data/lib/bucky/utils/requests.rb +33 -0
  56. data/lib/bucky/utils/yaml_load.rb +24 -0
  57. data/lib/bucky/version.rb +7 -0
  58. data/system_testing/test_bucky_project/.bucky_home +2 -0
  59. data/system_testing/test_bucky_project/config/bucky_config.yml +6 -0
  60. data/system_testing/test_bucky_project/config/e2e_config.yml +15 -0
  61. data/system_testing/test_bucky_project/config/linkstatus_config.yml +3 -0
  62. data/system_testing/test_bucky_project/config/test_db_config.yml +8 -0
  63. data/system_testing/test_bucky_project/services/README.md +1 -0
  64. data/system_testing/test_bucky_project/services/service_a/pc/pageobject/index.rb +13 -0
  65. data/system_testing/test_bucky_project/services/service_a/pc/parts/index.yml +6 -0
  66. data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/pc_e2e.yml +68 -0
  67. data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/setup_each_pc_e2e.yml +20 -0
  68. data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/setup_teardown_each_pc_e2e.yml +35 -0
  69. data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/teardown_each_pc_e2e.yml +20 -0
  70. data/system_testing/test_bucky_project/services/service_a/pc/scenarios/linkstatus/pc_link.yml +10 -0
  71. data/system_testing/test_bucky_project/services/service_a/sp/pageobject/index.rb +14 -0
  72. data/system_testing/test_bucky_project/services/service_a/sp/parts/index.yml +6 -0
  73. data/system_testing/test_bucky_project/services/service_a/sp/scenarios/e2e/sp_e2e_test.yml +26 -0
  74. data/system_testing/test_bucky_project/services/service_a/sp/scenarios/linkstatus/sp_link.yml +10 -0
  75. data/system_testing/test_bucky_project/services/service_a/tablet/pageobject/index.rb +14 -0
  76. data/system_testing/test_bucky_project/services/service_a/tablet/parts/index.yml +6 -0
  77. data/system_testing/test_bucky_project/services/service_a/tablet/scenarios/e2e/tablet_e2e_test.yml +26 -0
  78. data/system_testing/test_bucky_project/system/evidences/README.md +1 -0
  79. data/system_testing/test_bucky_project/system/evidences/screen_shots/README.md +1 -0
  80. data/system_testing/test_bucky_project/system/logs/README.md +1 -0
  81. data/system_testing/test_specification.md +38 -0
  82. data/system_testing/testing_code/command.bats +42 -0
  83. data/system_testing/testing_code/e2e.bats +75 -0
  84. data/system_testing/testing_code/linkstatus.bats +24 -0
  85. data/template/make_page/pc/pageobject/sample_page.rb +23 -0
  86. data/template/make_page/pc/parts/sample_page.yml +9 -0
  87. data/template/make_page/sp/pageobject/sample_page.rb +24 -0
  88. data/template/make_page/sp/parts/sample_page.yml +9 -0
  89. data/template/make_page/tablet/pageobject/sample_page.rb +24 -0
  90. data/template/make_page/tablet/parts/sample_page.yml +9 -0
  91. data/template/new/.bucky_home +2 -0
  92. data/template/new/config/bucky_config.yml +6 -0
  93. data/template/new/config/e2e_config.yml +15 -0
  94. data/template/new/config/linkstatus_config.yml +3 -0
  95. data/template/new/config/test_db_config.yml +8 -0
  96. data/template/new/services/README.md +1 -0
  97. data/template/new/system/evidences/README.md +1 -0
  98. data/template/new/system/evidences/screen_shots/README.md +1 -0
  99. data/template/new/system/logs/README.md +1 -0
  100. metadata +415 -0
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './db_connector'
4
+ require_relative '../../utils/config'
5
+
6
+ module Bucky
7
+ module Core
8
+ module Database
9
+ class TestDataOperator
10
+ def initialize
11
+ @connector = DbConnector.new
12
+ @connector.connect
13
+ @config = Bucky::Utils::Config.instance
14
+ end
15
+
16
+ # Save job data and return job id
17
+ # @param [Time] start_time
18
+ # @return [Fixnum] job_id
19
+ def save_job_record_and_get_job_id(start_time, command_and_option)
20
+ return 0 if $debug
21
+
22
+ job_id = @connector.con[:jobs].insert(start_time: start_time, command_and_option: command_and_option)
23
+ @connector.disconnect
24
+ job_id
25
+ end
26
+
27
+ # Save test result
28
+ # @param [Hash] test_suite_result test data for Sequel
29
+ def save_test_result(test_suite_result)
30
+ @connector.con[:test_case_results].import(test_suite_result[:column], test_suite_result[:data_set])
31
+ @connector.disconnect
32
+ end
33
+
34
+ # Add test_suites.id to loaded suite data
35
+ # @return [Array] test_suite_data
36
+ def add_suite_id_to_loaded_suite_data(test_suite_data)
37
+ return test_suite_data if $debug
38
+
39
+ test_suite_data.each_with_index do |test_data, i|
40
+ suite = get_test_suite_from_test_data(test_data)
41
+ test_suite_data[i][:test_suite_id] = suite[:id]
42
+ end
43
+ @connector.disconnect
44
+ test_suite_data
45
+ end
46
+
47
+ # Save test suite data
48
+ def update_test_suites_data(test_suite_data)
49
+ return if $debug
50
+
51
+ test_suite_data.each do |test_data|
52
+ saved_test_suite = get_test_suite_from_test_data(test_data)
53
+ suite_id = get_suite_id_from_saved_test_suite(saved_test_suite, test_data)
54
+ test_data[:suite][:cases].each do |test_case|
55
+ labels = get_labels_from_suite_and_case(test_data[:suite][:labels], test_case[:labels])
56
+ label_ids = insert_and_return_label_ids(labels)
57
+ update_test_case_and_test_case_label(suite_id, test_case, label_ids)
58
+ end
59
+ end
60
+ @connector.disconnect
61
+ end
62
+
63
+ # Return file path and CaseName that failed at last time.
64
+ # @return [Hash] re_test_cond
65
+ def get_ng_test_cases_at_last_execution(cond)
66
+ re_test_cond = {}
67
+ return {} if $debug
68
+
69
+ cases = @connector.con[:test_case_results].filter(cond).select(:test_case_id).all.map { |row| row[:test_case_id] }
70
+ Sequel.split_symbols = true # To use test_cases__id
71
+ suites_and_cases = @connector.con[:test_cases]
72
+ .left_join(:test_suites, id: Sequel.qualify('test_cases', 'test_suite_id'))
73
+ .where(test_cases__id: cases).all
74
+ # Created data
75
+ # {
76
+ # 1 => {file_path: "/hoge/fuga.yml", cases_names: ["hogehoge_hoge_1", "hogehoge_hoge_2"]},
77
+ # 2 => {file_path: "/gefu/hugo.yml", cases_names: ["hogehoge_hoge_1", "hogehoge_hoge_2"]},
78
+ # }
79
+ suites_and_cases.each do |suite_case|
80
+ suite_id = suite_case[:test_suite_id]
81
+ if re_test_cond.key? suite_id
82
+ re_test_cond[suite_id][:case_names].push suite_case[:case_name]
83
+ else
84
+ re_test_cond[suite_id] = {
85
+ file_path: suite_case[:file_path],
86
+ case_names: [suite_case[:case_name]]
87
+ }
88
+ end
89
+ end
90
+ re_test_cond
91
+ end
92
+
93
+ def get_test_case_id(test_suite_id, case_name)
94
+ return nil if $debug
95
+
96
+ test_case = @connector.con[:test_cases].filter(test_suite_id: test_suite_id, case_name: case_name).first
97
+ @connector.disconnect
98
+ raise "Cannot get test_case id. test_suite_id: #{test_suite_id}, case_name: #{case_name}" if test_case.nil?
99
+
100
+ test_case[:id]
101
+ end
102
+
103
+ # Return last round
104
+ # @param [Int] job_id
105
+ # @return [Int] round
106
+ def get_last_round_from_job_id(job_id)
107
+ round = @connector.con[:test_case_results].where(job_id: job_id).max(:round)
108
+ @connector.disconnect
109
+ round
110
+ end
111
+
112
+ private
113
+
114
+ # Common method for getting suite
115
+ def get_test_suite_from_test_data(test_data)
116
+ @connector.con[:test_suites].filter(
117
+ test_category: test_data[:test_category],
118
+ service: test_data[:suite][:service],
119
+ device: test_data[:suite][:device],
120
+ test_suite_name: test_data[:test_suite_name]
121
+ ).first
122
+ end
123
+
124
+ def get_suite_id_from_saved_test_suite(saved_test_suite, test_data)
125
+ file_path = "services/#{test_data[:suite][:service]}/#{test_data[:suite][:device]}/scenarios/#{test_data[:test_category]}/#{test_data[:test_suite_name]}.yml"
126
+ if saved_test_suite
127
+ @connector.con[:test_suites].where(id: saved_test_suite[:id]).update(
128
+ priority: test_data[:suite][:priority].to_s,
129
+ test_suite_name: test_data[:test_suite_name],
130
+ suite_description: test_data[:suite][:desc],
131
+ github_url: @config[:test_code_repo],
132
+ file_path: file_path
133
+ )
134
+ saved_test_suite[:id]
135
+ else # If there is no test_suite, save new record and return suite_id.
136
+ @connector.con[:test_suites].insert(
137
+ test_category: test_data[:test_category],
138
+ service: test_data[:suite][:service],
139
+ device: test_data[:suite][:device],
140
+ priority: test_data[:suite][:priority].to_s,
141
+ test_suite_name: test_data[:test_suite_name],
142
+ suite_description: test_data[:suite][:desc],
143
+ github_url: @config[:test_code_repo],
144
+ file_path: file_path
145
+ )
146
+ end
147
+ end
148
+
149
+ # Return array contains suite and case
150
+ def get_labels_from_suite_and_case(suite_labels, case_labels)
151
+ [suite_labels, case_labels].flatten.compact.uniq
152
+ end
153
+
154
+ # Return label ids if case has labels, else return nil
155
+ def insert_and_return_label_ids(labels)
156
+ label_ids = []
157
+ return nil if labels.empty?
158
+
159
+ labels.each do |label_name|
160
+ label = @connector.con[:labels].filter(label_name: label_name).first
161
+ label_ids << if label
162
+ label[:id]
163
+ else
164
+ @connector.con[:labels].insert(label_name: label_name)
165
+ end
166
+ end
167
+ label_ids
168
+ end
169
+
170
+ def update_test_case_and_test_case_label(suite_id, test_case, label_ids)
171
+ saved_test_case = @connector.con[:test_cases].filter(test_suite_id: suite_id, case_name: test_case[:case_name]).first
172
+ if saved_test_case
173
+ # Update case data
174
+ @connector.con[:test_cases].where(id: saved_test_case[:id]).update(case_name: test_case[:case_name], case_description: test_case[:desc])
175
+ # Update label of case
176
+ # At first, delete case connection
177
+ @connector.con[:test_case_labels].filter(test_case_id: saved_test_case[:id]).delete
178
+ # Create new connection
179
+ # If there is no labels, return nil
180
+ label_ids&.each do |label_id|
181
+ @connector.con[:test_case_labels].insert(test_case_id: saved_test_case[:id], label_id: label_id)
182
+ end
183
+ else
184
+ # Add case data
185
+ test_case_id = @connector.con[:test_cases].insert(test_suite_id: suite_id, case_name: test_case[:case_name], case_description: test_case[:desc])
186
+ # If there is no labels, return nil
187
+ label_ids&.each do |label_id|
188
+ @connector.con[:test_case_labels].insert(test_case_id: test_case_id, label_id: label_id)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../utils/bucky_logger'
4
+ require_relative '../../utils/config'
5
+
6
+ module Bucky
7
+ module Core
8
+ module Exception
9
+ class BuckyException
10
+ include Bucky::Utils::BuckyLogger
11
+ class << self
12
+ # Error handling on bucky framework
13
+ # @param [Object] err exception object
14
+ def handle(err)
15
+ Bucky::Utils::BuckyLogger.write(Bucky::Utils::Config.instance[:bucky_error], err)
16
+ end
17
+ end
18
+ end
19
+
20
+ class DbConnectorException < Bucky::Core::Exception::BuckyException
21
+ class << self
22
+ def handle(err)
23
+ super
24
+ raise err
25
+ end
26
+ end
27
+ end
28
+
29
+ class WebdriverException < Bucky::Core::Exception::BuckyException
30
+ class << self
31
+ def handle(err)
32
+ super
33
+ raise err
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../utils/config'
4
+ require_relative '../exception/bucky_exception'
5
+
6
+ module Bucky
7
+ module Core
8
+ module Report
9
+ module ScreenShotGenerator
10
+ # Save screen shot
11
+ # @param [Webdriver] driver
12
+ # @param [String] test_case e.g.) test_sample_app_pc_e2e_1_1
13
+ def generate_screen_shot(driver, test_case)
14
+ timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
15
+ driver.save_screenshot(
16
+ Bucky::Utils::Config.instance[:screen_shot_path] + test_case << "_#{timestamp}.png"
17
+ )
18
+ rescue StandardError => e
19
+ Bucky::Core::Exception::BuckyException.handle(e)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../database/test_data_operator'
4
+ require_relative '../../utils/yaml_load'
5
+
6
+ class Hash
7
+ def deep_symbolize_keys!
8
+ deep_transform_keys! do |key|
9
+ key unless key.respond_to? :to_sym
10
+ key.to_sym
11
+ end
12
+ end
13
+
14
+ def deep_transform_keys!(&block)
15
+ keys.each do |key|
16
+ value = delete(key)
17
+ self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
18
+ end
19
+ self
20
+ end
21
+ end
22
+
23
+ module Bucky
24
+ module Core
25
+ module TestCore
26
+ class TestCaseLoader
27
+ class << self
28
+ include Bucky::Utils::YamlLoad
29
+ # Load test code files and return test suite data.
30
+ # @return [Array] test suite
31
+ def load_testcode(test_cond)
32
+ return load_re_test_testcode(test_cond[:re_test_cond]) if test_cond.key? :re_test_cond
33
+
34
+ testcodes = []
35
+ service = (test_cond[:service] || ['*']).first
36
+ device = (test_cond[:device] || ['*']).first
37
+ category = (test_cond[:test_category] || ['*']).first
38
+
39
+ Dir.glob("#{$bucky_home_dir}/services/#{service}/#{device}/scenarios/#{category}/*.yml").each do |testcode_file|
40
+ testcodes << load_testcode_in_file(testcode_file, test_cond)
41
+ end
42
+ # Delete nil element
43
+ testcodes.compact
44
+ end
45
+
46
+ private
47
+
48
+ def load_testcode_in_file(testcode_file, test_cond)
49
+ testcode_info = testcode_file.split(%r{/|\.}).reverse
50
+ test_suite_name, test_category = testcode_info[1..3]
51
+ test_class_name = test_suite_name.split('_').map(&:capitalize).join
52
+ test_suite = load_suite_file(testcode_file)
53
+ return nil unless target_in_suite_options?(test_suite, test_cond, test_suite_name)
54
+
55
+ test_suite = set_suite_option_to_case(test_suite)
56
+ refined_suite = refine_case_with_option(test_cond, test_suite)
57
+ return nil if refined_suite[:cases].empty?
58
+
59
+ { test_class_name: test_class_name, test_suite_name: test_suite_name, test_category: test_category, suite: refined_suite }
60
+ end
61
+
62
+ def load_re_test_testcode(re_test_cond)
63
+ testcodes = []
64
+ re_test_cond.each_value do |cond|
65
+ testcode_info = cond[:file_path].split(%r{/|\.}).reverse
66
+ test_suite_name, test_category = testcode_info[1..3]
67
+ test_class_name = test_suite_name.split('_').map(&:capitalize).join
68
+ test_suite = load_suite_file(cond[:file_path])
69
+ test_suite[:cases].delete_if { |c| !cond[:case_names].include? c[:case_name] }
70
+ testcodes << { test_class_name: test_class_name, test_suite_name: test_suite_name, test_category: test_category, suite: test_suite }
71
+ end
72
+ testcodes
73
+ end
74
+
75
+ def load_suite_file(file)
76
+ test_suite = load_yaml(file)
77
+ test_suite.deep_symbolize_keys!
78
+ test_suite[:setup_each][:procs].each(&:deep_symbolize_keys!) if test_suite[:setup_each]
79
+ test_suite[:teardown_each][:procs].each(&:deep_symbolize_keys!) if test_suite[:teardown_each]
80
+ test_suite[:cases].each do |c|
81
+ c.deep_symbolize_keys!
82
+ next unless c.key? :procs
83
+
84
+ c[:procs].each do |p|
85
+ c[:procs].delete(p) unless when_match?(p)
86
+ p.deep_symbolize_keys!
87
+ end
88
+ end
89
+ test_suite
90
+ rescue StandardError => ex
91
+ raise ex, "loading #{file}, #{ex.message}"
92
+ end
93
+
94
+ def when_match?(proc)
95
+ return true unless proc.key?('when')
96
+ raise StandardError, 'Please input correct condition' unless [true, false].include?(proc['when'])
97
+
98
+ proc['when']
99
+ end
100
+
101
+ # Return true if match suite condition
102
+ # Only priority and suite name
103
+ def target_in_suite_options?(test_suite, test_cond, test_suite_name)
104
+ # priority
105
+ return false unless check_option_include_target?(test_cond[:priority], test_suite[:priority])
106
+ # suite_name
107
+ return false unless check_option_include_target?(test_cond[:suite_name], test_suite_name)
108
+
109
+ true
110
+ end
111
+
112
+ # Return true, if target includes specified option
113
+ def check_option_include_target?(option, target)
114
+ # If there is no option, return nil.
115
+ if option.nil?
116
+ nil
117
+ else
118
+ return false unless option.include?(target)
119
+ end
120
+ true
121
+ end
122
+
123
+ # set suite option to case e.g.) suite's labels are inherited by test cases
124
+ # only label
125
+ def set_suite_option_to_case(test_suite)
126
+ return test_suite unless test_suite.key?(:labels)
127
+
128
+ # Pattern of value is different depending on how to write (string/array)
129
+ # change to array on all pattern
130
+ test_suite[:labels] = [test_suite[:labels]].flatten
131
+ test_suite[:cases].each do |c|
132
+ c[:labels] = if c.key?(:labels)
133
+ [c[:labels]].flatten | test_suite[:labels]
134
+ else
135
+ test_suite[:labels]
136
+ end
137
+ end
138
+ test_suite
139
+ end
140
+
141
+ # Filter with option
142
+ def refine_case_with_option(test_cond, suite)
143
+ # Filtering by label
144
+ if test_cond.key? :label
145
+ # Delete test case that have no label
146
+ # Pattern of value is different depending on how to write (string/array)
147
+ # Change to array on all pattern
148
+ suite[:cases].delete_if { |c| c[:labels].nil? }
149
+ suite[:cases].delete_if { |c| !(test_cond[:label].sort - [c[:labels]].flatten.sort).empty? }
150
+ end
151
+ # If there is no option, do nothing.
152
+ return suite unless test_cond.key? :case
153
+
154
+ # Delete test case doesn't match
155
+ suite[:cases].delete_if { |c| !test_cond[:case].include? c[:case_name] }
156
+ suite
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../test_equipment/test_case/e2e_test_case'
4
+ require_relative '../../test_equipment/test_case/linkstatus_test_case'
5
+
6
+ module Bucky
7
+ module Core
8
+ module TestCore
9
+ # For creating class dynamically.
10
+ class TestClasses
11
+ end
12
+
13
+ module TestClassGeneratorHelper
14
+ private
15
+
16
+ def add_test_procedure(procedures)
17
+ procedures.each.with_index(1) do |procedure, index|
18
+ puts " #{index}:#{procedure[:proc]}" if procedure.key?(:proc)
19
+ method = procedure[:exec].key?(:operate) ? :operate : :verify
20
+ send(method, procedure[:exec])
21
+ check_js_error
22
+ end
23
+ end
24
+
25
+ def make_test_method_name(data, test_case, index)
26
+ if test_case[:case_name].nil?
27
+ return [
28
+ 'test',
29
+ data[:suite][:service],
30
+ data[:suite][:device],
31
+ data[:test_category],
32
+ data[:test_suite_name],
33
+ index.to_s
34
+ ].join('_')
35
+ end
36
+ "test_#{test_case[:case_name]}"
37
+ end
38
+ end
39
+
40
+ class TestClassGenerator
41
+ attr_accessor :test_classes
42
+
43
+ def initialize(test_cond)
44
+ @test_classes = TestClasses
45
+ @test_cond = test_cond
46
+ end
47
+
48
+ # Genrate test class by test suite and test case data
49
+ def generate_test_class(data, link_status_url_log)
50
+ test_cond = @test_cond
51
+ # Common proccessing
52
+ # e.g.) TestSampleAppPcE2e1, TestSampleAppPcHttpstatus1
53
+ test_class_name = make_test_class_name(data)
54
+ # Select super class by test category
55
+ super_suite_class = eval format('Bucky::TestEquipment::TestCase::%<test_category>sTestCase', test_category: data[:test_category].capitalize)
56
+ # Define test suite class
57
+ test_classes.const_set(test_class_name.to_sym, Class.new(super_suite_class) do |_klass|
58
+ extend TestClassGeneratorHelper
59
+ include TestClassGeneratorHelper
60
+ define_method(:suite_data, proc { data[:suite] })
61
+ define_method(:suite_id, proc { data[:test_suite_id] })
62
+ define_method(:simple_test_class_name) do |original_name|
63
+ match_obj = /\Atest_(.+)\(.+::(Test.+)\)\z/.match(original_name)
64
+ "#{match_obj[1]}(#{match_obj[2]})"
65
+ end
66
+
67
+ # Class structure is different for each test category
68
+ case data[:test_category]
69
+ when 'linkstatus' then
70
+ data[:suite][:cases].each_with_index do |t_case, i|
71
+ method_name = make_test_method_name(data, t_case, i)
72
+ description(
73
+ t_case[:case_name],
74
+ define_method(method_name) do
75
+ puts "\n#{simple_test_class_name(name)}"
76
+ t_case[:urls].each do |url|
77
+ link_status_check_args = { url: url, device: data[:suite][:device], exclude_urls: data[:suite][:exclude_urls], link_check_max_times: test_cond[:link_check_max_times], url_log: link_status_url_log }
78
+ link_status_check(link_status_check_args)
79
+ end
80
+ end
81
+ )
82
+ end
83
+
84
+ when 'e2e' then
85
+ if data[:suite][:setup_each]
86
+ def setup
87
+ super
88
+ puts "[setup]#{simple_test_class_name(name)}"
89
+ add_test_procedure(suite_data[:setup_each][:procs])
90
+ end
91
+ end
92
+
93
+ if data[:suite][:teardown_each]
94
+ def teardown
95
+ puts "[teardown]#{simple_test_class_name(name)}"
96
+ add_test_procedure(suite_data[:teardown_each][:procs])
97
+ super
98
+ end
99
+ end
100
+
101
+ # Generate test case method
102
+ data[:suite][:cases].each_with_index do |t_case, i|
103
+ # e.g.) test_sample_app_pc_e2e_1_2
104
+ method_name = make_test_method_name(data, t_case, i)
105
+ method_obj = proc do
106
+ puts "\n#{simple_test_class_name(name)}\n #{t_case[:desc]} ...."
107
+ add_test_procedure(t_case[:procs])
108
+ end
109
+ description(t_case[:case_name], define_method(method_name, method_obj))
110
+ end
111
+ end
112
+ end)
113
+ end
114
+
115
+ private
116
+
117
+ def make_test_class_name(data)
118
+ [
119
+ 'Test',
120
+ data[:suite][:service].split(/_|-/).map(&:capitalize).join.to_s,
121
+ data[:suite][:device].capitalize.to_s,
122
+ data[:test_category].to_s.capitalize.to_s,
123
+ (data[:test_class_name]).to_s
124
+ ].join
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end