onlyoffice_testrail_wrapper 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/onlyoffice_testrail_wrapper.rb +10 -0
- data/lib/onlyoffice_testrail_wrapper/helpers/hash_helper.rb +21 -0
- data/lib/onlyoffice_testrail_wrapper/helpers/rspec_helper.rb +24 -0
- data/lib/onlyoffice_testrail_wrapper/helpers/ruby_helper.rb +10 -0
- data/lib/onlyoffice_testrail_wrapper/helpers/string_helper.rb +12 -0
- data/lib/onlyoffice_testrail_wrapper/helpers/system_helper.rb +17 -0
- data/lib/onlyoffice_testrail_wrapper/mock/rspec_example_mock.rb +40 -0
- data/lib/onlyoffice_testrail_wrapper/name.rb +9 -0
- data/lib/onlyoffice_testrail_wrapper/rspec_extension.rb +14 -0
- data/lib/onlyoffice_testrail_wrapper/testrail.rb +187 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_case.rb +67 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_helper.rb +173 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_helper/testrail_helper_rspec_metadata.rb +55 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_helper/testrail_status_helper.rb +18 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_milestone.rb +23 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_plan.rb +92 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_plan_entry.rb +16 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_project.rb +227 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_project/testrail_project_plan_helper.rb +65 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_result.rb +47 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_run.rb +147 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_section.rb +109 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_suite.rb +113 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_test.rb +40 -0
- data/lib/onlyoffice_testrail_wrapper/testrail_tools/testrail_tools.rb +119 -0
- data/lib/onlyoffice_testrail_wrapper/version.rb +7 -0
- metadata +237 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c7cdb9209303106828ac8d2628bdfbd6243b0b66cbf9e57f8d1c3d506a29d0af
|
4
|
+
data.tar.gz: 54ad089da3f905190dc4b33784fbfc665faa725d865f0b28d77f034e4766b08e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 86813255438a058617f52e431bd1465fe1a2aba8397dc62cd41efc51fc270c22c271a3c0e6a8c59645540896b8842eab77ce53a3614048f7d7f4da9016615ce1
|
7
|
+
data.tar.gz: e198cc8aa5f2b5c537ee36ff4e30c03ebb262a0485f7852d12f4ef333ce3f751e9046df74a1a842221f9e5b17358afc55ef2ea73f92d64099dbdf368e8655072
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'onlyoffice_logger_helper'
|
4
|
+
require_relative 'onlyoffice_testrail_wrapper/rspec_extension'
|
5
|
+
require_relative 'onlyoffice_testrail_wrapper/testrail_helper'
|
6
|
+
require_relative 'onlyoffice_testrail_wrapper/mock/rspec_example_mock'
|
7
|
+
require_relative 'onlyoffice_testrail_wrapper/helpers/hash_helper'
|
8
|
+
require_relative 'onlyoffice_testrail_wrapper/helpers/rspec_helper'
|
9
|
+
require_relative 'onlyoffice_testrail_wrapper/helpers/string_helper'
|
10
|
+
require_relative 'onlyoffice_testrail_wrapper/testrail_tools/testrail_tools'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeTestrailWrapper
|
4
|
+
class HashHelper
|
5
|
+
class << self
|
6
|
+
def get_hash_from_array_with_two_parameters(array, key_parameter, value_parameter)
|
7
|
+
raise 'First argument must be Array!' unless array.is_a?(Array)
|
8
|
+
|
9
|
+
result_hash = {}
|
10
|
+
array.reverse_each { |element| result_hash[element[key_parameter]] = element[value_parameter] }
|
11
|
+
result_hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_to_class_variable(hash, class_name)
|
15
|
+
object = class_name.new
|
16
|
+
hash.each { |key, value| object.instance_variable_set("@#{key}", value) }
|
17
|
+
object
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeTestrailWrapper
|
4
|
+
# Methods to some rspec methods
|
5
|
+
module RspecHelper
|
6
|
+
# This method is based on
|
7
|
+
# https://github.com/rspec/rspec-core/blob/v3.3.0/lib/rspec/core/formatters/exception_presenter.rb#L130
|
8
|
+
# It extracted exact line of code from failed exception
|
9
|
+
# @param [RSpec::Core::Example] example
|
10
|
+
# @return [String] line value
|
11
|
+
def self.find_failed_line(example)
|
12
|
+
example_path = example.metadata[:absolute_file_path].downcase
|
13
|
+
dirty_line = example.exception.backtrace.find do |line|
|
14
|
+
next unless (line_path = line[/(.+?):(\d+)(|:\d+)/, 1])
|
15
|
+
|
16
|
+
File.expand_path(line_path).casecmp(example_path).zero?
|
17
|
+
end
|
18
|
+
line_number = dirty_line[/:\d*:/].delete(':').to_i
|
19
|
+
OnlyofficeFileHelper::FileHelper.read_array_from_file(example.metadata[:absolute_file_path])[line_number - 1]
|
20
|
+
rescue StandardError => e
|
21
|
+
"Cannot find failed line because of exception: #{e}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeTestrailWrapper
|
4
|
+
class StringHelper
|
5
|
+
class << self
|
6
|
+
def warnstrip!(string)
|
7
|
+
warn "Beginning or end of string has spaces! In: #{string}" unless string == string.strip
|
8
|
+
string.strip
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
module OnlyofficeTestrailWrapper
|
6
|
+
# Stuff for working with OS
|
7
|
+
class SystemHelper
|
8
|
+
class << self
|
9
|
+
# @return [String] name of current host
|
10
|
+
def hostname
|
11
|
+
name = Socket.gethostname
|
12
|
+
OnlyofficeLoggerHelper.log("hostname is: #{name}")
|
13
|
+
name
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeTestrailWrapper
|
4
|
+
# Mock Rspec example exception
|
5
|
+
class RspecExceptionMock
|
6
|
+
attr_accessor :backtrace
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@backtrace = %w[TestBackTraceLine1 TestBackTraceLine2]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Class for mocking rspec result metadata
|
14
|
+
class RspecExceptionResultMock
|
15
|
+
attr_accessor :started_at
|
16
|
+
end
|
17
|
+
|
18
|
+
# Mock Rspec example
|
19
|
+
class RspecExampleMock
|
20
|
+
# @return [Object] object exception
|
21
|
+
attr_accessor :exception
|
22
|
+
# @return [Object] backtrace object
|
23
|
+
attr_accessor :backtrace
|
24
|
+
# @return [Hash] metadata
|
25
|
+
attr_accessor :metadata
|
26
|
+
# @return [True, False] is test pending
|
27
|
+
attr_accessor :pending
|
28
|
+
# @return [String] description of spec
|
29
|
+
attr_accessor :description
|
30
|
+
|
31
|
+
def initialize(description: 'MockDescription',
|
32
|
+
exception: RspecExceptionMock.new)
|
33
|
+
@exception = exception
|
34
|
+
@metadata = { execution_result: RspecExceptionResultMock.new }
|
35
|
+
@pending = false
|
36
|
+
@description = description
|
37
|
+
@section = ''
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @author Roman.Zagudaev
|
4
|
+
# lib for working with http queries
|
5
|
+
|
6
|
+
require 'net/http'
|
7
|
+
require 'json'
|
8
|
+
require 'yaml'
|
9
|
+
require_relative 'testrail_project'
|
10
|
+
|
11
|
+
module OnlyofficeTestrailWrapper
|
12
|
+
# Main class for working with testrail
|
13
|
+
# dvd_copy = Project.init_project_by_name('AVS Disc Creator')
|
14
|
+
# compete_test_suit= dvd_copy.init_suite_by_name('Complete Test Suite')
|
15
|
+
# test_run_from_api = compete_test_suit.start_test_run('TestRunName', "Simple description")
|
16
|
+
# incompleted_test = test_run_from_api.get_incomplete_tests()
|
17
|
+
# while(incomplete_test.length > 0)
|
18
|
+
# current_test = incomplete_test.sample
|
19
|
+
# p current_test.title
|
20
|
+
# current_test.add_result(Testrail2::TEST_RESULT_OK, 'description','version')
|
21
|
+
# incomplete_test = test_run_from_api.get_incomplete_tests()
|
22
|
+
# end1
|
23
|
+
class Testrail2
|
24
|
+
# @return [String] address of testrail
|
25
|
+
@testrail_url = nil
|
26
|
+
# @return [String] login for admin user
|
27
|
+
@admin_user = nil
|
28
|
+
# @return [String] password for admin user
|
29
|
+
@admin_pass = nil
|
30
|
+
|
31
|
+
# @return [Hash] project information
|
32
|
+
attr_accessor :projects_names
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@projects_names = {}
|
36
|
+
end
|
37
|
+
|
38
|
+
class << self
|
39
|
+
attr_accessor :testrail_url
|
40
|
+
# Attribute to write admin_user
|
41
|
+
attr_writer :admin_user
|
42
|
+
# Attribute to write admin_pass
|
43
|
+
attr_writer :admin_pass
|
44
|
+
|
45
|
+
# @return [String] default config location
|
46
|
+
CONFIG_LOCATION = "#{Dir.home}/.gem-onlyoffice_testrail_wrapper/config.yml"
|
47
|
+
|
48
|
+
def read_keys
|
49
|
+
@testrail_url = ENV['TESTRAIL_URL']
|
50
|
+
@admin_user = ENV['TESTRAIL_USER']
|
51
|
+
@admin_pass = ENV['TESTRAIL_PASSWORD']
|
52
|
+
return unless @admin_user.nil? && @admin_pass.nil?
|
53
|
+
|
54
|
+
begin
|
55
|
+
yaml = YAML.load_file(CONFIG_LOCATION)
|
56
|
+
@testrail_url = yaml['url']
|
57
|
+
@admin_user = yaml['user']
|
58
|
+
@admin_pass = yaml['password']
|
59
|
+
rescue Errno::ENOENT
|
60
|
+
raise Errno::ENOENT, "No user of passwords found in #{CONFIG_LOCATION}. Please create correct config"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def admin_user
|
65
|
+
read_keys
|
66
|
+
@admin_user
|
67
|
+
end
|
68
|
+
|
69
|
+
def admin_pass
|
70
|
+
read_keys
|
71
|
+
@admin_pass
|
72
|
+
end
|
73
|
+
|
74
|
+
def get_testrail_address
|
75
|
+
read_keys unless testrail_url
|
76
|
+
testrail_url
|
77
|
+
end
|
78
|
+
|
79
|
+
# Perform http get on address
|
80
|
+
# @param [String] request_url to perform http get
|
81
|
+
# @return [Hash] Json with result data in hash form
|
82
|
+
def http_get(request_url)
|
83
|
+
uri = URI get_testrail_address + request_url
|
84
|
+
request = Net::HTTP::Get.new uri.request_uri
|
85
|
+
response = send_request(uri, request)
|
86
|
+
JSON.parse response.body
|
87
|
+
end
|
88
|
+
|
89
|
+
# Perform http post on address
|
90
|
+
# @param [String] request_url to perform http get
|
91
|
+
# @param [Hash] data_hash headers to add to post query
|
92
|
+
# @return [Hash] Json with result data in hash form
|
93
|
+
def http_post(request_url, data_hash)
|
94
|
+
uri = URI get_testrail_address + request_url
|
95
|
+
request = Net::HTTP::Post.new uri.request_uri
|
96
|
+
request.body = data_hash.to_json
|
97
|
+
response = send_request(uri, request)
|
98
|
+
return if response.body == ''
|
99
|
+
|
100
|
+
JSON.parse response.body
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# region PROJECT
|
105
|
+
|
106
|
+
def project(name_or_id)
|
107
|
+
case name_or_id.class.to_s
|
108
|
+
when 'Fixnum'
|
109
|
+
get_project_by_id name_or_id
|
110
|
+
when 'String'
|
111
|
+
init_project_by_name name_or_id
|
112
|
+
else
|
113
|
+
raise 'Wrong argument. Must be name [String] or id [Integer]'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Get all projects on testrail
|
118
|
+
# @return [Array, ProjectTestrail] array of projects
|
119
|
+
def get_projects
|
120
|
+
projects = Testrail2.http_get 'index.php?/api/v2/get_projects'
|
121
|
+
@projects_names = HashHelper.get_hash_from_array_with_two_parameters(projects, 'name', 'id') if @projects_names.empty?
|
122
|
+
projects
|
123
|
+
end
|
124
|
+
|
125
|
+
def create_new_project(name, announcement = '', show_announcement = true)
|
126
|
+
new_project = HashHelper.parse_to_class_variable(Testrail2.http_post('index.php?/api/v2/add_project', name: StringHelper.warnstrip!(name.to_s), announcement: announcement,
|
127
|
+
show_announcement: show_announcement), TestrailProject)
|
128
|
+
OnlyofficeLoggerHelper.log "Created new project: #{new_project.name}"
|
129
|
+
new_project.instance_variable_set('@testrail', self)
|
130
|
+
@projects_names[new_project.name] = new_project.id
|
131
|
+
new_project
|
132
|
+
end
|
133
|
+
|
134
|
+
# Initialize project by it's name
|
135
|
+
# @param [String] name name of project
|
136
|
+
# @return [TestrailProject] project with this name
|
137
|
+
def init_project_by_name(name)
|
138
|
+
found_project = get_project_by_name name
|
139
|
+
found_project.nil? ? create_new_project(name) : found_project
|
140
|
+
end
|
141
|
+
|
142
|
+
# Get all projects on testrail
|
143
|
+
# @return [Array, ProjectTestrail] array of projects
|
144
|
+
def get_project_by_id(id)
|
145
|
+
project = HashHelper.parse_to_class_variable(Testrail2.http_get("index.php?/api/v2/get_project/#{id}"), TestrailProject)
|
146
|
+
OnlyofficeLoggerHelper.log("Initialized project: #{project.name}")
|
147
|
+
project.instance_variable_set('@testrail', self)
|
148
|
+
project
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_project_by_name(name)
|
152
|
+
get_projects if @projects_names.empty?
|
153
|
+
@projects_names[StringHelper.warnstrip!(name.to_s)].nil? ? nil : get_project_by_id(@projects_names[StringHelper.warnstrip!(name.to_s)])
|
154
|
+
end
|
155
|
+
|
156
|
+
# Check if Testrail connection is available
|
157
|
+
# @return [True, False] result of test connection
|
158
|
+
def available?
|
159
|
+
get_projects
|
160
|
+
true
|
161
|
+
rescue StandardError
|
162
|
+
false
|
163
|
+
end
|
164
|
+
|
165
|
+
# endregion
|
166
|
+
|
167
|
+
def self.send_request(uri, request)
|
168
|
+
request.basic_auth admin_user, admin_pass
|
169
|
+
request.delete 'content-type'
|
170
|
+
request.add_field 'content-type', 'application/json'
|
171
|
+
is_ssl = (uri.scheme == 'https')
|
172
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: is_ssl) do |http|
|
173
|
+
attempts = 0
|
174
|
+
begin
|
175
|
+
response = http.request(request)
|
176
|
+
rescue Timeout::Error
|
177
|
+
attempts += 1
|
178
|
+
retry if attempts < 3
|
179
|
+
raise 'Timeout error after 3 attempts'
|
180
|
+
rescue StandardError => e
|
181
|
+
raise e
|
182
|
+
end
|
183
|
+
return response
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OnlyofficeTestrailWrapper
|
4
|
+
# @author Roman.Zagudaev
|
5
|
+
# Class for description of test case
|
6
|
+
class TestrailCase
|
7
|
+
# @return [Integer] Id of test case
|
8
|
+
attr_accessor :id
|
9
|
+
# @return [String] title of test case
|
10
|
+
attr_accessor :title
|
11
|
+
# @return [Integer] type id of test case
|
12
|
+
attr_accessor :type_id
|
13
|
+
# @return [Integer] priority id of test case
|
14
|
+
attr_accessor :priority_id
|
15
|
+
# @return [String] Steps of test case
|
16
|
+
attr_accessor :custom_steps
|
17
|
+
# @return [String] Estimated test time
|
18
|
+
attr_accessor :estimate
|
19
|
+
|
20
|
+
# Default constructor
|
21
|
+
# @param [String] title name of test case, default = nil
|
22
|
+
# @param [Integer] type_id type id of test case, default = 3
|
23
|
+
# @param [Integer] priority_id priority id of test case, default = 4
|
24
|
+
# @param [String] custom_steps Steps of test case
|
25
|
+
# @param [Integer] id Id of test case
|
26
|
+
# @return [TestCaseTestrail] new test case
|
27
|
+
def initialize(title = nil, type_id = 3, priority_id = 4, custom_steps = nil, id = nil)
|
28
|
+
@id = id
|
29
|
+
@title = title
|
30
|
+
@type_id = type_id
|
31
|
+
@priority_id = priority_id
|
32
|
+
@custom_steps = custom_steps
|
33
|
+
end
|
34
|
+
|
35
|
+
def update(title = @title, type_id = @type_id, priority_id = @priority_id, custom_steps = @custom_steps)
|
36
|
+
@section.cases_names.delete @title
|
37
|
+
@section.cases_names[StringHelper.warnstrip!(title.to_s)] = @id
|
38
|
+
HashHelper.parse_to_class_variable(Testrail2.http_post("index.php?/api/v2/update_case/#{@id}", title: title, type_id: type_id,
|
39
|
+
priority_id: priority_id, custom_steps: custom_steps), TestrailCase)
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete
|
43
|
+
@section.cases_names.delete @title
|
44
|
+
OnlyofficeLoggerHelper.log "Deleted test case: #{@title}"
|
45
|
+
Testrail2.http_post "index.php?/api/v2/delete_case/#{@id}", {}
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_results(run_id)
|
49
|
+
case_results = Testrail2.http_get "index.php?/api/v2/get_results_for_case/#{run_id}/#{@id}"
|
50
|
+
case_results.each_with_index { |test_case, index| case_results[index] = HashHelper.parse_to_class_variable(test_case, TestrailResult) }
|
51
|
+
case_results
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_result(run_id, result, comment = '', custom_fields = {}, version = '')
|
55
|
+
response = HashHelper.parse_to_class_variable(Testrail2.http_post("index.php?/api/v2/add_result_for_case/#{run_id}/#{@id}", { status_id: TestrailResult::RESULT_STATUSES[result],
|
56
|
+
comment: comment, version: version }.merge(custom_fields)), TestrailResult)
|
57
|
+
OnlyofficeLoggerHelper.log "Set test case result: #{result}. URL: #{Testrail2.get_testrail_address}index.php?/tests/view/#{response.test_id}", output_colors[result]
|
58
|
+
response
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def output_colors
|
64
|
+
{ failed: 45, pending: 43, passed: 42, passed_2: 46, aborted: 41, blocked: 44 }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'onlyoffice_bugzilla_helper'
|
4
|
+
require_relative 'testrail_helper/testrail_helper_rspec_metadata'
|
5
|
+
require_relative 'testrail_helper/testrail_status_helper'
|
6
|
+
require_relative 'testrail'
|
7
|
+
require_relative 'helpers/ruby_helper'
|
8
|
+
require_relative 'helpers/system_helper'
|
9
|
+
|
10
|
+
module OnlyofficeTestrailWrapper
|
11
|
+
# Class with help methods with testrail
|
12
|
+
class TestrailHelper
|
13
|
+
include RubyHelper
|
14
|
+
include TestrailHelperRspecMetadata
|
15
|
+
include TestrailStatusHelper
|
16
|
+
attr_reader :project, :plan, :suite, :run
|
17
|
+
attr_accessor :add_all_suites, :ignore_parameters, :suites_to_add, :search_plan_by_substring, :in_debug, :version
|
18
|
+
|
19
|
+
def initialize(project_name, suite_name = nil, plan_name = nil, run_name = nil)
|
20
|
+
@in_debug = debug?
|
21
|
+
begin
|
22
|
+
@bugzilla_helper = OnlyofficeBugzillaHelper::BugzillaHelper.new
|
23
|
+
rescue Errno::ENOENT
|
24
|
+
@bugzilla_helper = nil
|
25
|
+
end
|
26
|
+
if @in_debug
|
27
|
+
OnlyofficeLoggerHelper.log 'Do not initialize Testrail, because spec run in debug'
|
28
|
+
@run = TestrailRun.new
|
29
|
+
return
|
30
|
+
end
|
31
|
+
OnlyofficeLoggerHelper.log 'Begin initializing Testrail...'
|
32
|
+
@suites_to_add = []
|
33
|
+
@add_all_suites = true
|
34
|
+
@search_plan_by_substring = false
|
35
|
+
yield(self) if block_given?
|
36
|
+
@project = Testrail2.new.project project_name.to_s.dup
|
37
|
+
if plan_name
|
38
|
+
@plan = @project.get_plan_by_name(search_plan_by_substring ? get_plan_name_by_substring(plan_name.to_s) : plan_name.to_s)
|
39
|
+
@plan ||= @project.create_new_plan(plan_name, suites_to_add_hash(@add_all_suites ? all_suites_names : @suites_to_add))
|
40
|
+
end
|
41
|
+
return if suite_name.nil?
|
42
|
+
|
43
|
+
@suite = @project.suite suite_name.to_s
|
44
|
+
if @plan
|
45
|
+
init_run_in_plan(suite_name.to_s)
|
46
|
+
else
|
47
|
+
@run = @project.init_run_by_name(run_name ? run_name.to_s : suite_name.to_s, @suite.id)
|
48
|
+
end
|
49
|
+
raise "Plan '#{@plan.name}' is completed! Cannot add results. See #{@plan.url}" if !@plan.nil? && @plan.is_completed
|
50
|
+
|
51
|
+
OnlyofficeLoggerHelper.log 'Initializing complete!'
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_cases_to_suite(cases, section_name = 'All Test Cases')
|
55
|
+
if @in_debug
|
56
|
+
OnlyofficeLoggerHelper.log 'Do not add test result, because spec run in debug '
|
57
|
+
return
|
58
|
+
end
|
59
|
+
OnlyofficeLoggerHelper.log "Begin scanning #{@suite.name} suite for new cases" unless cases.is_a?(Array)
|
60
|
+
section = @suite.section section_name.to_s
|
61
|
+
existing_cases = section.get_cases.map { |test_case| test_case['title'] }
|
62
|
+
cases.each { |case_name| section.create_new_case case_name.to_s unless existing_cases.include?(case_name) }
|
63
|
+
OnlyofficeLoggerHelper.log 'Suite scanning complete!'
|
64
|
+
@suite = @project.get_suite_by_id @suite.id
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_result_to_test_case(example, comment = '', section_name = 'All Test Cases')
|
68
|
+
if @in_debug
|
69
|
+
OnlyofficeLoggerHelper.log 'Do not add test result, because spec run in debug '
|
70
|
+
return
|
71
|
+
end
|
72
|
+
exception = example.exception
|
73
|
+
custom_fields = init_custom_fields(example)
|
74
|
+
if @ignore_parameters && (ignored_hash = ignore_case?(example.metadata))
|
75
|
+
comment += "\nTest ignored by #{ignored_hash}"
|
76
|
+
result = :blocked
|
77
|
+
elsif example.pending
|
78
|
+
result, comment, bug_id = parse_pending_comment(example.execution_result.pending_message)
|
79
|
+
if example.exception.to_s == 'Expected example to fail since it is pending, but it passed.'
|
80
|
+
result = :failed
|
81
|
+
comment = "Test passed! #{comment}"
|
82
|
+
end
|
83
|
+
custom_fields[:defects] = bug_id.to_s
|
84
|
+
example.add_custom_exception(comment) if result == :failed
|
85
|
+
result = :lpv if comment.downcase.include?('limited program version')
|
86
|
+
elsif exception.to_s.include?('got:') || exception.to_s.include?('expected:')
|
87
|
+
result = :failed
|
88
|
+
failed_line = RspecHelper.find_failed_line(example)
|
89
|
+
comment += "\n#{exception.to_s.gsub('got:', "got:\n").gsub('expected:', "expected:\n")}\nIn line:\n#{failed_line}"
|
90
|
+
elsif exception.to_s.include?('to return') || exception.to_s.include?('expected')
|
91
|
+
result = :failed
|
92
|
+
comment += "\n#{exception.to_s.gsub('to return ', "to return:\n").gsub(', got ', "\ngot:\n")}"
|
93
|
+
elsif exception.to_s.include?('Service Unavailable')
|
94
|
+
result = :service_unavailable
|
95
|
+
comment += "\n#{exception}"
|
96
|
+
elsif exception.to_s.include?('Limited program version')
|
97
|
+
result = :lpv
|
98
|
+
comment += "\n#{exception}"
|
99
|
+
elsif exception.nil?
|
100
|
+
result = if @last_case == example.description
|
101
|
+
:passed_2
|
102
|
+
elsif custom_fields.key?(:custom_js_error)
|
103
|
+
:js_error
|
104
|
+
else
|
105
|
+
:passed
|
106
|
+
end
|
107
|
+
comment += "\nOk"
|
108
|
+
else
|
109
|
+
result = :aborted
|
110
|
+
comment += "\n#{exception}"
|
111
|
+
custom_fields[:custom_autotest_error_line] = exception.backtrace.join("\n") unless exception.backtrace.nil?
|
112
|
+
end
|
113
|
+
@last_case = example.description
|
114
|
+
@suite.section(section_name).case(example.description).add_result @run.id, result, comment, custom_fields
|
115
|
+
end
|
116
|
+
|
117
|
+
def add_result_by_case_name(name, result, comment = 'ok', section_name = 'All Test Cases')
|
118
|
+
@suite.section(section_name).case(name.to_s).add_result(@run.id, result, comment)
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_incomplete_tests
|
122
|
+
@run.get_tests.map { |test| test['title'] if test['status_id'] == 3 || test['status_id'] == 4 }.compact
|
123
|
+
end
|
124
|
+
|
125
|
+
# @param [Array] result. Example: [:retest, :passed]
|
126
|
+
def get_tests_by_result(result)
|
127
|
+
check_status_exist(result)
|
128
|
+
result = [result] unless result.is_a?(Array)
|
129
|
+
@run.get_tests.map { |test| test['title'] if result.include?(TestrailResult::RESULT_STATUSES.key(test['status_id'])) }.compact
|
130
|
+
end
|
131
|
+
|
132
|
+
def delete_plan(plan_name)
|
133
|
+
@project.plan(get_plan_name_by_substring(plan_name.to_s)).delete
|
134
|
+
end
|
135
|
+
|
136
|
+
def mark_rest_environment_dependencies(supported_test_list, status_to_mark = :lpv)
|
137
|
+
get_incomplete_tests.each do |current_test|
|
138
|
+
add_result_by_case_name(current_test, status_to_mark, 'Not supported on this test environment') unless supported_test_list.include?(current_test)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def init_run_in_plan(run_name)
|
145
|
+
@plan.entries.each { |entry| @run = entry.runs.first if entry.name == run_name }
|
146
|
+
@run = @plan.add_entry(run_name, @suite.id).runs.first if @run.nil?
|
147
|
+
OnlyofficeLoggerHelper.log("Initialized run: #{@run.name}")
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_plan_name_by_substring(string)
|
151
|
+
@project.get_plans.each { |plan| return plan['name'] if plan['name'].include?(string) }
|
152
|
+
string
|
153
|
+
end
|
154
|
+
|
155
|
+
def all_suites_names
|
156
|
+
@suites ? (return @suites) : @suites = []
|
157
|
+
@project.get_suites
|
158
|
+
@project.suites_names.each_key { |key| @suites << key }
|
159
|
+
@suites.sort!
|
160
|
+
end
|
161
|
+
|
162
|
+
def ignore_case?(example_metadata)
|
163
|
+
raise 'Ignore parameters must be Hash!!' unless @ignore_parameters.instance_of?(Hash)
|
164
|
+
|
165
|
+
@ignore_parameters.each { |key, value| return { key => value } if example_metadata[key] == value }
|
166
|
+
false
|
167
|
+
end
|
168
|
+
|
169
|
+
def suites_to_add_hash(suites_names)
|
170
|
+
suites_names.map { |suite| all_suites_names.include?(suite) ? { 'suite_id' => @project.suites_names[suite] } : { 'suite_id' => @project.create_new_suite(suite).id } }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|