itriagetestrail 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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: []