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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +66 -0
- data/.codeclimate.yml +48 -0
- data/.dockerignore +11 -0
- data/.gitignore +40 -0
- data/.rspec +3 -0
- data/.rubocop.yml +76 -0
- data/.rubocop_todo.yml +51 -0
- data/Dockerfile +38 -0
- data/Dockerfile.system-test +44 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +115 -0
- data/LICENSE +201 -0
- data/README.md +246 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/bucky-core.gemspec +47 -0
- data/docker-compose.dev-with-bm.yml +28 -0
- data/docker-compose.dev.yml +18 -0
- data/docker-compose.system-test.yml +21 -0
- data/docker/nginx/Dockerfile +7 -0
- data/docker/nginx/nginx.conf +22 -0
- data/docker/nginx/public/index.html +19 -0
- data/docker/nginx/public/test_page.html +12 -0
- data/exe/bucky +214 -0
- data/lib/bucky.rb +3 -0
- data/lib/bucky/core/database/db_connector.rb +29 -0
- data/lib/bucky/core/database/test_data_operator.rb +195 -0
- data/lib/bucky/core/exception/bucky_exception.rb +39 -0
- data/lib/bucky/core/report/screen_shot_generator.rb +24 -0
- data/lib/bucky/core/test_core/test_case_loader.rb +162 -0
- data/lib/bucky/core/test_core/test_class_generator.rb +129 -0
- data/lib/bucky/core/test_core/test_manager.rb +70 -0
- data/lib/bucky/core/test_core/test_result.rb +92 -0
- data/lib/bucky/test_equipment/evidence/evidence_generator.rb +36 -0
- data/lib/bucky/test_equipment/pageobject/base_pageobject.rb +55 -0
- data/lib/bucky/test_equipment/pageobject/pages.rb +61 -0
- data/lib/bucky/test_equipment/selenium_handler/webdriver_handler.rb +66 -0
- data/lib/bucky/test_equipment/test_case/abst_test_case.rb +49 -0
- data/lib/bucky/test_equipment/test_case/e2e_test_case.rb +70 -0
- data/lib/bucky/test_equipment/test_case/linkstatus_test_case.rb +28 -0
- data/lib/bucky/test_equipment/user_operation/user_operation_helper.rb +97 -0
- data/lib/bucky/test_equipment/user_operation/user_operation_logger.rb +15 -0
- data/lib/bucky/test_equipment/user_operation/user_operator.rb +61 -0
- data/lib/bucky/test_equipment/verifications/abst_verification.rb +13 -0
- data/lib/bucky/test_equipment/verifications/e2e_verification.rb +106 -0
- data/lib/bucky/test_equipment/verifications/js_error_checker.rb +23 -0
- data/lib/bucky/test_equipment/verifications/service_verifications.rb +62 -0
- data/lib/bucky/test_equipment/verifications/status_checker.rb +180 -0
- data/lib/bucky/tools/lint.rb +69 -0
- data/lib/bucky/utils/bucky_logger.rb +25 -0
- data/lib/bucky/utils/bucky_output.rb +23 -0
- data/lib/bucky/utils/config.rb +55 -0
- data/lib/bucky/utils/requests.rb +33 -0
- data/lib/bucky/utils/yaml_load.rb +24 -0
- data/lib/bucky/version.rb +7 -0
- data/system_testing/test_bucky_project/.bucky_home +2 -0
- data/system_testing/test_bucky_project/config/bucky_config.yml +6 -0
- data/system_testing/test_bucky_project/config/e2e_config.yml +15 -0
- data/system_testing/test_bucky_project/config/linkstatus_config.yml +3 -0
- data/system_testing/test_bucky_project/config/test_db_config.yml +8 -0
- data/system_testing/test_bucky_project/services/README.md +1 -0
- data/system_testing/test_bucky_project/services/service_a/pc/pageobject/index.rb +13 -0
- data/system_testing/test_bucky_project/services/service_a/pc/parts/index.yml +6 -0
- data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/pc_e2e.yml +68 -0
- data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/setup_each_pc_e2e.yml +20 -0
- data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/setup_teardown_each_pc_e2e.yml +35 -0
- data/system_testing/test_bucky_project/services/service_a/pc/scenarios/e2e/teardown_each_pc_e2e.yml +20 -0
- data/system_testing/test_bucky_project/services/service_a/pc/scenarios/linkstatus/pc_link.yml +10 -0
- data/system_testing/test_bucky_project/services/service_a/sp/pageobject/index.rb +14 -0
- data/system_testing/test_bucky_project/services/service_a/sp/parts/index.yml +6 -0
- data/system_testing/test_bucky_project/services/service_a/sp/scenarios/e2e/sp_e2e_test.yml +26 -0
- data/system_testing/test_bucky_project/services/service_a/sp/scenarios/linkstatus/sp_link.yml +10 -0
- data/system_testing/test_bucky_project/services/service_a/tablet/pageobject/index.rb +14 -0
- data/system_testing/test_bucky_project/services/service_a/tablet/parts/index.yml +6 -0
- data/system_testing/test_bucky_project/services/service_a/tablet/scenarios/e2e/tablet_e2e_test.yml +26 -0
- data/system_testing/test_bucky_project/system/evidences/README.md +1 -0
- data/system_testing/test_bucky_project/system/evidences/screen_shots/README.md +1 -0
- data/system_testing/test_bucky_project/system/logs/README.md +1 -0
- data/system_testing/test_specification.md +38 -0
- data/system_testing/testing_code/command.bats +42 -0
- data/system_testing/testing_code/e2e.bats +75 -0
- data/system_testing/testing_code/linkstatus.bats +24 -0
- data/template/make_page/pc/pageobject/sample_page.rb +23 -0
- data/template/make_page/pc/parts/sample_page.yml +9 -0
- data/template/make_page/sp/pageobject/sample_page.rb +24 -0
- data/template/make_page/sp/parts/sample_page.yml +9 -0
- data/template/make_page/tablet/pageobject/sample_page.rb +24 -0
- data/template/make_page/tablet/parts/sample_page.yml +9 -0
- data/template/new/.bucky_home +2 -0
- data/template/new/config/bucky_config.yml +6 -0
- data/template/new/config/e2e_config.yml +15 -0
- data/template/new/config/linkstatus_config.yml +3 -0
- data/template/new/config/test_db_config.yml +8 -0
- data/template/new/services/README.md +1 -0
- data/template/new/system/evidences/README.md +1 -0
- data/template/new/system/evidences/screen_shots/README.md +1 -0
- data/template/new/system/logs/README.md +1 -0
- 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
|