res 1.1.0.pre2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -3
- data/bin/res +156 -0
- data/lib/res.rb +25 -16
- data/lib/res/formatters/rspec.rb +5 -4
- data/lib/res/formatters/ruby_cucumber.rb +26 -31
- data/lib/res/formatters/{ruby_cucumber_legacy.rb → ruby_cucumber_2.rb} +34 -25
- data/lib/res/parsers/junitcasper.rb +98 -0
- data/lib/res/reporters/test_rail.rb +1 -1
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 092fab54cb28019323fb52c264ab4a328eca7887
|
4
|
+
data.tar.gz: 9fb52f6992949fdbce49c7a531a06227f3c168fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b29793fefaeb91e1bc3163aa9b5f96e05843de719d66dbfdacb66d3c08b9e2afa02aa84b581f8efdfafce50679d2ac526a6d300963f269c13845ad6f39108c9f
|
7
|
+
data.tar.gz: 362b6502e7036285599612faaa35f0fc3742fc907a7a3c95fdc5a7ddf96da923f3cd2dc98f6393f7320b18b49901e651ab1e9a61c9622a0910554ad01b7b45a3
|
data/README.md
CHANGED
@@ -37,7 +37,11 @@ Note: This cucumber formatter works for cucumber version < 2.0
|
|
37
37
|
|
38
38
|
## Junit
|
39
39
|
|
40
|
-
|
40
|
+
res.rb --junit '/path/to/xunit_result.xml'
|
41
|
+
Note: The Res output of the xunit parser is saved in the current directory
|
42
|
+
|
43
|
+
## Casper
|
44
|
+
res.rb --junitcasper '/path/to/xunit_result.xml'
|
41
45
|
Note: The Res output of the xunit parser is saved in the current directory
|
42
46
|
|
43
47
|
## Reporters
|
@@ -48,7 +52,7 @@ tool.
|
|
48
52
|
|
49
53
|
If you have a Res IR file, you can submit using a reporter:
|
50
54
|
|
51
|
-
|
55
|
+
res.rb --res '/path/to/file.res' --submit REPORTER [... options]
|
52
56
|
|
53
57
|
### Hive
|
54
58
|
|
@@ -63,7 +67,7 @@ Hive CI uses a Res reporter for result submission, the api arguments look like t
|
|
63
67
|
|
64
68
|
### TestRail
|
65
69
|
|
66
|
-
|
70
|
+
res.rb --res '/path/to/file.res' --submit testrail --config-file '/path/to/.test_rail.yaml'
|
67
71
|
|
68
72
|
Our TestRail reporter currently be used to sync a suite with TestRail, and
|
69
73
|
to submit test results against a test run. You will need to create a
|
@@ -79,6 +83,8 @@ Your config file should be called .test_rail.yaml, and should look like this:
|
|
79
83
|
suite: 'MySuite'
|
80
84
|
run_name: 'RunName' or run_id: '1234'
|
81
85
|
|
86
|
+
Note: Above parameters can also be set through environment as TESTRAIL_#{PARAMETER} instead of config file.
|
87
|
+
|
82
88
|
### Testmine
|
83
89
|
|
84
90
|
The Testmine reporter is very similar to the TestRail reporter, but doesn't
|
@@ -93,6 +99,8 @@ should be called .testmine.yaml, and should look like this:
|
|
93
99
|
component: 'Android acceptance'
|
94
100
|
suite: 'MySuiteName'
|
95
101
|
|
102
|
+
Note: Above parameters can also be set through environment as TESTMINE_#{PARAMETER} instead of config file.
|
103
|
+
|
96
104
|
## License
|
97
105
|
|
98
106
|
*Res* is available to everyone under the terms of the MIT open source licence. Take a look at the LICENSE file in the code.
|
data/bin/res
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'res/ir'
|
6
|
+
require 'res/reporters/testmine'
|
7
|
+
require 'res/reporters/test_rail'
|
8
|
+
require 'res/reporters/hive'
|
9
|
+
require 'res/parsers/junit'
|
10
|
+
require 'res/parsers/junitcasper'
|
11
|
+
require 'openssl'
|
12
|
+
|
13
|
+
class CLIParser
|
14
|
+
|
15
|
+
#
|
16
|
+
# Return a structure describing the options.
|
17
|
+
#
|
18
|
+
def self.parse(args)
|
19
|
+
|
20
|
+
# Default values
|
21
|
+
options = OpenStruct.new
|
22
|
+
|
23
|
+
opt_parser = OptionParser.new do |opts|
|
24
|
+
opts.banner = "Usage: res [options]"
|
25
|
+
|
26
|
+
opts.on("-r", "--res RES_FILE",
|
27
|
+
"res file to load") do |res|
|
28
|
+
options.res = res
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-s", "--submit REPORTER",
|
32
|
+
"Reporter to use to submit results") do |reporter|
|
33
|
+
options.reporter = reporter
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("--junit junit_xml",
|
37
|
+
"Parse junit xml to res type") do |junit|
|
38
|
+
options.junit = junit
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("--junitcasper junit_xml",
|
42
|
+
"Parse junit xml to res type") do |junitcasper|
|
43
|
+
options.junitcasper = junitcasper
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on("--cert CERT",
|
47
|
+
"Client certificate file") do |cert|
|
48
|
+
options.cert = cert
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on("--cacert CACERT",
|
52
|
+
"CA Certificate") do |cacert|
|
53
|
+
options.cacert = cacert
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on("--no-ssl-verification",
|
57
|
+
"Turn off ssl verification (don't do this)") do |no_ssl_verification|
|
58
|
+
options.ssl_verify_mode = OpenSSL::SSL::VERIFY_NONE
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on("--url URL",
|
62
|
+
"URL to submit results to") do |url|
|
63
|
+
options.url = url
|
64
|
+
end
|
65
|
+
|
66
|
+
opts.on("--job-id JOB_ID",
|
67
|
+
"JOB_ID to submit results against") do |job_id|
|
68
|
+
options.job_id = job_id
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on("--config-file CONFIG_FILE",
|
72
|
+
"Config file for the submitter") do |config_file|
|
73
|
+
options.config_file = config_file
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on("--version VERSION",
|
77
|
+
"VERSION of the world under test") do |version|
|
78
|
+
options.version = version
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on("--target TARGET",
|
82
|
+
"Target of execution (e.g. Chrome)") do |target|
|
83
|
+
options.target = target
|
84
|
+
end
|
85
|
+
|
86
|
+
opts.on_tail("-h", "--help", "Display help") do
|
87
|
+
puts opts
|
88
|
+
exit
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
opt_parser.parse!(args)
|
94
|
+
options
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
options = CLIParser.parse(ARGV)
|
99
|
+
|
100
|
+
if options.res
|
101
|
+
ir = Res::IR.load(options.res)
|
102
|
+
puts 'IR File loaded'
|
103
|
+
end
|
104
|
+
|
105
|
+
if options.junit
|
106
|
+
junit_output = Res::Parsers::Junit.new(options.junit)
|
107
|
+
ir = Res::IR.load(junit_output.io)
|
108
|
+
end
|
109
|
+
|
110
|
+
if options.junitcasper
|
111
|
+
junit_output = Res::Parsers::Junitcasper.new(options.junitcasper)
|
112
|
+
ir = Res::IR.load(junit_output.io)
|
113
|
+
end
|
114
|
+
|
115
|
+
raise "No results loaded" if !ir
|
116
|
+
|
117
|
+
if options.reporter
|
118
|
+
case options.reporter
|
119
|
+
when 'hive'
|
120
|
+
|
121
|
+
raise "Need to provide a hive job_id" if !options.job_id
|
122
|
+
|
123
|
+
reporter = Res::Reporters::Hive.new(
|
124
|
+
:url => options.url,
|
125
|
+
:cert => options.cert,
|
126
|
+
:cacert => options.cacert,
|
127
|
+
:ssl_verify_mode => options.ssl_verify_mode
|
128
|
+
)
|
129
|
+
|
130
|
+
reporter.submit_results( ir, :job_id => options.job_id )
|
131
|
+
when 'testmine'
|
132
|
+
|
133
|
+
reporter = Res::Reporters::Testmine.new(
|
134
|
+
:config_file => options.config_file,
|
135
|
+
:version => options.version,
|
136
|
+
:target => options.target,
|
137
|
+
:url => options.url
|
138
|
+
)
|
139
|
+
|
140
|
+
id = reporter.submit_results(ir)
|
141
|
+
puts "Reported to testmine: #{id}"
|
142
|
+
when 'testrail'
|
143
|
+
reporter = Res::Reporters::TestRail.new(
|
144
|
+
:config_file => options.config_file,
|
145
|
+
:target => options.target,
|
146
|
+
:url => options.url,
|
147
|
+
:ir => ir
|
148
|
+
)
|
149
|
+
|
150
|
+
output = reporter.submit_results(ir)
|
151
|
+
puts output
|
152
|
+
else
|
153
|
+
|
154
|
+
raise "#{options.reporter} not implemented"
|
155
|
+
end
|
156
|
+
end
|
data/lib/res.rb
CHANGED
@@ -3,27 +3,29 @@ require 'res/ir'
|
|
3
3
|
# Res API
|
4
4
|
module Res
|
5
5
|
|
6
|
+
@data = []
|
7
|
+
|
6
8
|
# Report Res IR to a test repository or similar
|
7
9
|
def self.submit_results(args)
|
8
10
|
reporter_class = Res.reporter_class(args[:reporter])
|
9
11
|
reporter = reporter_class.new( args )
|
10
|
-
|
12
|
+
|
11
13
|
ir = Res::IR.load(args[:ir])
|
12
|
-
|
14
|
+
|
13
15
|
reporter.submit_results( ir, args )
|
14
16
|
end
|
15
17
|
|
16
18
|
def self.reporter_class(type)
|
17
19
|
case type
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
20
|
+
when :test_rail
|
21
|
+
require 'res/reporters/test_rail'
|
22
|
+
Res::Reporters::TestRail
|
23
|
+
when :hive
|
24
|
+
require 'res/reporters/hive'
|
25
|
+
Res::Reporters::Hive
|
26
|
+
when :testmine
|
27
|
+
require 'res/reporters/testmine'
|
28
|
+
Res::Reporters::Testmine
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
@@ -34,12 +36,19 @@ module Res
|
|
34
36
|
|
35
37
|
def self.parser_class(type)
|
36
38
|
case type
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
when :junit
|
40
|
+
require 'res/parsers/junit'
|
41
|
+
Res::Parsers::Junit
|
42
|
+
when :junitcasper
|
43
|
+
require 'res/parsers/junitcasper'
|
44
|
+
Res::Parsers::Junitcasper
|
45
|
+
else
|
46
|
+
raise "#{type} parser not Implemented"
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
50
|
+
def self.perf_data
|
51
|
+
@data
|
52
|
+
end
|
53
|
+
|
45
54
|
end
|
data/lib/res/formatters/rspec.rb
CHANGED
@@ -5,15 +5,16 @@ module Res
|
|
5
5
|
module Formatters
|
6
6
|
class Rspec
|
7
7
|
|
8
|
-
attr_accessor :output, :result
|
8
|
+
attr_accessor :output, :result, :start_time
|
9
9
|
RSpec::Core::Formatters.register self, :start,
|
10
10
|
:example_group_started, :example_passed, :example_failed, :example_pending,
|
11
11
|
:stop, :start_dump
|
12
12
|
|
13
13
|
|
14
14
|
def initialize output
|
15
|
-
|
16
|
-
|
15
|
+
@io = output
|
16
|
+
@result = Array.new
|
17
|
+
@start_time = Time.now
|
17
18
|
end
|
18
19
|
|
19
20
|
# Called when rspec starts execution
|
@@ -120,7 +121,7 @@ module Res
|
|
120
121
|
# Called At the end of the suite
|
121
122
|
def stop(stop_notification)
|
122
123
|
@ir = ::Res::IR.new( :type => 'Rspec',
|
123
|
-
:started =>
|
124
|
+
:started => @start_time,
|
124
125
|
:results => result,
|
125
126
|
:finished => Time.now(),
|
126
127
|
)
|
@@ -1,19 +1,22 @@
|
|
1
1
|
# Formatter for ruby cucumber
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
|
+
require 'res'
|
4
5
|
require 'res/ir'
|
5
6
|
require 'cucumber/formatter/io'
|
6
|
-
require 'cucumber/formatter/summary'
|
7
7
|
|
8
8
|
module Res
|
9
9
|
module Formatters
|
10
10
|
class RubyCucumber
|
11
11
|
include FileUtils
|
12
12
|
include ::Cucumber::Formatter::Io
|
13
|
-
|
13
|
+
|
14
14
|
def initialize(runtime, path_or_io, options)
|
15
|
+
cucumber_version = %x(cucumber --version)
|
16
|
+
@cucumber_version = cucumber_version.gsub("\n","")
|
17
|
+
|
15
18
|
@runtime = runtime
|
16
|
-
@io = ensure_io(path_or_io)
|
19
|
+
@io = ensure_io(path_or_io, "reporter")
|
17
20
|
@options = options
|
18
21
|
@exceptions = []
|
19
22
|
@indent = 0
|
@@ -42,7 +45,13 @@ module Res
|
|
42
45
|
@_context = {}
|
43
46
|
@_feature[:started] = Time.now()
|
44
47
|
begin
|
45
|
-
|
48
|
+
if @cucumber_version.to_f < 1.3.to_f
|
49
|
+
uri = feature.file.to_s
|
50
|
+
else
|
51
|
+
uri = feature.location.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
hash = RubyCucumber.split_uri( uri )
|
46
55
|
@_feature[:file] = hash[:file]
|
47
56
|
@_feature[:line] = hash[:line]
|
48
57
|
@_feature[:urn] = hash[:urn]
|
@@ -90,7 +99,12 @@ module Res
|
|
90
99
|
@_context = {}
|
91
100
|
@_feature_element[:started] = Time.now
|
92
101
|
begin
|
93
|
-
|
102
|
+
if @cucumber_version.to_f < 1.3.to_f
|
103
|
+
uri = feature_element.file_colon_line
|
104
|
+
else
|
105
|
+
uri = feature_element.location.to_s
|
106
|
+
end
|
107
|
+
hash = RubyCucumber.split_uri( uri )
|
94
108
|
@_feature_element[:file] = hash[:file]
|
95
109
|
@_feature_element[:line] = hash[:line]
|
96
110
|
@_feature_element[:urn] = hash[:urn]
|
@@ -109,29 +123,14 @@ module Res
|
|
109
123
|
def after_feature_element(feature_element)
|
110
124
|
@_context = {}
|
111
125
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
fail = @runtime.scenarios(:failed).select do |s|
|
116
|
-
[scenario_class, example_table_class].include?(s.class)
|
117
|
-
end.map do |s|
|
118
|
-
if s.location == feature_element.location
|
119
|
-
s
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
if fail.compact.empty? and feature_element.respond_to? :status
|
124
|
-
@_feature_element[:status] = feature_element.status if feature_element.status.to_s != "skipped"
|
125
|
-
else
|
126
|
-
fail = fail.compact
|
127
|
-
@_feature_element[:status] = fail[0].status
|
126
|
+
if feature_element.respond_to? :status
|
127
|
+
@_feature_element[:status] = feature_element.status
|
128
128
|
end
|
129
|
-
|
130
129
|
@_feature_element[:finished] = Time.now
|
130
|
+
@_feature_element[:values] = Res.perf_data.pop if !Res.perf_data.empty?
|
131
131
|
end
|
132
132
|
|
133
133
|
def before_background(background)
|
134
|
-
#@_context[:background] = background
|
135
134
|
end
|
136
135
|
|
137
136
|
def after_background(background)
|
@@ -143,7 +142,6 @@ module Res
|
|
143
142
|
def examples_name(keyword, name)
|
144
143
|
end
|
145
144
|
|
146
|
-
|
147
145
|
def scenario_name(keyword, name, file_colon_line, source_indent)
|
148
146
|
@_context[:type] = "Cucumber::" + keyword.gsub(/\s+/, "")
|
149
147
|
@_context[:name] = name || ''
|
@@ -163,6 +161,7 @@ module Res
|
|
163
161
|
@_context = @_step
|
164
162
|
end
|
165
163
|
|
164
|
+
# Argument list changed after cucumber 1.4, hence the *args
|
166
165
|
def step_name(keyword, step_match, status, source_indent, background, *args)
|
167
166
|
|
168
167
|
file_colon_line = args[0] if args[0]
|
@@ -171,11 +170,10 @@ module Res
|
|
171
170
|
name = keyword + step_match.format_args(lambda{|param| %{#{param}}})
|
172
171
|
@_step[:name] = name
|
173
172
|
@_step[:status] = status
|
174
|
-
#@_step[:background] = background
|
175
173
|
@_step[:type] = "Cucumber::Step"
|
176
174
|
|
177
175
|
end
|
178
|
-
|
176
|
+
|
179
177
|
def exception(exception, status)
|
180
178
|
@_context[:message] = exception.to_s
|
181
179
|
end
|
@@ -210,17 +208,14 @@ module Res
|
|
210
208
|
end
|
211
209
|
|
212
210
|
def after_table_row(table_row)
|
213
|
-
|
214
|
-
|
211
|
+
if table_row.class == Cucumber::Ast::OutlineTable::ExampleRow
|
215
212
|
@_current_table_row[:name] = table_row.name
|
216
213
|
if table_row.exception
|
217
214
|
@_current_table_row[:message] = table_row.exception.to_s
|
218
215
|
end
|
219
|
-
|
220
|
-
if table_row.status and table_row.status != "skipped" and table_row.status != nil
|
216
|
+
if table_row.scenario_outline
|
221
217
|
@_current_table_row[:status] = table_row.status
|
222
218
|
end
|
223
|
-
|
224
219
|
@_current_table_row[:line] = table_row.line
|
225
220
|
@_current_table_row[:urn] = @_feature_element[:file] + ":" + table_row.line.to_s
|
226
221
|
@_table << @_current_table_row
|
@@ -1,21 +1,20 @@
|
|
1
1
|
# Formatter for ruby cucumber
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
|
+
require 'res'
|
4
5
|
require 'res/ir'
|
5
6
|
require 'cucumber/formatter/io'
|
7
|
+
require 'cucumber/formatter/summary'
|
6
8
|
|
7
9
|
module Res
|
8
10
|
module Formatters
|
9
|
-
class
|
11
|
+
class RubyCucumber2
|
10
12
|
include FileUtils
|
11
13
|
include ::Cucumber::Formatter::Io
|
12
|
-
|
14
|
+
|
13
15
|
def initialize(runtime, path_or_io, options)
|
14
|
-
cucumber_version = %x(cucumber --version)
|
15
|
-
@cucumber_version = cucumber_version.gsub("\n","")
|
16
|
-
|
17
16
|
@runtime = runtime
|
18
|
-
@io = ensure_io(path_or_io
|
17
|
+
@io = ensure_io(path_or_io)
|
19
18
|
@options = options
|
20
19
|
@exceptions = []
|
21
20
|
@indent = 0
|
@@ -44,13 +43,7 @@ module Res
|
|
44
43
|
@_context = {}
|
45
44
|
@_feature[:started] = Time.now()
|
46
45
|
begin
|
47
|
-
|
48
|
-
uri = feature.file.to_s
|
49
|
-
else
|
50
|
-
uri = feature.location.to_s
|
51
|
-
end
|
52
|
-
|
53
|
-
hash = RubyCucumberLegacy.split_uri( uri )
|
46
|
+
hash = RubyCucumber2.split_uri( feature.location.to_s )
|
54
47
|
@_feature[:file] = hash[:file]
|
55
48
|
@_feature[:line] = hash[:line]
|
56
49
|
@_feature[:urn] = hash[:urn]
|
@@ -98,12 +91,7 @@ module Res
|
|
98
91
|
@_context = {}
|
99
92
|
@_feature_element[:started] = Time.now
|
100
93
|
begin
|
101
|
-
|
102
|
-
uri = feature_element.file_colon_line
|
103
|
-
else
|
104
|
-
uri = feature_element.location.to_s
|
105
|
-
end
|
106
|
-
hash = RubyCucumberLegacy.split_uri( uri )
|
94
|
+
hash = RubyCucumber2.split_uri( feature_element.location.to_s )
|
107
95
|
@_feature_element[:file] = hash[:file]
|
108
96
|
@_feature_element[:line] = hash[:line]
|
109
97
|
@_feature_element[:urn] = hash[:urn]
|
@@ -122,13 +110,30 @@ module Res
|
|
122
110
|
def after_feature_element(feature_element)
|
123
111
|
@_context = {}
|
124
112
|
|
125
|
-
|
126
|
-
|
113
|
+
scenario_class = Cucumber::Formatter::LegacyApi::Ast::Scenario
|
114
|
+
example_table_class = Cucumber::Core::Ast::Location
|
115
|
+
|
116
|
+
fail = @runtime.scenarios(:failed).select do |s|
|
117
|
+
[scenario_class, example_table_class].include?(s.class)
|
118
|
+
end.map do |s|
|
119
|
+
if s.location == feature_element.location
|
120
|
+
s
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
if fail.compact.empty? and feature_element.respond_to? :status
|
125
|
+
@_feature_element[:status] = feature_element.status if feature_element.status.to_s != "skipped"
|
126
|
+
else
|
127
|
+
fail = fail.compact
|
128
|
+
@_feature_element[:status] = fail[0].status
|
127
129
|
end
|
130
|
+
|
128
131
|
@_feature_element[:finished] = Time.now
|
132
|
+
@_feature_element[:values] = Res.perf_data.pop if !Res.perf_data.empty?
|
129
133
|
end
|
130
134
|
|
131
135
|
def before_background(background)
|
136
|
+
#@_context[:background] = background
|
132
137
|
end
|
133
138
|
|
134
139
|
def after_background(background)
|
@@ -140,6 +145,7 @@ module Res
|
|
140
145
|
def examples_name(keyword, name)
|
141
146
|
end
|
142
147
|
|
148
|
+
|
143
149
|
def scenario_name(keyword, name, file_colon_line, source_indent)
|
144
150
|
@_context[:type] = "Cucumber::" + keyword.gsub(/\s+/, "")
|
145
151
|
@_context[:name] = name || ''
|
@@ -159,7 +165,6 @@ module Res
|
|
159
165
|
@_context = @_step
|
160
166
|
end
|
161
167
|
|
162
|
-
# Argument list changed after cucumber 1.4, hence the *args
|
163
168
|
def step_name(keyword, step_match, status, source_indent, background, *args)
|
164
169
|
|
165
170
|
file_colon_line = args[0] if args[0]
|
@@ -168,10 +173,11 @@ module Res
|
|
168
173
|
name = keyword + step_match.format_args(lambda{|param| %{#{param}}})
|
169
174
|
@_step[:name] = name
|
170
175
|
@_step[:status] = status
|
176
|
+
#@_step[:background] = background
|
171
177
|
@_step[:type] = "Cucumber::Step"
|
172
178
|
|
173
179
|
end
|
174
|
-
|
180
|
+
|
175
181
|
def exception(exception, status)
|
176
182
|
@_context[:message] = exception.to_s
|
177
183
|
end
|
@@ -206,14 +212,17 @@ module Res
|
|
206
212
|
end
|
207
213
|
|
208
214
|
def after_table_row(table_row)
|
209
|
-
|
215
|
+
if table_row.class == Cucumber::Formatter::LegacyApi::Ast::ExampleTableRow
|
216
|
+
|
210
217
|
@_current_table_row[:name] = table_row.name
|
211
218
|
if table_row.exception
|
212
219
|
@_current_table_row[:message] = table_row.exception.to_s
|
213
220
|
end
|
214
|
-
|
221
|
+
|
222
|
+
if table_row.status and table_row.status != "skipped" and table_row.status != nil
|
215
223
|
@_current_table_row[:status] = table_row.status
|
216
224
|
end
|
225
|
+
|
217
226
|
@_current_table_row[:line] = table_row.line
|
218
227
|
@_current_table_row[:urn] = @_feature_element[:file] + ":" + table_row.line.to_s
|
219
228
|
@_table << @_current_table_row
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'ox'
|
2
|
+
require 'json'
|
3
|
+
require 'res/ir'
|
4
|
+
|
5
|
+
module Res
|
6
|
+
module Parsers
|
7
|
+
class Junitcasper
|
8
|
+
attr_accessor :io
|
9
|
+
|
10
|
+
def initialize(junit_xml)
|
11
|
+
file = File.open(junit_xml, "rb")
|
12
|
+
begin
|
13
|
+
junit = Ox.parse(file.read)
|
14
|
+
rescue Ox::ParseError => e
|
15
|
+
raise "Invalid xunit XML format. Error: #{e}"
|
16
|
+
end
|
17
|
+
file.close
|
18
|
+
@test_suites = create_test_suites(packagenames(junit))
|
19
|
+
junit.nodes.collect do |test_suites|
|
20
|
+
create_multiple_test_suite(test_suites)
|
21
|
+
end
|
22
|
+
ir = ::Res::IR.new(:type => 'Casper',
|
23
|
+
:started => "",
|
24
|
+
:finished => Time.now(),
|
25
|
+
:results => @test_suites
|
26
|
+
)
|
27
|
+
|
28
|
+
@io = File.open("./junitcasper.res", "w")
|
29
|
+
@io.puts ir.json
|
30
|
+
@io.close
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_case(suite)
|
34
|
+
testcases = Hash.new
|
35
|
+
testcases = suite.nodes.collect do |node|
|
36
|
+
if node.value == "testcase"
|
37
|
+
testcase = Hash.new
|
38
|
+
testcase[:type] = "Casper::" + node.value
|
39
|
+
testcase[:name] = truncateName(node.attributes[:name])
|
40
|
+
testcase["duration"] = node.attributes[:time]
|
41
|
+
testcase["status"] = "passed"
|
42
|
+
if node.nodes[0] != nil
|
43
|
+
testcase["status"] = "failed" if node.nodes[0].value == "failure" or node.nodes[0].value == "error"
|
44
|
+
testcase["status"] = "notrun" if node.nodes[0].value == "skipped"
|
45
|
+
end
|
46
|
+
testcase
|
47
|
+
end
|
48
|
+
end
|
49
|
+
testcases.compact
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_multiple_test_suite(suites)
|
53
|
+
i = 0
|
54
|
+
suites.nodes.each_with_index do |suite, index|
|
55
|
+
test_suite = Hash.new
|
56
|
+
test_suite[:type] = "Casper::testsuite"
|
57
|
+
test_suite[:name] = suite.attributes[:name]
|
58
|
+
test_suite[:children] = Array.new
|
59
|
+
test_suite[:children] = test_case(suite)
|
60
|
+
i = @test_suites.index { |test_suites|
|
61
|
+
test_suites[:name] == suite.attributes[:package]
|
62
|
+
}
|
63
|
+
@test_suites[i][:children].push(test_suite)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_test_suites (pkgnames)
|
68
|
+
test_suites= Array.new
|
69
|
+
pkgnames.each_with_index do |pkgname, index|
|
70
|
+
test_suites[index] = Hash.new
|
71
|
+
test_suites[index][:type]= "Casper::testsuites"
|
72
|
+
test_suites[index][:name]= pkgname
|
73
|
+
test_suites[index][:children] = Array.new
|
74
|
+
end
|
75
|
+
test_suites
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def packagenames (junit)
|
80
|
+
packagename=junit.nodes[0].nodes.collect do |node|
|
81
|
+
node.attributes[:package]
|
82
|
+
end
|
83
|
+
packagename.uniq
|
84
|
+
end
|
85
|
+
|
86
|
+
def truncateName(inputText)
|
87
|
+
if inputText.to_s.empty? ==false
|
88
|
+
return inputText[0..253]#.gsub(/\s+$/, '')
|
89
|
+
else
|
90
|
+
return inputText
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end # class JUnit
|
96
|
+
end # class Parsers
|
97
|
+
end # class Res
|
98
|
+
|
@@ -10,7 +10,7 @@ module Res
|
|
10
10
|
attr_accessor :ir, :case_status, :config, :project, :suite
|
11
11
|
def initialize(args)
|
12
12
|
@url = args[:url]
|
13
|
-
@config = Res::Config.new([:user, :password, :namespace, :project, :suite], :optional => [:run_id, :run_name], :pre_env => '
|
13
|
+
@config = Res::Config.new([:user, :password, :namespace, :project, :suite], :optional => [:run_id, :run_name], :pre_env => 'testrail_')
|
14
14
|
config.process(args)
|
15
15
|
|
16
16
|
@case_status = {}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: res
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BBC
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-02-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -86,19 +86,22 @@ description: Formatters, parsers, and submitters for test results
|
|
86
86
|
email:
|
87
87
|
- david.buckhurst@bbc.co.uk
|
88
88
|
- asim.khan.ext@bbc.co.uk
|
89
|
-
executables:
|
89
|
+
executables:
|
90
|
+
- res
|
90
91
|
extensions: []
|
91
92
|
extra_rdoc_files: []
|
92
93
|
files:
|
93
94
|
- README.md
|
95
|
+
- bin/res
|
94
96
|
- lib/res.rb
|
95
97
|
- lib/res/config.rb
|
96
98
|
- lib/res/formatters/rspec.rb
|
97
99
|
- lib/res/formatters/ruby_cucumber.rb
|
98
|
-
- lib/res/formatters/
|
100
|
+
- lib/res/formatters/ruby_cucumber_2.rb
|
99
101
|
- lib/res/ir.rb
|
100
102
|
- lib/res/mappings.rb
|
101
103
|
- lib/res/parsers/junit.rb
|
104
|
+
- lib/res/parsers/junitcasper.rb
|
102
105
|
- lib/res/reporters/hive.rb
|
103
106
|
- lib/res/reporters/test_rail.rb
|
104
107
|
- lib/res/reporters/testmine.rb
|
@@ -117,9 +120,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
117
120
|
version: '0'
|
118
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
122
|
requirements:
|
120
|
-
- - "
|
123
|
+
- - ">="
|
121
124
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
125
|
+
version: '0'
|
123
126
|
requirements: []
|
124
127
|
rubyforge_project:
|
125
128
|
rubygems_version: 2.4.8
|
@@ -127,3 +130,4 @@ signing_key:
|
|
127
130
|
specification_version: 4
|
128
131
|
summary: Test Result report libraries
|
129
132
|
test_files: []
|
133
|
+
has_rdoc:
|