cukerail 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/cukerail/version.rb +1 -1
- data/lib/json_sender.rb +171 -0
- data/lib/tasks/cukerail.rake +71 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d5e94039d69eaeda30dcd54079c8a6a32e54405
|
4
|
+
data.tar.gz: 5de856db7882e048d153b3363d4416747e7c399d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cee48c1ec2d56dc332dccd445fde07232d67a7a9c419fce54f4e241e2e2ee0cb42f58b07883cb966bfd211be9ddbdeb26c30c959fe402db1da9534f7df1a77d
|
7
|
+
data.tar.gz: 8981b323ad57e7d668c304f9433f45ecb474ebf9ef11e7eab0a19b933c61bfbf8b5c500899f6128feba6c9bdccfe53d7b19479ae39f8f4e0f7697cee3133b531
|
data/Rakefile
CHANGED
data/lib/cukerail/version.rb
CHANGED
data/lib/json_sender.rb
ADDED
@@ -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.
|
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-
|
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: ''
|