itriagetestrail 1.0.2 → 1.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 60a7641e7255058ed13e18ca80a789133c7e5eba
4
- data.tar.gz: 1311492cd1cd2f59dc9cfe20a303d126b5c15430
3
+ metadata.gz: 2cf1256452b3bb7d41e2eaa822e7139af10acf1e
4
+ data.tar.gz: b9864514855c3cdaba1d96d518f3da7fad81479c
5
5
  SHA512:
6
- metadata.gz: 3a261214a074fd3f997371f7824e1767439cd81c237f28286326644ccee5e0bb630c50b872b9282cbe1419bb46221be0ec820ba32a38c82f0130cdcdc9e0d3b0
7
- data.tar.gz: 256e30f116140fc04f1c02d98d1642e7667e79f6a4c6bebdc8a5644af81df80001a1178073d893e61e0d0c8e80f40967f1644712ac9062c9b74a84bb7fa51047
6
+ metadata.gz: 27c259fd9132e190b92559fa4959e15b135c8ef6562ea83f2c56669701f21420a842f8001c20338a8c661c67eacb232a6f9ac9f02d8c39c9a9f96f6e6f836a60
7
+ data.tar.gz: e5d82b254b2d99305d1c92696c55c169d7aaf8af2e67438f92e1e7e8e42c5404d20aff9891fd162da4f4731060564419101e2455628c4272cabcb8934d30a80b
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzinfo'
4
+
5
+ module Itriagetestrail
6
+ module Milestones
7
+
8
+ # Establish the milestone name based on origin passed in,
9
+ # usually origin represents a branch or environment
10
+ def normalize_milestone
11
+ if @testrail_config[:milestone].nil? || @testrail_config[:milestone].empty?
12
+ case @testrail_config[:origin]
13
+ when 'prd', 'production', 'origin/production'
14
+ 'Production'
15
+ when 'stg', 'staging', 'origin/staging'
16
+ 'Staging'
17
+ when 'dev', 'development', 'origin/development'
18
+ 'Development'
19
+ when 'local', ''
20
+ 'Local'
21
+ when 'master', 'origin/master'
22
+ 'Master'
23
+ else
24
+ 'Dev Branch'
25
+ end
26
+ else
27
+ @testrail_config[:milestone]
28
+ end
29
+ end
30
+
31
+ # returns timestamp for begining of first day of current quarter
32
+ def milestone_period_start
33
+ time_zone = TZInfo::Timezone.get('America/Denver')
34
+ current_year = time_zone.now.year
35
+ month = time_zone.now.mon
36
+
37
+ # determine which quarter we are in
38
+ if month <= 3
39
+ time_zone.utc_to_local(Time.utc(current_year, 1, 1))
40
+ elsif month <= 6
41
+ time_zone.utc_to_local(Time.utc(current_year, 4, 1))
42
+ elsif month <= 9
43
+ time_zone.utc_to_local(Time.utc(current_year, 7, 1))
44
+ else
45
+ time_zone.utc_to_local(Time.utc(current_year, 10, 1))
46
+ end
47
+ end
48
+
49
+ # determine the due date (end of quarter) for a new milestone being added
50
+ def milestone_due_date
51
+ time_zone = TZInfo::Timezone.get('America/Denver')
52
+ current_year = time_zone.now.year
53
+ month = time_zone.now.mon
54
+
55
+ # determine which quarter we are in
56
+ if month <= 3
57
+ Time.utc(current_year, 3, 31).strftime('%s')
58
+ elsif month <= 6
59
+ Time.utc(current_year, 6, 30).strftime('%s')
60
+ elsif month <= 9
61
+ Time.utc(current_year, 9, 30).strftime('%s')
62
+ else
63
+ Time.new(current_year, 12, 31).strftime('%s')
64
+ end
65
+ end
66
+
67
+ # returns the id for a requested milestone by name, or creates one if the milestone does not exist
68
+ def fetch_milestone(requested_milestone_name)
69
+ milestones = @client.send_get("get_milestones/#{@project_id}")
70
+ res = -1
71
+ milestones.each do |milestone|
72
+ res = milestone['id'] if milestone['name'] == requested_milestone_name
73
+ end
74
+
75
+ if res == -1
76
+ # We need to add the milestone to TestRail
77
+
78
+ body = {
79
+ name: requested_milestone_name,
80
+ due_on: milestone_due_date
81
+ }
82
+
83
+ res = @client.send_post("add_milestone/#{@project_id}", body)['id']
84
+ end
85
+ res
86
+ end
87
+
88
+ # return a standardized name for a milestone to be archived
89
+ def milestone_archive_name(milestone_name, date)
90
+ year = date.year
91
+ month = date.mon
92
+
93
+ if month <= 3
94
+ "#{milestone_name} #{year}-Q1"
95
+ elsif month <= 6
96
+ "#{milestone_name} #{year}-Q2"
97
+ elsif month <= 9
98
+ "#{milestone_name} #{year}-Q3"
99
+ else
100
+ "#{milestone_name} #{year}-Q4"
101
+ end
102
+ end
103
+
104
+ # return all the runs associated with an existing milestone
105
+ def milestone_runs(milestone_name)
106
+ # use the matching milestone id for project
107
+ milestone_id = fetch_milestone(milestone_name)
108
+
109
+ # fetch all test runs associated with the milestone id for project
110
+ @client.send_get("get_runs/#{@project_id}&milestone_id=#{milestone_id}&is_completed=1") || []
111
+ end
112
+
113
+ # testrail call to rename a milestone (for archiving)
114
+ def rename_milestone(id, new_name)
115
+ # todo: rename milestone with previous_milestone
116
+ body = { name: new_name }
117
+ res = @client.send_post("update_milestone/#{id}", body)['id']
118
+ end
119
+
120
+ # this archives a milestone at the turn of a quarter and creates a new one in its place
121
+ def reset_milestone(milestone_name)
122
+ runs = milestone_runs(milestone_name)
123
+ if runs.size > 0
124
+ last_run_time = Time.at(runs.last['completed_on'])
125
+ if last_run_time < milestone_period_start
126
+ rename_milestone(@milestone_id, milestone_archive_name(milestone_name, last_run_time))
127
+ @milestone_id = fetch_milestone(@milestone_name)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'itriagetestrail/version'
4
+ require 'itriagetestrail/testrail_binding'
5
+ require 'itriagetestrail/pool'
6
+ require 'tzinfo'
7
+
8
+ module Itriagetestrail
9
+ module Projects
10
+ # populate projects instance variable with all projects objects in the testrail site
11
+ def projects
12
+ @projects ||= @client.send_get('get_projects')
13
+ end
14
+
15
+ def project_by_name(name)
16
+ res = -1
17
+ projects.each do |project|
18
+ res = project if project['name'] == name
19
+ end
20
+ res
21
+ end
22
+
23
+ # return the project object for a given project id
24
+ def project_by_id(id)
25
+ res = -1
26
+ projects.each do |project|
27
+ res = project if project['id'] == id.to_i
28
+ end
29
+ res
30
+ end
31
+
32
+ # set the project_id by a requested project from config/environment variable
33
+ def set_project
34
+ requested_id = @testrail_config[:projectId]
35
+ case requested_id
36
+ when nil, ''
37
+ # a project id was not provided, fetch it from TestRail by project name
38
+ res = project_by_name(@testrail_config[:projectName])
39
+ if res == -1
40
+ @execute = false
41
+ return
42
+ end
43
+ @project_id = res['id']
44
+ @suite_mode = res['suite_mode']
45
+ else
46
+ # use the requested project id
47
+ @project_id = requested_id
48
+ @suite_mode = project_by_id(@project_id)['suite_mode']
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Itriagetestrail
4
+ module Sections
5
+ # TestRail Sections
6
+ def testrail_sections
7
+ case @suite_mode
8
+ when 2,3
9
+ @suite_id = testrail_suite_id(@suite_name)
10
+ @sections = @client.send_get("get_sections/#{@project_id}&suite_id=#{@suite_id}")
11
+ else
12
+ @sections = @client.send_get("get_sections/#{@project_id}")
13
+ end
14
+ end
15
+
16
+ def testrail_section_id(section_title)
17
+ res = -1
18
+ @sections.each do |section|
19
+ res = section['id'] if section['name'] == section_title
20
+ end
21
+ res
22
+ end
23
+
24
+ def add_testrail_section(section_title)
25
+ if @suite_name
26
+ body = {
27
+ name: section_title,
28
+ suite_id: testrail_suite_id(@suite_name)
29
+ }
30
+ else
31
+ body = {
32
+ name: section_title
33
+ }
34
+ end
35
+
36
+ res = @client.send_post("add_section/#{@project_id}", body)
37
+
38
+ testrail_section = res['id']
39
+
40
+ # re-establish sections
41
+ testrail_sections
42
+
43
+ testrail_section
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Itriagetestrail
4
+ module Suites
5
+ # TestRail Suites
6
+ def testrail_suites
7
+ case @suite_mode
8
+ when 2,3
9
+ @suites = @client.send_get("get_suites/#{@project_id}")
10
+ end
11
+ end
12
+
13
+ def testrail_suite_id(suite_name)
14
+ res = -1
15
+ @suites.each do |suite|
16
+ res = suite['id'] if suite['name'] == suite_name
17
+ end
18
+ res
19
+ end
20
+
21
+ def add_testrail_suite(suite_name)
22
+ body = { name: suite_name }
23
+ res = @client.send_post("add_suite/#{@project_id}", body)
24
+ testrail_suite = res['id']
25
+
26
+ #re-establish suites
27
+ testrail_suites
28
+
29
+ testrail_suite
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,64 @@
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
+ if test_case['custom_external_case_id'] == external_id
23
+ res = test_case['id']
24
+ end
25
+ end
26
+ res
27
+ end
28
+
29
+ def associate_result(external_id)
30
+ test_case_id = testrail_test_case_id(external_id)
31
+ # store the test case id with the local result
32
+ @results[:results].each do |result|
33
+ next unless result[:external_id] == external_id
34
+ @external_results[:results] << { case_id: test_case_id,
35
+ status_id: result['status_id'],
36
+ comment: result['comment'] }
37
+ end
38
+ end
39
+
40
+ # add the test case if it doesn't exist
41
+ def add_testrail_test_case(scenario_title, external_id, scenario_steps, section_id)
42
+ body = {
43
+ title: scenario_title,
44
+ custom_external_case_id: external_id,
45
+ custom_steps: scenario_steps,
46
+ type_id: 3
47
+ }
48
+
49
+ @client.send_post("add_case/#{section_id}", body)
50
+
51
+ # refresh test case ids
52
+ testrail_ids
53
+ end
54
+
55
+ def test_name
56
+ label = ''
57
+ label += "App Version:#{@app_version}" unless @app_version.nil? || @app_version == ''
58
+ label += " Jenkins Build:#{@jenkins_build}" unless @jenkins_build .nil? || @jenkins_build == ''
59
+ label.strip!
60
+ label = 'Regression' if label == ''
61
+ label + ' (' + @time_zone.now.strftime('%-I:%M %p') + ')'
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Itriagetestrail
4
+ module TestPlans
5
+
6
+ def configuration_group(name)
7
+ res = {}
8
+ @configurations.each do |config|
9
+ res = config if config['name'] == name
10
+ end
11
+ res
12
+ end
13
+
14
+ def config_id(name, value)
15
+ res = {}
16
+ configuration = configuration_group(name)
17
+
18
+ return nil if configuration.empty?
19
+ configuration['configs'].each do |config|
20
+ res = config['id'] if config['name'] == value
21
+ end
22
+ res
23
+ end
24
+
25
+
26
+ def configurations
27
+ @configurations = @client.send_get("get_configs/#{@project_id}")
28
+ end
29
+
30
+ def configuration_ids
31
+
32
+ @configuration_ids = []
33
+
34
+ # evaluate @testrail_comfig
35
+ @configuration_ids << config_id('Browser', @testrail_config[:config][:browser]) unless @testrail_config[:config][:browser].nil?
36
+ @configuration_ids << config_id('Browser Version', @testrail_config[:config][:browserVersion]) unless @testrail_config[:config][:browserVersion].nil?
37
+ @configuration_ids << config_id('Platform', @testrail_config[:config][:platform]) unless @testrail_config[:config][:platform].nil?
38
+ @configuration_ids << config_id('Android Version', @testrail_config[:config][:android]) unless @testrail_config[:config][:android].nil?
39
+ @configuration_ids << config_id('Android Device', @testrail_config[:config][:androidDevice]) unless @testrail_config[:config][:androidDevice].nil?
40
+ @configuration_ids << config_id('IOS Version', @testrail_config[:config][:ios]) unless @testrail_config[:config][:ios].nil?
41
+
42
+ # remove the nils
43
+ @configuration_ids.compact!
44
+
45
+ @configuration_ids
46
+ end
47
+
48
+ def add_testrail_plan
49
+
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
+
67
+ # todo: refactor redundant assignments of @suite_id
68
+ @suite_id = testrail_suite_id(@suite_name)
69
+ body = {
70
+ suite_id: @suite_id,
71
+ # todo: replace hardcoded name
72
+ name: 'replace this with config description',
73
+ include_all: true,
74
+ # todo: replace hardcoded config
75
+ config_ids: configuration_ids,
76
+ runs: [
77
+ {
78
+ include_all: true,
79
+ config_ids: configuration_ids
80
+ }
81
+ ]
82
+ }
83
+
84
+ @plan_entry = @client.send_post("add_plan_entry/#{@plan_id}", body)
85
+ # todo: replace debugging
86
+ puts @plan_entry.inspect
87
+ @run_id = @plan_entry['runs'][0]['id']
88
+ # todo: replace debugging
89
+ puts @run_id.inspect
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Itriagetestrail
4
+ module TestResults
5
+ def send_results_to_testrail
6
+ return unless @results[:results].size != 0
7
+ # copy what is in the results
8
+ @submitted[:results] << @results[:results]
9
+
10
+ begin
11
+ send = { results: @results[:results] }
12
+ res = @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
+ def update_test_suite(scenario_title, external_id, scenario_steps)
20
+ feature = external_id.split(';')[0].split('#')[0]
21
+
22
+ # if the testrail case does not exist, update cases
23
+ if testrail_test_case_id(external_id) == -1
24
+
25
+ section_id = testrail_section_id(feature)
26
+
27
+ # if the testrail section does not exist, update sections
28
+ section_id = add_testrail_section(feature) if section_id == -1
29
+
30
+ add_testrail_test_case(scenario_title, external_id, scenario_steps, section_id)
31
+ sleep 1
32
+ end
33
+ # store the case id associated with the external_id
34
+ associate_result(external_id)
35
+ end
36
+
37
+ def store_result(scenario_title, external_id, scenario_steps, status_id, comment)
38
+ update_test_suite scenario_title, external_id, scenario_steps
39
+
40
+ case_id = testrail_test_case_id(external_id)
41
+ @results[:results] << {
42
+ case_id: case_id,
43
+ scenario_title: scenario_title,
44
+ external_id: external_id,
45
+ scenario_steps: scenario_steps,
46
+ status_id: status_id,
47
+ comment: comment,
48
+ custom_branch_name: @testrail_config[:origin]
49
+ }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,54 @@
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
+
20
+ tests = @client.send_get("get_tests/#{run_id}&status_id=1,2,4,5") || []
21
+
22
+ cases = []
23
+
24
+ tests.each do |test|
25
+
26
+ cases << test["case_id"]
27
+
28
+ end
29
+ cases
30
+ end
31
+
32
+ # open a test run to submit test results
33
+ def add_testrail_run
34
+ body = {
35
+ name: test_name,
36
+ description: '',
37
+ include_all: true,
38
+ milestone_id: @milestone_id
39
+ }
40
+
41
+ unless @testrail_config[:include_all] || true
42
+ body[:include_all] = false
43
+ body[:case_ids] = @test_case_ids
44
+ end
45
+
46
+ case @suite_mode
47
+ when 2,3
48
+ body[:suite_id] = @suite_id
49
+ end
50
+ res = @client.send_post("add_run/#{@project_id}", body)
51
+ @run_id = res['id']
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Itriagetestrail
2
- VERSION = '1.0.2'
2
+ VERSION = '1.0.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itriagetestrail
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - a801069
@@ -93,6 +93,14 @@ files:
93
93
  - lib/itriagetestrail/framework_bindings/trminitest.rb
94
94
  - lib/itriagetestrail/pool.rb
95
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
96
104
  - lib/itriagetestrail/version.rb
97
105
  homepage:
98
106
  licenses: []