itriagetestrail 0.0.1
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/lib/itriagetestrail.rb +235 -0
- data/lib/itriagetestrail/pool.rb +35 -0
- data/lib/itriagetestrail/testrail_binding.rb +116 -0
- data/lib/itriagetestrail/version.rb +3 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ca184602865faed2cddddc923bbf3cba340a7c03
|
4
|
+
data.tar.gz: 7424622d43d58c797c2caae9bfb32a1b11c2937a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 97d4a13b3e89e9325c6c80ecfe0822d463db4d4830f7b64ecc45e0f2a7b7f5c0206ab5169f21e7df2880d991ed9878a01f0cfa1aeb2358f648175c5318f0f0da
|
7
|
+
data.tar.gz: bce81ab788adc8bf1b78a5c3d2b10d355e17e40023242c7cb7e70f9951257957c1371161ab93b79a8cc824db106e44f8e97ac39807d484aea3b9b8719e3c2d69
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require "itriagetestrail/version"
|
2
|
+
require_relative "itriagetestrail/testrail_binding"
|
3
|
+
require_relative "itriagetestrail/pool"
|
4
|
+
#require 'testrail-rails'
|
5
|
+
|
6
|
+
|
7
|
+
module Itriagetestrail
|
8
|
+
class TestRailInterface
|
9
|
+
# code goes here...
|
10
|
+
attr_accessor :client
|
11
|
+
attr_accessor :sections
|
12
|
+
attr_accessor :test_cases
|
13
|
+
attr_accessor :test_case_ids
|
14
|
+
attr_accessor :run_id
|
15
|
+
attr_accessor :execute
|
16
|
+
attr_reader :results
|
17
|
+
attr_reader :external_results
|
18
|
+
attr_accessor :pool
|
19
|
+
attr_accessor :batch_size
|
20
|
+
|
21
|
+
def initialize(execute, testrail_config)
|
22
|
+
@run_id = 0
|
23
|
+
@setup = false
|
24
|
+
@testrail_config = testrail_config
|
25
|
+
@project_id = @testrail_config.project_id
|
26
|
+
@execute = execute
|
27
|
+
end
|
28
|
+
|
29
|
+
def setup?
|
30
|
+
@setup
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup
|
34
|
+
return false if setup?
|
35
|
+
|
36
|
+
@results = { results: [] }
|
37
|
+
@submitted = { results: [] }
|
38
|
+
|
39
|
+
@external_results = { results: [] }
|
40
|
+
@batch_size = @testrail_config.batch_size
|
41
|
+
|
42
|
+
make_connection
|
43
|
+
|
44
|
+
# Get the test rail sections
|
45
|
+
testrail_sections
|
46
|
+
|
47
|
+
# Get the test rail ids
|
48
|
+
testrail_ids
|
49
|
+
|
50
|
+
add_testrail_run
|
51
|
+
|
52
|
+
@pool = Pool.new(1)
|
53
|
+
|
54
|
+
@setup = true
|
55
|
+
end
|
56
|
+
|
57
|
+
def make_connection
|
58
|
+
@client = TestRail::APIClient.new(@testrail_config.site)
|
59
|
+
@client.user = @testrail_config.user
|
60
|
+
@client.password = @testrail_config.password
|
61
|
+
end
|
62
|
+
|
63
|
+
# TestRail Sections
|
64
|
+
def testrail_sections
|
65
|
+
@sections = @client.send_get("get_sections/#{@project_id}")
|
66
|
+
end
|
67
|
+
|
68
|
+
def testrail_section_id(section_title)
|
69
|
+
res = -1
|
70
|
+
@sections.each { | section |
|
71
|
+
|
72
|
+
if section['name'] == section_title
|
73
|
+
res = section['id']
|
74
|
+
end
|
75
|
+
}
|
76
|
+
res
|
77
|
+
end
|
78
|
+
|
79
|
+
def add_testrail_section(section_title)
|
80
|
+
body = {
|
81
|
+
:name => section_title
|
82
|
+
}
|
83
|
+
|
84
|
+
res = @client.send_post("add_section/#{@project_id}", body)
|
85
|
+
|
86
|
+
testrail_section = res['id']
|
87
|
+
|
88
|
+
#re-establish sections
|
89
|
+
testrail_sections
|
90
|
+
|
91
|
+
testrail_section
|
92
|
+
end
|
93
|
+
|
94
|
+
# TestRail Cases
|
95
|
+
def testrail_ids
|
96
|
+
|
97
|
+
@test_cases = @client.send_get("get_cases/#{@project_id}&type_id=3")
|
98
|
+
|
99
|
+
@test_case_ids = []
|
100
|
+
|
101
|
+
@test_cases.each { |test_case| @test_case_ids << test_case['id']}
|
102
|
+
end
|
103
|
+
|
104
|
+
def testrail_test_case_id(external_id)
|
105
|
+
|
106
|
+
res = -1
|
107
|
+
@test_cases.each { | test_case |
|
108
|
+
|
109
|
+
if test_case['custom_external_case_id'] == external_id
|
110
|
+
res = test_case['id']
|
111
|
+
end
|
112
|
+
}
|
113
|
+
res
|
114
|
+
end
|
115
|
+
|
116
|
+
def associate_result(external_id)
|
117
|
+
|
118
|
+
test_case_id = testrail_test_case_id(external_id)
|
119
|
+
#store the test case id with the local result
|
120
|
+
@results[:results].each { |result|
|
121
|
+
|
122
|
+
if result['external_id'] == external_id
|
123
|
+
@external_results['results'] << {case_id: test_case_id, status_id: result['status_id'], comment: result['comment']}
|
124
|
+
end
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
# add the test case if it doesn't exist
|
129
|
+
def add_testrail_test_case(scenario_title, external_id, scenario_steps, section_id)
|
130
|
+
body = {
|
131
|
+
:title => scenario_title,
|
132
|
+
:custom_external_case_id => external_id,
|
133
|
+
:custom_steps => scenario_steps,
|
134
|
+
:type_id => 3
|
135
|
+
}
|
136
|
+
|
137
|
+
@client.send_post("add_case/#{section_id}", body)
|
138
|
+
|
139
|
+
#refresh test case ids
|
140
|
+
testrail_ids
|
141
|
+
end
|
142
|
+
|
143
|
+
# open a test run to submit test results
|
144
|
+
def add_testrail_run
|
145
|
+
|
146
|
+
if @testrail_config.include_all? then
|
147
|
+
|
148
|
+
body = {
|
149
|
+
:name => "POC Regression on #{Time.now}",
|
150
|
+
:include_all => true
|
151
|
+
}
|
152
|
+
else
|
153
|
+
|
154
|
+
body = {
|
155
|
+
:name => "POC Regression on #{Time.now}",
|
156
|
+
:include_all => false,
|
157
|
+
:case_ids => @test_case_ids
|
158
|
+
}
|
159
|
+
end
|
160
|
+
|
161
|
+
res = @client.send_post("add_run/#{@project_id}", body)
|
162
|
+
|
163
|
+
@run_id = res['id']
|
164
|
+
end
|
165
|
+
|
166
|
+
def send_results_to_testrail
|
167
|
+
if @results[:results].size != 0
|
168
|
+
|
169
|
+
# copy what is in the results
|
170
|
+
@submitted[:results] << @results[:results]
|
171
|
+
|
172
|
+
send = {:results => @results[:results]}
|
173
|
+
@pool.schedule do
|
174
|
+
#make sure tests are part of current run
|
175
|
+
@client.send_post("add_results_for_cases/#{@run_id}", send)
|
176
|
+
end
|
177
|
+
|
178
|
+
@results[:results] = @results[:results] - send[:results]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def update_test_suite(scenario_title, external_id, scenario_steps)
|
183
|
+
|
184
|
+
# establish variables
|
185
|
+
#@external_id = result['external_id']
|
186
|
+
|
187
|
+
feature = external_id.split(';')[0]
|
188
|
+
|
189
|
+
section_id = testrail_section_id(feature)
|
190
|
+
|
191
|
+
#if the testrail section does not exist, update sections
|
192
|
+
if section_id == -1
|
193
|
+
|
194
|
+
section_id = add_testrail_section(feature)
|
195
|
+
end
|
196
|
+
|
197
|
+
#if the testrail case does not exist, update cases
|
198
|
+
if testrail_test_case_id(external_id) == -1
|
199
|
+
|
200
|
+
#@scenario_title = result['scenario_title']
|
201
|
+
|
202
|
+
add_testrail_test_case(scenario_title, external_id, scenario_steps, section_id)
|
203
|
+
sleep 1
|
204
|
+
end
|
205
|
+
|
206
|
+
#store the case id associated with the external_id
|
207
|
+
associate_result(external_id)
|
208
|
+
end
|
209
|
+
|
210
|
+
|
211
|
+
def store_result(scenario_title, external_id, scenario_steps, status_id, comment)
|
212
|
+
|
213
|
+
update_test_suite scenario_title, external_id, scenario_steps
|
214
|
+
|
215
|
+
case_id = testrail_test_case_id(external_id)
|
216
|
+
|
217
|
+
@results[:results] << {case_id: case_id, scenario_title: scenario_title, external_id: external_id, scenario_steps: scenario_steps, status_id: status_id, comment: comment }
|
218
|
+
|
219
|
+
if @results[:results].size >= @batch_size
|
220
|
+
|
221
|
+
send_results_to_testrail
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def shutdown
|
227
|
+
@pool.shutdown
|
228
|
+
|
229
|
+
if @testrail_config.close_run?
|
230
|
+
@client.send_post("close_run/#{@run_id}", {})
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
class Pool
|
4
|
+
|
5
|
+
def initialize(size)
|
6
|
+
|
7
|
+
@size = size
|
8
|
+
@jobs = Queue.new
|
9
|
+
|
10
|
+
@pool = Array.new(@size) do |i|
|
11
|
+
Thread.new do
|
12
|
+
Thread.current[:id] = i
|
13
|
+
|
14
|
+
catch(:exit) do
|
15
|
+
loop do
|
16
|
+
job, args = @jobs.pop
|
17
|
+
job.call(*args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def schedule(*args, &block)
|
25
|
+
@jobs << [block, args]
|
26
|
+
end
|
27
|
+
|
28
|
+
def shutdown
|
29
|
+
@size.times do
|
30
|
+
schedule { throw :exit }
|
31
|
+
end
|
32
|
+
|
33
|
+
@pool.map(&:join)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#
|
2
|
+
# TestRail API binding for Ruby (API v2, available since TestRail 3.0)
|
3
|
+
#
|
4
|
+
# Learn more:
|
5
|
+
#
|
6
|
+
# http://docs.gurock.com/testrail-api2/start
|
7
|
+
# http://docs.gurock.com/testrail-api2/accessing
|
8
|
+
#
|
9
|
+
# Copyright Gurock Software GmbH. See license.md for details.
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'net/http'
|
13
|
+
require 'net/https'
|
14
|
+
require 'uri'
|
15
|
+
require 'json'
|
16
|
+
|
17
|
+
module TestRail
|
18
|
+
class APIClient
|
19
|
+
@url = ''
|
20
|
+
@user = ''
|
21
|
+
@password = ''
|
22
|
+
|
23
|
+
attr_accessor :user
|
24
|
+
attr_accessor :password
|
25
|
+
|
26
|
+
def initialize(base_url)
|
27
|
+
if !base_url.match(/\/$/)
|
28
|
+
base_url += '/'
|
29
|
+
end
|
30
|
+
@url = base_url + 'index.php?/api/v2/'
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Send Get
|
35
|
+
#
|
36
|
+
# Issues a GET request (read) against the API and returns the result
|
37
|
+
# (as Ruby hash).
|
38
|
+
#
|
39
|
+
# Arguments:
|
40
|
+
#
|
41
|
+
# uri The API method to call including parameters
|
42
|
+
# (e.g. get_case/1)
|
43
|
+
#
|
44
|
+
def send_get(uri)
|
45
|
+
_send_request('GET', uri, nil)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Send POST
|
50
|
+
#
|
51
|
+
# Issues a POST request (write) against the API and returns the result
|
52
|
+
# (as Ruby hash).
|
53
|
+
#
|
54
|
+
# Arguments:
|
55
|
+
#
|
56
|
+
# uri The API method to call including parameters
|
57
|
+
# (e.g. add_case/1)
|
58
|
+
# data The data to submit as part of the request (as
|
59
|
+
# Ruby hash, strings must be UTF-8 encoded)
|
60
|
+
#
|
61
|
+
def send_post(uri, data)
|
62
|
+
_send_request('POST', uri, data)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def make_connection(url)
|
67
|
+
conn = Net::HTTP.new(url.host, url.port)
|
68
|
+
if url.scheme == 'https'
|
69
|
+
conn.use_ssl = true
|
70
|
+
conn.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
71
|
+
end
|
72
|
+
conn
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse_json(response)
|
76
|
+
if response.body && !response.body.empty?
|
77
|
+
result = JSON.parse(response.body)
|
78
|
+
else
|
79
|
+
result = {}
|
80
|
+
end
|
81
|
+
result
|
82
|
+
end
|
83
|
+
|
84
|
+
def _send_request(method, uri, data)
|
85
|
+
url = URI.parse(@url + uri)
|
86
|
+
if method == 'POST'
|
87
|
+
request = Net::HTTP::Post.new(url.path + '?' + url.query)
|
88
|
+
request.body = JSON.dump(data)
|
89
|
+
else
|
90
|
+
request = Net::HTTP::Get.new(url.path + '?' + url.query)
|
91
|
+
end
|
92
|
+
request.basic_auth(@user, @password)
|
93
|
+
request.add_field('Content-Type', 'application/json')
|
94
|
+
|
95
|
+
conn = make_connection(url)
|
96
|
+
|
97
|
+
response = conn.request(request)
|
98
|
+
|
99
|
+
result = parse_json(response)
|
100
|
+
|
101
|
+
if response.code != '200'
|
102
|
+
if result && result.key?('error')
|
103
|
+
error = '"' + result['error'] + '"'
|
104
|
+
else
|
105
|
+
error = 'No additional error message received'
|
106
|
+
end
|
107
|
+
|
108
|
+
raise APIError, "TestRail API returned HTTP #{response.code} #{error}"
|
109
|
+
end
|
110
|
+
result
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class APIError < StandardError
|
115
|
+
end
|
116
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: itriagetestrail
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- a801069
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Plugin to export your cucumber tests in the Testrail
|
56
|
+
email:
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/itriagetestrail.rb
|
62
|
+
- lib/itriagetestrail/testrail_binding.rb
|
63
|
+
- lib/itriagetestrail/pool.rb
|
64
|
+
- lib/itriagetestrail/version.rb
|
65
|
+
homepage:
|
66
|
+
licenses: []
|
67
|
+
metadata: {}
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
requirements: []
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 2.0.14
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Plugin to export your cucumber tests in the Testrail
|
88
|
+
test_files: []
|