itriagetestrail 1.0.36
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 +254 -0
- data/lib/itriagetestrail/framework_bindings/trcucumber13.rb +46 -0
- data/lib/itriagetestrail/framework_bindings/trcucumber20.rb +44 -0
- data/lib/itriagetestrail/framework_bindings/trcucumber30.rb +44 -0
- data/lib/itriagetestrail/framework_bindings/trminitest.rb +29 -0
- data/lib/itriagetestrail/pool.rb +33 -0
- data/lib/itriagetestrail/testrail_binding.rb +187 -0
- data/lib/itriagetestrail/testrail_objects/milestones.rb +135 -0
- data/lib/itriagetestrail/testrail_objects/projects.rb +52 -0
- data/lib/itriagetestrail/testrail_objects/sections.rb +46 -0
- data/lib/itriagetestrail/testrail_objects/suites.rb +32 -0
- data/lib/itriagetestrail/testrail_objects/test_cases.rb +83 -0
- data/lib/itriagetestrail/testrail_objects/test_plans.rb +91 -0
- data/lib/itriagetestrail/testrail_objects/test_results.rb +131 -0
- data/lib/itriagetestrail/testrail_objects/test_runs.rb +53 -0
- data/lib/itriagetestrail/version.rb +3 -0
- metadata +127 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Itriagetestrail
|
4
|
+
module TestCases
|
5
|
+
# TestRail Cases
|
6
|
+
def testrail_ids
|
7
|
+
case @suite_mode
|
8
|
+
when 2, 3
|
9
|
+
@test_cases = @client.send_get("get_cases/#{@project_id}&suite_id=#{@suite_id}&type_id=3")
|
10
|
+
else
|
11
|
+
@test_cases = @client.send_get("get_cases/#{@project_id}&type_id=3")
|
12
|
+
end
|
13
|
+
|
14
|
+
@test_case_ids = []
|
15
|
+
|
16
|
+
@test_cases.each { |test_case| @test_case_ids << test_case['id'] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def testrail_test_case_id(external_id)
|
20
|
+
res = -1
|
21
|
+
@test_cases.each do |test_case|
|
22
|
+
res = test_case['id'] if test_case['custom_external_case_id'] == external_id
|
23
|
+
end
|
24
|
+
res
|
25
|
+
end
|
26
|
+
|
27
|
+
def associate_result(external_id)
|
28
|
+
test_case_id = testrail_test_case_id(external_id)
|
29
|
+
# store the test case id with the local result
|
30
|
+
@results[:results].each do |result|
|
31
|
+
next unless result[:external_id] == external_id
|
32
|
+
@external_results[:results] << { case_id: test_case_id,
|
33
|
+
status_id: result['status_id'],
|
34
|
+
comment: result['comment'] }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# add the test case if it doesn't exist
|
39
|
+
def add_testrail_test_case(scenario_title, external_id, scenario_steps, section_id)
|
40
|
+
body = {
|
41
|
+
title: scenario_title,
|
42
|
+
custom_external_case_id: external_id,
|
43
|
+
custom_steps: scenario_steps,
|
44
|
+
type_id: 3
|
45
|
+
}
|
46
|
+
|
47
|
+
@client.send_post("add_case/#{section_id}", body)
|
48
|
+
|
49
|
+
# refresh test case ids
|
50
|
+
testrail_ids
|
51
|
+
end
|
52
|
+
|
53
|
+
def app_version_label
|
54
|
+
if @app_version.nil? || @app_version.empty?
|
55
|
+
''
|
56
|
+
else
|
57
|
+
"App Version:#{@app_version}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def jenkins_build_label
|
62
|
+
if @jenkins_build .nil? || @jenkins_build.empty?
|
63
|
+
''
|
64
|
+
else
|
65
|
+
" Jenkins Build:#{@jenkins_build}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def time_zone_label
|
70
|
+
' (' + @time_zone.now.strftime('%-I:%M %p') + ')'
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_name
|
74
|
+
ci_label = "#{app_version_label}#{jenkins_build_label}"
|
75
|
+
|
76
|
+
if ci_label.dup.strip.empty?
|
77
|
+
'Regression' + time_zone_label
|
78
|
+
else
|
79
|
+
ci_label + time_zone_label
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Itriagetestrail
|
4
|
+
module TestPlans
|
5
|
+
def configuration_group(name)
|
6
|
+
res = {}
|
7
|
+
@configurations.each do |config|
|
8
|
+
res = config if config['name'] == name
|
9
|
+
end
|
10
|
+
res
|
11
|
+
end
|
12
|
+
|
13
|
+
def config_id(name, value)
|
14
|
+
res = {}
|
15
|
+
configuration = configuration_group(name)
|
16
|
+
|
17
|
+
return nil if configuration.empty?
|
18
|
+
configuration['configs'].each do |config|
|
19
|
+
res = config['id'] if config['name'] == value
|
20
|
+
end
|
21
|
+
res
|
22
|
+
end
|
23
|
+
|
24
|
+
def configurations
|
25
|
+
@configurations = @client.send_get("get_configs/#{@project_id}")
|
26
|
+
end
|
27
|
+
|
28
|
+
def configuration_ids
|
29
|
+
@configuration_ids = []
|
30
|
+
|
31
|
+
# evaluate @testrail_comfig
|
32
|
+
append_configuration_ids('Browser', @testrail_config[:config][:browser])
|
33
|
+
append_configuration_ids('Browser Version', @testrail_config[:config][:browserVersion])
|
34
|
+
append_configuration_ids('Platform', @testrail_config[:config][:platform])
|
35
|
+
append_configuration_ids('Android Version', @testrail_config[:config][:android])
|
36
|
+
append_configuration_ids('Android Device', @testrail_config[:config][:androidDevice])
|
37
|
+
append_configuration_ids('IOS Version', @testrail_config[:config][:ios])
|
38
|
+
|
39
|
+
# remove the nils
|
40
|
+
@configuration_ids.compact!
|
41
|
+
|
42
|
+
@configuration_ids
|
43
|
+
end
|
44
|
+
|
45
|
+
def append_configuration_ids(topic, configuration)
|
46
|
+
@configuration_ids << config_id(topic, configuration) unless configuration.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_testrail_plan
|
50
|
+
body = {
|
51
|
+
name: test_name,
|
52
|
+
description: '',
|
53
|
+
milestone_id: @milestone_id
|
54
|
+
}
|
55
|
+
|
56
|
+
@plan = @client.send_post("add_plan/#{@project_id}", body)
|
57
|
+
# TODO: replace debugging
|
58
|
+
puts @plan.inspect
|
59
|
+
|
60
|
+
@plan_id = @plan['id']
|
61
|
+
# TODO: replace debugging
|
62
|
+
puts @plan_id.inspect
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_plan_entry
|
66
|
+
# TODO: refactor redundant assignments of @suite_id
|
67
|
+
@suite_id = testrail_suite_id(@suite_name)
|
68
|
+
body = {
|
69
|
+
suite_id: @suite_id,
|
70
|
+
# TODO: replace hardcoded name
|
71
|
+
name: 'replace this with config description',
|
72
|
+
include_all: true,
|
73
|
+
# TODO: replace hardcoded config
|
74
|
+
config_ids: configuration_ids,
|
75
|
+
runs: [
|
76
|
+
{
|
77
|
+
include_all: true,
|
78
|
+
config_ids: configuration_ids
|
79
|
+
}
|
80
|
+
]
|
81
|
+
}
|
82
|
+
|
83
|
+
@plan_entry = @client.send_post("add_plan_entry/#{@plan_id}", body)
|
84
|
+
# TODO: replace debugging
|
85
|
+
puts @plan_entry.inspect
|
86
|
+
@run_id = @plan_entry['runs'][0]['id']
|
87
|
+
# TODO: replace debugging
|
88
|
+
puts @run_id.inspect
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Itriagetestrail
|
4
|
+
module TestResults
|
5
|
+
def send_results_to_testrail
|
6
|
+
return if @results[:results].empty?
|
7
|
+
# copy what is in the results
|
8
|
+
@submitted[:results] << @results[:results]
|
9
|
+
|
10
|
+
begin
|
11
|
+
send = { results: @results[:results] }
|
12
|
+
@client.send_post("add_results_for_cases/#{@run_id}", send)
|
13
|
+
clear_results
|
14
|
+
rescue StandardError => e
|
15
|
+
raise e
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# In implementations where there is not an at_exit, parallel test threads can store results
|
20
|
+
# of tests from the completed test class into a batch file, so final processing sends all results
|
21
|
+
# at the very end of the job while avoiding rate limiting issues.
|
22
|
+
def store_results_to_batch_file
|
23
|
+
return if @results[:results].empty?
|
24
|
+
entry = {runId: @run_id, results: @results[:results]}
|
25
|
+
|
26
|
+
Dir.mkdir('./tmp') unless File.exist?('./tmp')
|
27
|
+
file = File.open("./tmp/batch", 'a')
|
28
|
+
file.write("#{entry}\n")
|
29
|
+
file.close
|
30
|
+
|
31
|
+
# keep track of what is submitted
|
32
|
+
@submitted[:results] << @results[:results]
|
33
|
+
|
34
|
+
# clear the buffer for next class
|
35
|
+
@results[:results] = []
|
36
|
+
end
|
37
|
+
|
38
|
+
# Use this method to read bulk records of results stored in the temp file, and send entire set as a
|
39
|
+
# post execution batch.
|
40
|
+
def send_batch_results_to_testrail
|
41
|
+
content = read_batch_file
|
42
|
+
begin
|
43
|
+
send = { results: content[:results] }
|
44
|
+
@client.send_post("add_results_for_cases/#{content[:runId]}", send)
|
45
|
+
clear_results
|
46
|
+
rescue StandardError => e
|
47
|
+
raise e
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def read_batch_file
|
52
|
+
return unless File.exist?('./tmp/batch')
|
53
|
+
run_id = nil
|
54
|
+
results = []
|
55
|
+
File.open("./tmp/batch").each do |line|
|
56
|
+
content = eval(line)
|
57
|
+
unless run_id
|
58
|
+
run_id = content[:runId]
|
59
|
+
end
|
60
|
+
content[:results].each { |result| results << result }
|
61
|
+
end
|
62
|
+
{runId: run_id, results: results}
|
63
|
+
end
|
64
|
+
|
65
|
+
def update_test_suite(scenario_title, external_id, scenario_steps)
|
66
|
+
feature = external_id.split(';')[0].split('#')[0]
|
67
|
+
|
68
|
+
# if the testrail case does not exist, update cases
|
69
|
+
if testrail_test_case_id(external_id) == -1
|
70
|
+
|
71
|
+
section_id = testrail_section_id(feature)
|
72
|
+
|
73
|
+
# if the testrail section does not exist, update sections
|
74
|
+
section_id = add_testrail_section(feature) if section_id == -1
|
75
|
+
|
76
|
+
add_testrail_test_case(scenario_title, external_id, scenario_steps, section_id)
|
77
|
+
sleep 1
|
78
|
+
|
79
|
+
# Update Test Run
|
80
|
+
extend_testrail_run
|
81
|
+
end
|
82
|
+
# store the case id associated with the external_id
|
83
|
+
associate_result(external_id)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Called during after_teardown, this saves the result of the test method or scenario
|
87
|
+
# into local memory for later processing
|
88
|
+
def store_result(scenario_title, external_id, scenario_steps, status_id, comment)
|
89
|
+
update_test_suite scenario_title, external_id, scenario_steps
|
90
|
+
|
91
|
+
case_id = testrail_test_case_id(external_id)
|
92
|
+
@results[:results] << {
|
93
|
+
case_id: case_id,
|
94
|
+
scenario_title: scenario_title,
|
95
|
+
external_id: external_id,
|
96
|
+
scenario_steps: scenario_steps,
|
97
|
+
status_id: status_id,
|
98
|
+
comment: comment,
|
99
|
+
custom_branch_name: @testrail_config[:origin]
|
100
|
+
}
|
101
|
+
|
102
|
+
# Pull Tag IDs
|
103
|
+
unless @scenario_tags.nil?
|
104
|
+
|
105
|
+
# https://github.com/cucumber/cucumber-ruby/blob/master/lib/cucumber/runtime.rb
|
106
|
+
# Test has to actually run in order to populate testrail.
|
107
|
+
|
108
|
+
testrail_tag_object = @testrail_case_fields.select { |field| field['system_name'] == 'custom_tags'}[0]
|
109
|
+
testrail_tag_items = testrail_tag_object['configs'][0]['options']['items'].split("\n")
|
110
|
+
scenario_tag_ids = []
|
111
|
+
@scenario_tags.each do |scenario_tag|
|
112
|
+
testrail_tag_items.each do | tag_item |
|
113
|
+
system_tag = tag_item.split(',')
|
114
|
+
if scenario_tag == system_tag[1]
|
115
|
+
scenario_tag_ids << system_tag[0].to_i
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
current_case = @test_cases.select { |item| item['id'] == case_id }[0]
|
121
|
+
|
122
|
+
testrail_case_tag_ids = current_case['custom_tags']
|
123
|
+
testrail_case_steps = current_case['custom_steps']
|
124
|
+
|
125
|
+
if testrail_case_tag_ids == scenario_tag_ids || testrail_case_steps == @scenario_steps
|
126
|
+
@client.send_post("update_case/#{case_id}", { 'custom_tags': scenario_tag_ids, 'custom_steps': @scenario_steps})
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Itriagetestrail
|
4
|
+
module TestRuns
|
5
|
+
def extend_testrail_run
|
6
|
+
# Reset test scope to include all cases
|
7
|
+
body = { include_all: true }
|
8
|
+
@client.send_post("update_run/#{@run_id}", body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def existing_cases_from_description
|
12
|
+
# Grabs from testrail run description
|
13
|
+
run = @client.send_get("get_run/#{@run_id}")
|
14
|
+
@description = run['description']
|
15
|
+
@description.nil? ? [] : @description.split(',')
|
16
|
+
end
|
17
|
+
|
18
|
+
def existing_cases_from_run(run_id = @run_id)
|
19
|
+
allowed_statuses = %i[1 2 4 5]
|
20
|
+
allowed_statuses << 6 if @testrail_config[:report_skips] == 'true'
|
21
|
+
tests = @client.send_get("get_tests/#{run_id}&status_id=#{allowed_statuses.compact.join(',')}") || []
|
22
|
+
|
23
|
+
cases = []
|
24
|
+
|
25
|
+
tests.each do |test|
|
26
|
+
cases << test['case_id']
|
27
|
+
end
|
28
|
+
cases
|
29
|
+
end
|
30
|
+
|
31
|
+
# open a test run to submit test results
|
32
|
+
def add_testrail_run
|
33
|
+
body = {
|
34
|
+
name: test_name,
|
35
|
+
description: '',
|
36
|
+
include_all: true,
|
37
|
+
milestone_id: @milestone_id
|
38
|
+
}
|
39
|
+
|
40
|
+
unless @testrail_config[:include_all] == 'true'
|
41
|
+
body[:include_all] = false
|
42
|
+
body[:case_ids] = @test_case_ids
|
43
|
+
end
|
44
|
+
|
45
|
+
case @suite_mode
|
46
|
+
when 2, 3
|
47
|
+
body[:suite_id] = @suite_id
|
48
|
+
end
|
49
|
+
res = @client.send_post("add_run/#{@project_id}", body)
|
50
|
+
@run_id = res['id']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: itriagetestrail
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.36
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- a801069
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tzinfo
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.56.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.56.0
|
83
|
+
description: Plugin to export your cucumber tests in the Testrail
|
84
|
+
email:
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- lib/itriagetestrail.rb
|
90
|
+
- lib/itriagetestrail/framework_bindings/trcucumber13.rb
|
91
|
+
- lib/itriagetestrail/framework_bindings/trcucumber20.rb
|
92
|
+
- lib/itriagetestrail/framework_bindings/trcucumber30.rb
|
93
|
+
- lib/itriagetestrail/framework_bindings/trminitest.rb
|
94
|
+
- lib/itriagetestrail/pool.rb
|
95
|
+
- lib/itriagetestrail/testrail_binding.rb
|
96
|
+
- lib/itriagetestrail/testrail_objects/milestones.rb
|
97
|
+
- lib/itriagetestrail/testrail_objects/projects.rb
|
98
|
+
- lib/itriagetestrail/testrail_objects/sections.rb
|
99
|
+
- lib/itriagetestrail/testrail_objects/suites.rb
|
100
|
+
- lib/itriagetestrail/testrail_objects/test_cases.rb
|
101
|
+
- lib/itriagetestrail/testrail_objects/test_plans.rb
|
102
|
+
- lib/itriagetestrail/testrail_objects/test_results.rb
|
103
|
+
- lib/itriagetestrail/testrail_objects/test_runs.rb
|
104
|
+
- lib/itriagetestrail/version.rb
|
105
|
+
homepage:
|
106
|
+
licenses: []
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubygems_version: 3.0.3
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Plugin to export your cucumber tests in the Testrail
|
127
|
+
test_files: []
|