cucumber-repeat 0.0.2 → 0.0.3
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 +52 -2
- data/lib/cucumber-repeat.rb +31 -35
- data/lib/formatter.rb +178 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58234b4d3481996c50baa2c9dc684ac691d5c7ed
|
4
|
+
data.tar.gz: cd30d812654b6c7d96c4991485558399531e1a1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27e230ae3bb33b96e5e5090f118755f36368f51546d18f259833963ae025b96db20d39688f1d14eb7b20e05cd392733191da72a3b07a7c2a3a5c77f1e6e6cdbe
|
7
|
+
data.tar.gz: 0adb398e6e0faf3674574b3c8dc5e8f7920d1a3a617f3b633d0974b9c760af67bf541e8da30c9fe96360ed12176661c7a2e34627ab73a4ca6231cf336d6ca430
|
data/README.md
CHANGED
@@ -1,2 +1,52 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
Cucumber Repeater
|
2
|
+
===============
|
3
|
+
|
4
|
+
This will repeat a scenario which fails up to 2 additional times. It will repeat the whole scenario again.
|
5
|
+
|
6
|
+
How you use?
|
7
|
+
============
|
8
|
+
|
9
|
+
Either tag the scenario of feature with the @repeat tag
|
10
|
+
|
11
|
+
Scenario e.g:
|
12
|
+
|
13
|
+
```
|
14
|
+
@repeat
|
15
|
+
Scenario: Works first time
|
16
|
+
Given I do something
|
17
|
+
Then I expect it this to pass on the second go
|
18
|
+
```
|
19
|
+
|
20
|
+
Feature e.g:
|
21
|
+
|
22
|
+
```
|
23
|
+
@repeat
|
24
|
+
Feature: Testing Cucumber Repeat
|
25
|
+
|
26
|
+
Scenario: Works first time
|
27
|
+
Given I do something
|
28
|
+
Then I expect it this to pass on the second go
|
29
|
+
```
|
30
|
+
|
31
|
+
Outputting results
|
32
|
+
============
|
33
|
+
This will display results in the pretty format, additionally it is also able to display the results as Junit.
|
34
|
+
|
35
|
+
To output as Pretty do:
|
36
|
+
|
37
|
+
```
|
38
|
+
cucumber --format Cucumber::Formatter::Pretty
|
39
|
+
```
|
40
|
+
|
41
|
+
To output as Junit do:
|
42
|
+
|
43
|
+
```
|
44
|
+
cucumber --format Cucumber::Formatter::JunitRepeater --out results/
|
45
|
+
```
|
46
|
+
Note: this still displays some Pretty text
|
47
|
+
|
48
|
+
|
49
|
+
To output as Junit and Pretty:
|
50
|
+
```
|
51
|
+
cucumber --format Cucumber::Formatter::Pretty --format Cucumber::Formatter::JunitRepeater --out results/
|
52
|
+
```
|
data/lib/cucumber-repeat.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
|
3
|
+
require_relative('formatter.rb')
|
4
|
+
|
3
5
|
$coloured_output = true
|
4
6
|
|
5
7
|
WINDOWS = RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
@@ -10,56 +12,45 @@ elsif (!ENV['ANSICON'].nil?) then
|
|
10
12
|
$coloured_output =false
|
11
13
|
end
|
12
14
|
|
13
|
-
|
14
15
|
After('@repeat') do | scenario |
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if (scenario.failed?) then
|
17
|
+
for i in 1..2
|
18
|
+
if (scenario.failed?)
|
19
|
+
$stdout.puts blue_text(" Test Failed, Retrying test")
|
20
|
+
run_scenario(scenario)
|
21
|
+
end
|
19
22
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
scenario.steps.each do |step_details|
|
25
|
-
step_details.status!(:passed)
|
23
|
+
if (scenario.passed?) then
|
24
|
+
if (!$failures.nil?) then
|
25
|
+
$failures -= 1
|
26
|
+
end
|
26
27
|
end
|
27
|
-
$stdout.puts " Test Failed, Retrying test".blue
|
28
|
-
run_scenario(scenario)
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
32
31
|
|
33
|
-
def run_scenario(scenario)
|
34
32
|
|
33
|
+
def run_scenario(scenario)
|
35
34
|
scenario.steps.each do |step_details|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
$stdout.puts " " + green_text(step_details.multiline_arg.to_s.gsub(/\e\[(\d+)m/, '').strip)
|
42
|
-
end
|
43
|
-
step_details.status!(:passed)
|
44
|
-
rescue Exception => e
|
45
|
-
$stdout.puts " " + red_text(step_details.name.strip)
|
46
|
-
if (!step_details.multiline_arg.to_s.empty?) then
|
47
|
-
$stdout.puts " " + red_text(step_details.multiline_arg.to_s.gsub(/\e\[(\d+)m/, '').strip)
|
48
|
-
end
|
49
|
-
$stdout.puts e.to_s.red
|
50
|
-
step_details.status!(:failed)
|
35
|
+
begin
|
36
|
+
step step_details.name.to_s, step_details.multiline_arg
|
37
|
+
$stdout.puts " " + green_text(step_details.name.strip)
|
38
|
+
if (!step_details.multiline_arg.to_s.empty?) then
|
39
|
+
$stdout.puts " " + green_text(step_details.multiline_arg.to_s.gsub(/\e\[(\d+)m/, '').strip)
|
51
40
|
end
|
52
|
-
|
53
|
-
|
41
|
+
step_details.status!(:passed)
|
42
|
+
rescue Exception => e
|
43
|
+
$stdout.puts " " + red_text(step_details.name.strip)
|
54
44
|
if (!step_details.multiline_arg.to_s.empty?) then
|
55
|
-
$stdout.puts " " +
|
45
|
+
$stdout.puts " " + red_text(step_details.multiline_arg.to_s.gsub(/\e\[(\d+)m/, '').strip)
|
56
46
|
end
|
47
|
+
$stdout.puts e.to_s.red
|
48
|
+
step_details.status!(:failed)
|
57
49
|
end
|
58
50
|
end
|
59
51
|
end
|
60
52
|
|
61
53
|
def green_text(text)
|
62
|
-
|
63
54
|
if ($coloured_output == true) then
|
64
55
|
text = text.green
|
65
56
|
end
|
@@ -67,7 +58,6 @@ def green_text(text)
|
|
67
58
|
end
|
68
59
|
|
69
60
|
def red_text(text)
|
70
|
-
|
71
61
|
if ($coloured_output == true) then
|
72
62
|
text = text.red
|
73
63
|
end
|
@@ -75,9 +65,15 @@ def red_text(text)
|
|
75
65
|
end
|
76
66
|
|
77
67
|
def yellow_text(text)
|
78
|
-
|
79
68
|
if ($coloured_output == true) then
|
80
69
|
text = text.yellow
|
81
70
|
end
|
82
71
|
return text
|
83
72
|
end
|
73
|
+
|
74
|
+
def blue_text(text)
|
75
|
+
if ($coloured_output == true) then
|
76
|
+
text = text.blue
|
77
|
+
end
|
78
|
+
return text
|
79
|
+
end
|
data/lib/formatter.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'cucumber/formatter/ordered_xml_markup'
|
2
|
+
require 'cucumber/formatter/io'
|
3
|
+
require 'cucumber/formatter/interceptor'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Cucumber
|
7
|
+
module Formatter
|
8
|
+
# The formatter used for <tt>--format junit</tt>
|
9
|
+
class JunitRepeater
|
10
|
+
include Io
|
11
|
+
|
12
|
+
class UnNamedFeatureError < StandardError
|
13
|
+
def initialize(feature_file)
|
14
|
+
super("The feature in '#{feature_file}' does not have a name. The JUnit XML format requires a name for the testsuite element.")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(runtime, io, options)
|
19
|
+
@reportdir = ensure_dir(io, "junit")
|
20
|
+
@options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
def before_feature(feature)
|
24
|
+
@current_feature = feature
|
25
|
+
$failures = @errors = @tests = @skipped = 0
|
26
|
+
|
27
|
+
@builder = OrderedXmlMarkup.new( :indent => 2 )
|
28
|
+
@time = 0
|
29
|
+
# In order to fill out <system-err/> and <system-out/>, we need to
|
30
|
+
# intercept the $stderr and $stdout
|
31
|
+
@interceptedout = Interceptor::Pipe.wrap(:stdout)
|
32
|
+
@interceptederr = Interceptor::Pipe.wrap(:stderr)
|
33
|
+
end
|
34
|
+
|
35
|
+
def before_feature_element(feature_element)
|
36
|
+
@in_examples = Ast::ScenarioOutline === feature_element
|
37
|
+
@steps_start = Time.now
|
38
|
+
end
|
39
|
+
|
40
|
+
def after_feature(feature)
|
41
|
+
@testsuite = OrderedXmlMarkup.new( :indent => 2 )
|
42
|
+
@testsuite.instruct!
|
43
|
+
@testsuite.testsuite(
|
44
|
+
:failures => $failures,
|
45
|
+
:errors => @errors,
|
46
|
+
:skipped => @skipped,
|
47
|
+
:tests => @tests,
|
48
|
+
:time => "%.6f" % @time,
|
49
|
+
:name => @feature_name ) do
|
50
|
+
@testsuite << @builder.target!
|
51
|
+
@testsuite.tag!('system-out') do
|
52
|
+
@testsuite.cdata! strip_control_chars(@interceptedout.buffer.join)
|
53
|
+
end
|
54
|
+
@testsuite.tag!('system-err') do
|
55
|
+
@testsuite.cdata! strip_control_chars(@interceptederr.buffer.join)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
write_file(feature_result_filename(feature.file), @testsuite.target!)
|
60
|
+
|
61
|
+
Interceptor::Pipe.unwrap! :stdout
|
62
|
+
Interceptor::Pipe.unwrap! :stderr
|
63
|
+
end
|
64
|
+
|
65
|
+
def before_background(*args)
|
66
|
+
@in_background = true
|
67
|
+
end
|
68
|
+
|
69
|
+
def after_background(*args)
|
70
|
+
@in_background = false
|
71
|
+
end
|
72
|
+
|
73
|
+
def feature_name(keyword, name)
|
74
|
+
raise UnNamedFeatureError.new(@current_feature.file) if name.empty?
|
75
|
+
lines = name.split(/\r?\n/)
|
76
|
+
@feature_name = lines[0]
|
77
|
+
end
|
78
|
+
|
79
|
+
def scenario_name(keyword, name, file_colon_line, source_indent)
|
80
|
+
@scenario = (name.nil? || name == "") ? "Unnamed scenario" : name.split("\n")[0]
|
81
|
+
@output = "#{keyword}: #{@scenario}\n\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
def before_steps(steps)
|
85
|
+
end
|
86
|
+
|
87
|
+
def after_steps(steps)
|
88
|
+
|
89
|
+
return if @in_background || @in_examples
|
90
|
+
|
91
|
+
duration = Time.now - @steps_start
|
92
|
+
if steps.failed?
|
93
|
+
steps.each { |step| @output += "#{step.keyword}#{step.name}\n" }
|
94
|
+
@output += "\nMessage:\n"
|
95
|
+
end
|
96
|
+
build_testcase(duration, steps.status, steps.exception)
|
97
|
+
end
|
98
|
+
|
99
|
+
def before_examples(*args)
|
100
|
+
@header_row = true
|
101
|
+
@in_examples = true
|
102
|
+
end
|
103
|
+
|
104
|
+
def after_examples(*args)
|
105
|
+
@in_examples = false
|
106
|
+
end
|
107
|
+
|
108
|
+
def before_table_row(table_row)
|
109
|
+
return unless @in_examples
|
110
|
+
|
111
|
+
@table_start = Time.now
|
112
|
+
end
|
113
|
+
|
114
|
+
def after_table_row(table_row)
|
115
|
+
|
116
|
+
return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row
|
117
|
+
duration = Time.now - @table_start
|
118
|
+
unless @header_row
|
119
|
+
name_suffix = " (outline example : #{table_row.name})"
|
120
|
+
if table_row.failed?
|
121
|
+
@output += "Example row: #{table_row.name}\n"
|
122
|
+
@output += "\nMessage:\n"
|
123
|
+
end
|
124
|
+
build_testcase(duration, table_row.status, table_row.exception, name_suffix)
|
125
|
+
end
|
126
|
+
|
127
|
+
@header_row = false if @header_row
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def build_testcase(duration, status, exception = nil, suffix = "")
|
133
|
+
@time += duration
|
134
|
+
classname = @feature_name
|
135
|
+
name = "#{@scenario}#{suffix}"
|
136
|
+
pending = [:pending, :undefined].include?(status) && (!@options[:strict])
|
137
|
+
|
138
|
+
@builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
|
139
|
+
if status == :skipped || pending
|
140
|
+
@builder.skipped
|
141
|
+
@skipped += 1
|
142
|
+
elsif status != :passed
|
143
|
+
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
|
144
|
+
@builder.cdata! @output
|
145
|
+
@builder.cdata!(format_exception(exception)) if exception
|
146
|
+
end
|
147
|
+
$failures += 1
|
148
|
+
end
|
149
|
+
@builder.tag!('system-out')
|
150
|
+
@builder.tag!('system-err')
|
151
|
+
end
|
152
|
+
@tests += 1
|
153
|
+
end
|
154
|
+
|
155
|
+
def format_exception(exception)
|
156
|
+
(["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
|
157
|
+
end
|
158
|
+
|
159
|
+
def feature_result_filename(feature_file)
|
160
|
+
File.join(@reportdir, "TEST-#{basename(feature_file)}.xml")
|
161
|
+
end
|
162
|
+
|
163
|
+
def basename(feature_file)
|
164
|
+
File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
|
165
|
+
end
|
166
|
+
|
167
|
+
def write_file(feature_filename, data)
|
168
|
+
File.open(feature_filename, 'w') { |file| file.write(data) }
|
169
|
+
end
|
170
|
+
|
171
|
+
# strip control chars from cdata, to make it safe for external parsers
|
172
|
+
def strip_control_chars(cdata)
|
173
|
+
cdata.scan(/[[:print:]\t\n\r]/).join
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-repeat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Moore
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -45,6 +45,7 @@ extensions: []
|
|
45
45
|
extra_rdoc_files: []
|
46
46
|
files:
|
47
47
|
- lib/cucumber-repeat.rb
|
48
|
+
- lib/formatter.rb
|
48
49
|
- LICENSE
|
49
50
|
- README.md
|
50
51
|
homepage: https://github.com/mooreandrew/cucumber-repeat
|