res 1.1.0.pre2 → 1.2.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 +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:
|