cukerail 0.2.2 → 0.3.0

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: 982bc5b8489480f18b05ec0ba879f387b8ba32ce
4
- data.tar.gz: ec916a3a62fa3fcf304ccc8b952a3b50e7480ab1
3
+ metadata.gz: 4d5e94039d69eaeda30dcd54079c8a6a32e54405
4
+ data.tar.gz: 5de856db7882e048d153b3363d4416747e7c399d
5
5
  SHA512:
6
- metadata.gz: 2b00406acf979ee5add3bf25deda6979457ab5bf59e5efedbcfc62eed9cba303a6b4b6041768877630c28ba0adbb62268d5eca61401f21fa654067e80f6624c9
7
- data.tar.gz: 5048aa64d6f6544c199a39768375201bc5d97c12ddf09d78816cfc753d504524f6dde6eba5769659a8981ddf86e35bf0348ca0b58d3dae877f9786e1a06c9e24
6
+ metadata.gz: 8cee48c1ec2d56dc332dccd445fde07232d67a7a9c419fce54f4e241e2e2ee0cb42f58b07883cb966bfd211be9ddbdeb26c30c959fe402db1da9534f7df1a77d
7
+ data.tar.gz: 8981b323ad57e7d668c304f9433f45ecb474ebf9ef11e7eab0a19b933c61bfbf8b5c500899f6128feba6c9bdccfe53d7b19479ae39f8f4e0f7697cee3133b531
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rspec/core/rake_task'
2
2
  require 'bundler/gem_tasks'
3
-
3
+ import './lib/tasks/cukerail.rake'
4
4
  # Default directory to look in is `/specs`
5
5
  # # Run with `rake spec`
6
6
  RSpec::Core::RakeTask.new(:spec) do |task|
@@ -1,3 +1,3 @@
1
1
  module Cukerail
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,171 @@
1
+ require_relative "cukerail/version"
2
+ require_relative "cukerail/testrail"
3
+ require 'json' unless JSON
4
+ module Cukerail
5
+ class JsonSender
6
+ attr_reader :testrail_api_client,:results
7
+ def initialize(json_file)
8
+ if %w(BASE_URL USER PASSWORD).map{|e| ENV["TESTRAIL_#{e}"]}.any?{|e| e=='' || !e}
9
+ raise 'You need to setup Testrail environment parameters see https://bbcworldwide.atlassian.net/wiki/display/BAR/Installing+and+Running+Cukerail'
10
+ end
11
+ @testrail_api_client = TestRail::APIClient.new(ENV['TESTRAIL_BASE_URL'],ENV['TESTRAIL_USER'],ENV['TESTRAIL_PASSWORD'])
12
+ @results = JSON.parse(File.read(json_file)).select{|f| f['tags']}
13
+ end
14
+
15
+ def each_feature
16
+ results.each do |feature|
17
+ scenarios = feature['elements'].reject{|e| e['keyword']=='Background'}.select{|e| e['type'] == 'scenario'}
18
+ project_id,suite_id,sub_section_id,background_steps = extract_top_level_data(feature)
19
+ yield scenarios,project_id,suite_id,sub_section_id,background_steps
20
+ end
21
+ end
22
+
23
+
24
+ def get_id(scenario,background_steps,project_id,suite_id,sub_section_id)
25
+ title = get_name(scenario)
26
+ found_case = testrail_api_client.send_get("get_cases/#{project_id}&suite_id=#{suite_id}").select{|c| c['title'] == title}.first
27
+ if found_case
28
+ result= found_case['id']
29
+ else
30
+ result = create_new_case(scenario,background_steps,project_id,suite_id,sub_section_id)['id']
31
+ end
32
+ return result
33
+ end
34
+
35
+ def extract_top_level_data(feature)
36
+ project_id = feature['tags'].select{|j| j['name']=~/project_\d+/}.map{|j| /project_(\d+)/.match(j['name'])[1].to_i}.first
37
+ suite_id = feature['tags'].select{|j| j['name']=~/suite_\d+/}.map{|j| /suite_(\d+)/.match(j['name'])[1].to_i}.first
38
+ sub_section_id = feature['tags'].select{|j| j['name']=~/sub_section_\d+/}.map{|j| /sub_section_(\d+)/.match(j['name'])[1].to_i}.first
39
+ background=feature['elements'].select{|e| e['keyword']=='Background'}.first
40
+ background_steps = background['steps'].map{|s| s['keyword']+s['name']}.join("\n")
41
+ return project_id,suite_id,sub_section_id,background_steps
42
+ end
43
+
44
+ def get_name(scenario)
45
+ base_name = scenario['name']
46
+ outline_number_str = scenario['id'].split(';').select{|e| e =~/^\d+$/}.first
47
+ if outline_number_str
48
+ outline_number = (outline_number_str.to_i) -1
49
+ end
50
+ tags= [scenario['tags']].flatten.compact
51
+ requirement = tags.select{|t| t['name'] =~/@req/}.map{|t| /@req_(\w+)/.match(t['name'])[1]}.first unless tags.empty?
52
+ [requirement, base_name, outline_number].join(' ').strip
53
+ end
54
+
55
+ def create_new_case(scenario,background_steps,project_id,suite_id,sub_section_id)
56
+ data = prepare_data(scenario,background_steps)
57
+ testrail_api_client.send_post("add_case/#{sub_section_id || suite_id}", data)
58
+ end
59
+
60
+ def send_steps(scenario,background_steps,testcase_id)
61
+ data = prepare_data(scenario,background_steps)
62
+ testrail_api_client.send_post("update_case/#{testcase_id}",data)
63
+ end
64
+
65
+ def prepare_data(scenario,background_steps)
66
+ steps = background_steps + "\n" + scenario['steps'].map{|s| s['keyword']+s['name']}.join("\n")
67
+ is_manual = scenario['tags'].any?{|tag| tag['name'] =~/manual/} if scenario['tags']
68
+ data = {'title'=>get_name(scenario),
69
+ 'type_id'=>(is_manual ? 7 : 1 ),
70
+ 'custom_steps'=>steps,
71
+ 'refs'=>defects(scenario)
72
+ }
73
+ end
74
+
75
+ def defects(scenario)
76
+ if scenario['tags']
77
+ scenario['tags'].select{|t| t['name'] =~/@jira_/}.map{|t| /jira_(\w+-\w+)/.match(t['name'])}.join(' ')
78
+ end
79
+ end
80
+
81
+ def send_result(scenario,id,testrun)
82
+ error_line = scenario['steps'].select{|s| s['result']['status'] != 'passed'}.first
83
+ if error_line
84
+ puts error_line['result']
85
+ testrail_status = case error_line['result']['status']
86
+ when 'failed'
87
+ {id:5,comment: 'failed'}
88
+ when 'undefined'
89
+ {id:7,comment: 'undefined step'}
90
+ when 'pending'
91
+ {id:6,comment: 'pending step'}
92
+ when 'skipped'
93
+ {id:5,comment: 'failed in before hook'}
94
+ end
95
+ error_result = error_line['error_message']
96
+ failure_message = <<-FAILURE
97
+ Error message: #{testrail_status[:comment]} #{error_result}
98
+ Step: #{error_line['keyword']} #{error_line['name']}
99
+ Location: #{error_line['match']['location']}
100
+ FAILURE
101
+ else
102
+ testrail_status = {id:1,comment: 'passed'}
103
+ failure_message = nil
104
+ end
105
+ report_on_result = {status_id:testrail_status[:id],comment:failure_message,defects:defects(scenario)}
106
+ begin
107
+ testrail_api_client.send_post("add_result_for_case/#{testrun}/#{id}",report_on_result)
108
+ rescue => e
109
+ if e.message =~ /No \(active\) test found for the run\/case combination/
110
+ add_case_to_test_run(id,testrun)
111
+ retry
112
+ else
113
+ puts "#{e.message} testrun=#{testrun} test case id=#{id}"
114
+ end
115
+ end
116
+ end
117
+
118
+ def get_run(run_id)
119
+ testrail_api_client.send_get("get_run/#{run_id}")
120
+ end
121
+
122
+ def get_tests_in_a_run(run_id)
123
+ testrail_api_client.send_get("get_tests/#{run_id}")
124
+ end
125
+
126
+ def update_run(testrun,case_ids)
127
+ begin
128
+ testrail_api_client.send_post("update_run/#{testrun}",case_ids)
129
+ rescue => e
130
+ puts "#{e.message} testrun=#{testrun} test case ids=#{case_ids}"
131
+ end
132
+ end
133
+
134
+ def remove_case_from_test_run(testcase,testrun)
135
+ testcase_id = get_id(testcase)
136
+ run = get_run(testrun)
137
+ unless run['include_all']
138
+ case_ids = get_tests_in_a_run(testrun).map{|h| h['case_id']} - [testcase_id]
139
+ update_run(testrun,{'case_ids'=>case_ids})
140
+ end
141
+ end
142
+
143
+ def add_case_to_test_run(testcase_id,testrun)
144
+ run = get_run(testrun)
145
+ unless run['include_all']
146
+ case_ids = get_tests_in_a_run(testrun).map{|h| h['case_id']} + [testcase_id]
147
+ update_run(testrun,{'case_ids'=>case_ids})
148
+ end
149
+ end
150
+
151
+ def remove_all_except_these_cases_from_testrun(testcases,testrun)
152
+ run = get_run(testrun)
153
+ unless run['include_all']
154
+ case_ids = get_tests_in_a_run(testrun).map{|h| h['case_id']} & testcases
155
+ update_run(testrun,{'case_ids'=>case_ids})
156
+ end
157
+ end
158
+
159
+ def remove_all_except_these_cases_from_suite(testcases,project_id,suite_id)
160
+ puts '=== testcases === '
161
+ puts testcases
162
+ existing_cases = testrail_api_client.send_get("get_cases/#{project_id}&suite_id=#{suite_id}").map{|m| m['id']}
163
+ puts '===== existing_cases === '
164
+ puts existing_cases
165
+ (existing_cases - testcases).each do |case_to_remove|
166
+ puts "case_to_remove #{case_to_remove}"
167
+ testrail_api_client.send_post("delete_case/#{case_to_remove}",nil)
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,71 @@
1
+ require_relative '../json_sender'
2
+ desc 'load a json results file into a test suite'
3
+ task :load_to_suite do
4
+ raise 'You must have JSON=filename on the command line' unless ENV['JSON']
5
+ json_sender =Cukerail::JsonSender.new(ENV['JSON'])
6
+ features = json_sender.results
7
+ #only work with feature files that have tags set up
8
+ features.select{|f| f['tags']}.each do | feature |
9
+ # project_id = feature['tags'].select{|j| j['name']=~/project_\d+/}.map{|j| /project_(\d+)/.match(j['name'])[1].to_i}.first
10
+ # suite_id = feature['tags'].select{|j| j['name']=~/suite_\d+/}.map{|j| /suite_(\d+)/.match(j['name'])[1].to_i}.first
11
+ # sub_section_id = feature['tags'].select{|j| j['name']=~/sub_section_\d+/}.map{|j| /sub_section_(\d+)/.match(j['name'])[1].to_i}.first
12
+ # background=feature['elements'].select{|e| e['keyword']=='Background'}.first
13
+ # background_steps = background['steps'].map{|s| s['keyword']+s['name']}.join("\n")
14
+ project_id,suite_id,sub_section_id,background_steps = json_sender.extract_top_level_data(feature)
15
+ feature['elements'].reject{|e| e['keyword']=='Background'}.select{|e| e['type'] == 'scenario'}.each do | scenario |
16
+ testcase_id = json_sender.get_id(scenario,background_steps,project_id,suite_id,sub_section_id) if scenario['type'] == 'scenario'
17
+ puts "testcase_id = #{testcase_id}"
18
+ json_sender.send_steps(scenario,background_steps,testcase_id)
19
+ end
20
+ end
21
+ end
22
+
23
+ desc 'load a json results file into a test run'
24
+ task :load_to_test_run do
25
+ raise 'You must have TESTRUN=testrun_number on the command line' unless ENV['TESTRUN']
26
+ json_sender =Cukerail::JsonSender.new(ENV['JSON'])
27
+ #only work with feature files that have tags set up
28
+ json_sender.each_feature do | scenarios,project_id,suite_id,sub_section_id,background_steps |
29
+ scenarios.each do | scenario |
30
+ testcase_id = json_sender.get_id(scenario,background_steps,project_id,suite_id,sub_section_id)
31
+ puts "scenario_id #{scenario['id']} testcase_id = #{testcase_id}"
32
+ json_sender.send_steps(scenario,background_steps,testcase_id)
33
+ json_sender.send_result(scenario,testcase_id,ENV['TESTRUN'])
34
+ end
35
+ end
36
+ end
37
+
38
+ desc "remove cases from a test run that are aren't in the json results"
39
+ task :remove_from_test_run do
40
+ raise 'You must have TESTRUN=testrun_number on the command line' unless ENV['TESTRUN']
41
+ raise 'You must have JSON=filename on the command line' unless ENV['JSON']
42
+ json_sender =Cukerail::JsonSender.new(ENV['JSON'])
43
+ testcase_ids = []
44
+ json_sender.each_feature do | scenarios,project_id,suite_id,sub_section_id,background_steps |
45
+ scenarios.each do | scenario |
46
+ testcase_ids << json_sender.get_id(scenario,background_steps,project_id,suite_id,sub_section_id)
47
+ end
48
+ end
49
+ json_sender.remove_all_except_these_cases_from_testrun(testcase_ids,ENV['TESTRUN'])
50
+ end
51
+
52
+ desc "match test run cases to json results file"
53
+ task match_to_test_run: [:remove_from_test_run,:load_to_test_run] do
54
+ end
55
+
56
+ desc "remove cases from a test suite that aren't in the json results"
57
+ task :remove_from_test_suite do
58
+ raise 'You must have JSON=filename on the command line' unless ENV['JSON']
59
+ json_sender =Cukerail::JsonSender.new(ENV['JSON'])
60
+ testcase_ids = []
61
+ ex_project_id = 0
62
+ ex_suite_id = 0
63
+ json_sender.each_feature do | scenarios,project_id,suite_id,sub_section_id,background_steps |
64
+ ex_project_id = project_id
65
+ ex_suite_id = suite_id
66
+ scenarios.each do | scenario |
67
+ testcase_ids << json_sender.get_id(scenario,background_steps,project_id,suite_id,sub_section_id)
68
+ end
69
+ end
70
+ json_sender.remove_all_except_these_cases_from_suite(testcase_ids,ex_project_id,ex_suite_id)
71
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cukerail
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Small
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-15 00:00:00.000000000 Z
11
+ date: 2015-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -98,6 +98,8 @@ files:
98
98
  - lib/cukerail.rb
99
99
  - lib/cukerail/testrail.rb
100
100
  - lib/cukerail/version.rb
101
+ - lib/json_sender.rb
102
+ - lib/tasks/cukerail.rake
101
103
  - spec/cukerail_spec.rb
102
104
  - spec/spec_helper.rb
103
105
  homepage: ''