SurfCustomCalabash 0.2.0 → 1.0.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +68 -4
- data/SurfCustomCalabash.gemspec +3 -3
- data/bin/SurfCustomCalabash +54 -0
- data/bin/surf-calabash-console.rb +62 -0
- data/bin/surf-calabash-gen.rb +17 -0
- data/bin/surf-calabash-helpers.rb +34 -0
- data/lib/SurfCustomCalabash/CommonMethods.rb +3 -3
- data/lib/SurfCustomCalabash/DroidMethods.rb +2 -1
- data/lib/SurfCustomCalabash/IosMethods.rb +2 -2
- data/lib/SurfCustomCalabash/version.rb +1 -1
- data/sources/Backdoors list b/data/sources/Backdoors → list +0 -0
- data/sources/Gemfile +27 -0
- data/sources/Scripts/and.sh +5 -0
- data/sources/Scripts/ca.sh +5 -0
- data/sources/Scripts/ci.sh +5 -0
- data/sources/Scripts/data +7 -0
- data/sources/Scripts/fa.sh +6 -0
- data/sources/Scripts/fi.sh +5 -0
- data/sources/Scripts/get_apk.rb +68 -0
- data/sources/Scripts/get_scenarios.rb +193 -0
- data/sources/Scripts/import_scenarios.rb +172 -0
- data/sources/Scripts/ios.sh +5 -0
- data/sources/Scripts/parallel_android_smoke.sh +4 -0
- data/sources/Scripts/parallel_android_test.sh +4 -0
- data/sources/Scripts/ra.sh +12 -0
- data/sources/Scripts/ri.sh +9 -0
- data/sources/Scripts/smoke_and.sh +5 -0
- data/sources/Scripts/smoke_ios.sh +5 -0
- data/sources/Scripts/ta.sh +5 -0
- data/sources/Scripts/ti.sh +5 -0
- data/sources/Scripts/to_exec.sh +19 -0
- data/sources/Scripts/update.sh +24 -0
- data/sources/Scripts/update_exec.rb +96 -0
- data/sources/TestFolder/small.gif +0 -0
- data/sources/ci/JenkinsfileUiTestAndroid.groovy +22 -0
- data/sources/ci/JenkinsfileUiTestIos.groovy +23 -0
- data/sources/config/cucumber.yml +24 -0
- data/sources/features/android/pages/standard/DroidCommon.rb +33 -0
- data/sources/features/android/pages/standard/Init_android.rb +8 -0
- data/sources/features/android/pages/test.rb +43 -0
- data/sources/features/android/support/app_life_cycle_hooks.rb +147 -0
- data/sources/features/android/support/log_hooks_and.rb +40 -0
- data/sources/features/android/support/video_hooks_and.rb +110 -0
- data/sources/features/ios/pages/standard/Init_ios.rb +5 -0
- data/sources/features/ios/pages/standard/IosCommon.rb +30 -0
- data/sources/features/ios/pages/test.rb +37 -0
- data/sources/features/ios/support/01_launch.rb +194 -0
- data/sources/features/ios/support/log_hooks_ios.rb +40 -0
- data/sources/features/ios/support/video_hooks_ios.rb +58 -0
- data/sources/features/net/net.rb +28 -0
- data/sources/features/net/screentest_api.rb +186 -0
- data/sources/features/scenarios/eng.feature +8 -0
- data/sources/features/scenarios/rus.feature +8 -0
- data/sources/features/step_definitions/test.rb +43 -0
- data/sources/features/support/credentials.rb +11 -0
- data/sources/features/support/env.rb +8 -0
- data/sources/features/support/hooks.rb +21 -0
- data/sources/features/support/localization.rb +8 -0
- data/sources/find_id.rb +95 -0
- data/sources/group_steps.rb +39 -0
- data/sources/irbrcs/android/irbrc +105 -0
- data/sources/irbrcs/ios/irbrc +132 -0
- data/sources/start.sh +134 -0
- metadata +63 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
@@ -0,0 +1,193 @@
|
|
1
|
+
require_relative 'import_scenarios'
|
2
|
+
|
3
|
+
class GetScenarios
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@user_data = Scenarios.new("..")
|
7
|
+
end
|
8
|
+
|
9
|
+
# получить название всех сценариев из папки scenarios
|
10
|
+
def get_all_scenarios_name
|
11
|
+
@lines = Array.new
|
12
|
+
all_scenarios = Array.new
|
13
|
+
|
14
|
+
# путь до папки с фича файлами
|
15
|
+
file_names = Dir["./**/*.feature"]
|
16
|
+
|
17
|
+
# проходимся по всем файлам
|
18
|
+
file_names.each do |name|
|
19
|
+
|
20
|
+
# записываем все строки файла в массив
|
21
|
+
text=File.open(name).read
|
22
|
+
text.gsub!(/\r\n?/, "\n")
|
23
|
+
text.each_line do |line|
|
24
|
+
@lines.push(line)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# получаем все названия сценариев
|
29
|
+
@lines.each do |x|
|
30
|
+
if x.match(/Сценарий:/)
|
31
|
+
x.sub!(/Сценарий:/,'')
|
32
|
+
all_scenarios.push(x.strip)
|
33
|
+
elsif x.match(/Структура сценария:/)
|
34
|
+
x.sub!(/Структура сценария:/,'')
|
35
|
+
all_scenarios.push(x.strip)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
# Kernel.puts all_scenarios.count
|
39
|
+
return all_scenarios
|
40
|
+
end
|
41
|
+
|
42
|
+
# получить все не закомментрованные сценарии
|
43
|
+
def get_all_work_scenarios
|
44
|
+
all_work_scenarios = Array.new
|
45
|
+
get_all_scenarios_name.each do |x|
|
46
|
+
all_work_scenarios.push(x) unless x.match(/#/)
|
47
|
+
end
|
48
|
+
# Kernel.puts all_work_scenarios
|
49
|
+
# p all_work_scenarios.count
|
50
|
+
return all_work_scenarios
|
51
|
+
end
|
52
|
+
|
53
|
+
# получить все закомментированные сценарии
|
54
|
+
def get_all_comment_scenarios
|
55
|
+
all_comment_scenarios = Array.new
|
56
|
+
scenarios_name = Array.new
|
57
|
+
get_all_scenarios_name.each do |x|
|
58
|
+
all_comment_scenarios.push(x) if x.match(/#/)
|
59
|
+
end
|
60
|
+
|
61
|
+
all_comment_scenarios.each do |x|
|
62
|
+
x.sub!(/#/,'')
|
63
|
+
scenarios_name.push(x.strip)
|
64
|
+
end
|
65
|
+
|
66
|
+
Kernel.puts scenarios_name
|
67
|
+
p scenarios_name.count
|
68
|
+
return scenarios_name
|
69
|
+
end
|
70
|
+
|
71
|
+
# получить все сценарии с одинаковым именем
|
72
|
+
def show_all_duplicate_scenarios
|
73
|
+
if get_all_scenarios_name.duplicate.reject { |c| c.empty? }.any?
|
74
|
+
Kernel.puts "В репозитории найдены сценарии с одинаковыми названиями:"
|
75
|
+
Kernel.puts get_all_scenarios_name.duplicate
|
76
|
+
else
|
77
|
+
Kernel.puts "В репозитории нет сценариев с одинаковыми названиями"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# получаем все названия и ключи сценариев автотестов из джиры
|
82
|
+
def get_scenarios_name_from_jira
|
83
|
+
# @user_data = Scenarios.new("..")
|
84
|
+
jql = "project%20=%20#{@user_data.key}%20AND%20issuetype%20=%20Test%20AND%20\"Test%20Type\"%20=%20Cucumber"
|
85
|
+
fields = "summary"
|
86
|
+
max_results = "500"
|
87
|
+
url = "https://jira.surfstudio.ru/rest/api/2/search?jql=#{jql}&fields=#{fields}&maxResults=#{max_results}"
|
88
|
+
|
89
|
+
response = RestClient.get url, {:Authorization => @user_data.auth}
|
90
|
+
|
91
|
+
parse_response = JSON.parse(response.body)
|
92
|
+
|
93
|
+
summary = {}
|
94
|
+
|
95
|
+
parse_response['issues'].each {|x| summary[x['key']] = x['fields'].values[0]}
|
96
|
+
# Kernel.puts summary
|
97
|
+
# Kernel.puts summary.count
|
98
|
+
return summary
|
99
|
+
end
|
100
|
+
|
101
|
+
# получаем все сценарии которых нет в джире
|
102
|
+
def get_all_scenarios_not_exists_in_jira
|
103
|
+
get_all_work_scenarios.sort - get_scenarios_name_from_jira.values.sort
|
104
|
+
end
|
105
|
+
|
106
|
+
# получаем все названия сценариев и их ключи которые есть в джире, но нет в репозитории
|
107
|
+
def get_all_scenarios_not_exists_in_repo
|
108
|
+
Hash[get_scenarios_name_from_jira.to_a - get_scenarios_name_from_jira.extract_subhash(get_all_work_scenarios).to_a]
|
109
|
+
end
|
110
|
+
|
111
|
+
def show_all_scenarios_not_exists_in_repo
|
112
|
+
Kernel.puts get_all_scenarios_not_exists_in_repo.values
|
113
|
+
end
|
114
|
+
|
115
|
+
# выводит в консоль информацию о недостающих или лишних тестах в джире
|
116
|
+
def show_difference_tests
|
117
|
+
if get_all_scenarios_not_exists_in_jira.any?
|
118
|
+
Kernel.puts "В jira не хватает #{get_all_scenarios_not_exists_in_jira.count} сценариев, которые есть в репозитории:"
|
119
|
+
Kernel.puts get_all_scenarios_not_exists_in_jira
|
120
|
+
Kernel.puts "\n"
|
121
|
+
end
|
122
|
+
if get_all_scenarios_not_exists_in_repo.any?
|
123
|
+
Kernel.puts "В jira найдены #{get_all_scenarios_not_exists_in_repo.count} сценариев, которых нет в репозитории:"
|
124
|
+
Kernel.puts get_all_scenarios_not_exists_in_repo.values
|
125
|
+
Kernel.puts "\n"
|
126
|
+
end
|
127
|
+
unless get_all_scenarios_not_exists_in_repo.any? || get_all_scenarios_not_exists_in_jira.any?
|
128
|
+
Kernel.puts "В jira есть все сценарии из репозитория и нет лишних"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# создаем тест в репозитории в джире
|
133
|
+
def create_cucumber_test(test_name)
|
134
|
+
# user_data = Scenarios.new("..")
|
135
|
+
url = "https://jira.surfstudio.ru/rest/api/2/issue/"
|
136
|
+
body = {"fields"=>{"project"=>{"key"=>@user_data.key},
|
137
|
+
"summary"=>test_name,
|
138
|
+
"issuetype"=>{"name"=>"Test"},
|
139
|
+
"assignee"=>{"name"=>@user_data.login},
|
140
|
+
"customfield_10200"=>{"value"=>"Cucumber"}}}
|
141
|
+
|
142
|
+
response = RestClient.post url, body.to_json,
|
143
|
+
{:Authorization => @user_data.auth,
|
144
|
+
content_type: :json,
|
145
|
+
accept: :json}
|
146
|
+
return JSON.parse(response.body)['key']
|
147
|
+
end
|
148
|
+
|
149
|
+
# создаем все недостающие тесты в джире
|
150
|
+
def create_all_missing_test
|
151
|
+
Kernel.puts "Созданы сценарии:" if get_all_scenarios_not_exists_in_jira.any?
|
152
|
+
get_all_scenarios_not_exists_in_jira.each do |name|
|
153
|
+
Kernel.puts "#{create_cucumber_test(name)} #{name}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# удаляем тест из jira
|
158
|
+
def delete_issues_by_key(key)
|
159
|
+
# user_data = Scenarios.new("..")
|
160
|
+
url = "https://jira.surfstudio.ru/rest/api/2/issue/#{key}"
|
161
|
+
response = RestClient.delete url,{:Authorization => @user_data.auth}
|
162
|
+
response.code
|
163
|
+
end
|
164
|
+
|
165
|
+
# удаляем тесты, которые есть в джира, но нет в репо
|
166
|
+
def delete_all_waste_tests
|
167
|
+
get_all_scenarios_not_exists_in_repo.each do |k, v|
|
168
|
+
Kernel.puts "Сценарий: #{v} успешно удален" if delete_issues_by_key(k) == 204
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# find duplicate in array
|
174
|
+
class Array
|
175
|
+
def duplicate
|
176
|
+
duplicate = Array.new
|
177
|
+
duplicate.push(self.uniq.
|
178
|
+
map { | e | [self.count(e), e] }.
|
179
|
+
select { | c, _ | c > 1 }.
|
180
|
+
sort.reverse.
|
181
|
+
map { | _, e | "#{e}" })
|
182
|
+
|
183
|
+
return duplicate
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# extract subhash from hash
|
188
|
+
class Hash
|
189
|
+
def extract_subhash(extract)
|
190
|
+
self.select{|k, v| extract.include?(v)}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'json'
|
3
|
+
require 'base64'
|
4
|
+
require_relative 'get_scenarios'
|
5
|
+
|
6
|
+
class Scenarios
|
7
|
+
|
8
|
+
# path - путь до папки с автотестами, пример - /Users/hripunov/autotests/labirint-test/
|
9
|
+
def initialize(path)
|
10
|
+
# хэш со всеми данными из файла scripts/data
|
11
|
+
@all_data = get_all_data
|
12
|
+
|
13
|
+
# логин в джире
|
14
|
+
@login = @all_data['login']
|
15
|
+
|
16
|
+
# пароль в джире
|
17
|
+
@password = @all_data['jira_pass']
|
18
|
+
|
19
|
+
# ключ проекта в формате LABIOS
|
20
|
+
@key = @all_data['project_key']
|
21
|
+
|
22
|
+
# путь до папки с автотестами
|
23
|
+
@path = path
|
24
|
+
|
25
|
+
# токен в джире
|
26
|
+
@auth = 'Basic ' + Base64.encode64( "#{@login}:#{@password}" ).chomp
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :path, :auth, :key, :login
|
30
|
+
|
31
|
+
# для импорта необходимо запустить метод import_scenarios
|
32
|
+
# импортирует все сценарии из проекта в репозиторий тестов, перемещая тесты в соответствующие папки
|
33
|
+
def import_scenarios
|
34
|
+
# через api xray больше нельзя создавать новые сценрарии, только обновлять существующие
|
35
|
+
# поэтому сначала создаем недостающие сценарии в джира через ее api
|
36
|
+
new_scenarios = GetScenarios.new
|
37
|
+
if new_scenarios.get_all_scenarios_not_exists_in_jira.any?
|
38
|
+
Kernel.puts "Будут созданы #{new_scenarios.get_all_scenarios_not_exists_in_jira.count} новых сценариев:"
|
39
|
+
Kernel.puts new_scenarios.get_all_scenarios_not_exists_in_jira
|
40
|
+
new_scenarios.create_all_missing_test
|
41
|
+
end
|
42
|
+
|
43
|
+
file_names = Dir["#{@path}features/scenarios/**/*.feature"]
|
44
|
+
file_names.each do |file_name|
|
45
|
+
p file_name
|
46
|
+
|
47
|
+
response = import_feature_files(file_name)
|
48
|
+
parse_response = JSON.parse(response.body)
|
49
|
+
Kernel.puts(parse_response)
|
50
|
+
test_key = []
|
51
|
+
parse_response.each{|x| test_key << x['key']}
|
52
|
+
|
53
|
+
p test_key
|
54
|
+
|
55
|
+
folder_name = File.basename(file_name, ".feature")
|
56
|
+
|
57
|
+
p folder_name
|
58
|
+
|
59
|
+
folderid = get_folderid_by_name(folder_name)
|
60
|
+
|
61
|
+
# если папки в репозитории нет - создаем ее
|
62
|
+
if folderid.to_s.empty?
|
63
|
+
cur_folder = File.basename(File.dirname(file_name))
|
64
|
+
if cur_folder == 'scenarios'
|
65
|
+
cur_id = get_id_auto_folders
|
66
|
+
else
|
67
|
+
cur_id = get_folderid_by_name(cur_folder)
|
68
|
+
if cur_id.nil?
|
69
|
+
create_folder(cur_folder, get_id_auto_folders)
|
70
|
+
cur_id = get_folderid_by_name(cur_folder)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
p cur_folder
|
74
|
+
create_folder(folder_name, cur_id)
|
75
|
+
end
|
76
|
+
|
77
|
+
folderid = get_folderid_by_name(folder_name)
|
78
|
+
|
79
|
+
if !test_key.empty?
|
80
|
+
move_tests(folderid, test_key)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# считываем данные пользователя из файла
|
86
|
+
def get_all_data
|
87
|
+
Hash[*File.read("#{@path}scripts/data").split(/[, \n]+/)]
|
88
|
+
end
|
89
|
+
|
90
|
+
# получаем id папки с авотестами в репозитории
|
91
|
+
def get_id_auto_folders
|
92
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testrepository/#{@key}/folders"
|
93
|
+
|
94
|
+
response = RestClient.get url, {:Authorization => @auth}
|
95
|
+
# Kernel.puts(response)
|
96
|
+
|
97
|
+
parse_response = JSON.parse(response.body)
|
98
|
+
id_auto = parse_response['folders'].select {|x| x["name"] == "Auto"}[0]['id']
|
99
|
+
Kernel.puts(id_auto)
|
100
|
+
return id_auto
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_folder(name, root_id)
|
104
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testrepository/#{@key}/folders/#{root_id}"
|
105
|
+
response = RestClient.post url, {:name => name}.to_json,
|
106
|
+
{:Authorization => @auth,
|
107
|
+
content_type: :json,
|
108
|
+
accept: :json}
|
109
|
+
# Kernel.puts(response)
|
110
|
+
return response
|
111
|
+
end
|
112
|
+
|
113
|
+
# получаем список папок с фичами
|
114
|
+
def get_directories_name
|
115
|
+
dir_name = "#{@path}features/scenarios"
|
116
|
+
all_folders = Dir.entries(dir_name).select {|entry| File.directory? File.join(dir_name, entry) and !(entry =='.' || entry == '..') }
|
117
|
+
all_folders.sort
|
118
|
+
end
|
119
|
+
|
120
|
+
# ищем id папки в репозитории по ее имени
|
121
|
+
def get_folderid_by_name(name)
|
122
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testrepository/#{@key}/folders"
|
123
|
+
|
124
|
+
@folder_id = nil
|
125
|
+
|
126
|
+
response = RestClient.get url, {:Authorization => @auth}
|
127
|
+
# Kernel.puts(response)
|
128
|
+
parse_response = JSON.parse(response.body)
|
129
|
+
|
130
|
+
auto = {}
|
131
|
+
parse_response['folders'].each{|x| x["name"] == "Auto" ? auto.update(x) : false}
|
132
|
+
|
133
|
+
ind = auto['folders'].index{|x| x['name'] == name}
|
134
|
+
|
135
|
+
if !ind.nil?
|
136
|
+
@folder_id = auto['folders'][ind]['id']
|
137
|
+
end
|
138
|
+
|
139
|
+
if @folder_id.to_s.empty?
|
140
|
+
auto['folders'].each_with_index do |(x, y), ind|
|
141
|
+
x['folders'].index{|x| x["name"] == name}.nil? ? false : ind_sub = x["folders"].index{|x| x["name"] == name}
|
142
|
+
if !ind_sub.nil?
|
143
|
+
@folder_id = auto['folders'][ind]['folders'][ind_sub]['id']
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
p @folder_id
|
148
|
+
return @folder_id
|
149
|
+
end
|
150
|
+
|
151
|
+
# имортируем фича файл
|
152
|
+
def import_feature_files(file_name)
|
153
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/import/feature?projectKey=#{@key}"
|
154
|
+
|
155
|
+
RestClient.post url, { :multipart => true,
|
156
|
+
:file => File.new(file_name, 'rb')},
|
157
|
+
{ :Authorization => @auth}
|
158
|
+
end
|
159
|
+
|
160
|
+
# перемещаем выгруженные сценарии в нужную папку
|
161
|
+
def move_tests(folderid, tests)
|
162
|
+
# https://jira.surfstudio.ru/rest/raven/1.0/folderStructure/moveTests?destinationId=1757
|
163
|
+
url = "https://jira.surfstudio.ru/rest/raven/1.0/api/testrepository/#{@key}/folders/#{folderid}/tests"
|
164
|
+
p url
|
165
|
+
p tests
|
166
|
+
response = RestClient.put url, {:add => tests}.to_json,
|
167
|
+
{:Authorization => @auth,
|
168
|
+
content_type: :json,
|
169
|
+
accept: :json}
|
170
|
+
Kernel.puts(response)
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
password=12345678
|
4
|
+
alias=my
|
5
|
+
|
6
|
+
echo "===== RUNNING SIGNING ====================="
|
7
|
+
|
8
|
+
static_param="{\"keystore_location\":\"my.keystore\",\"keystore_password\":\"12345678\",\"keystore_alias\":\"my\"}"
|
9
|
+
echo $static_param > /.calabash_settings
|
10
|
+
calabash-android resign L.apk
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
echo "enter json name with tests form file name.json in root dir in format <name>"
|
3
|
+
|
4
|
+
read json
|
5
|
+
|
6
|
+
echo "\nвведите код прогона TEST-EXECUTION в формате <BZN-344>"
|
7
|
+
echo "\nenter exec key TEST-EXECUTION in format <KEYPROJ-344>"
|
8
|
+
|
9
|
+
read code
|
10
|
+
|
11
|
+
|
12
|
+
username=$(head -n 2 ./Scripts/user | tail -n 1)
|
13
|
+
password=$(head -n 3 ./Scripts/user | tail -n 1)
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
curl -H "Content-Type: application/json" -X POST -u $username:$password --data @$json.json https://jira.surfstudio.ru/rest/raven/1.0/api/testexec/$code/test
|