gurke 2.4.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +4 -0
- data/bin/gurke +2 -0
- data/features/gurke.feature +2 -5
- data/features/gurke.rb +2 -1
- data/features/gurke/backtrace_filtering.feature +3 -4
- data/features/gurke/context_in_hooks.feature +1 -2
- data/features/gurke/filter_by_tags.feature +5 -6
- data/features/gurke/include_by_tags.feature +1 -2
- data/features/gurke/other_reporter.feature +3 -4
- data/features/gurke/pending_steps.feature +1 -4
- data/features/gurke/run_specific_directories.feature +4 -5
- data/features/gurke/run_specific_scenarios.feature +5 -6
- data/features/gurke/step_specific_definitions.feature +1 -4
- data/features/support/steps/cli_steps.rb +17 -8
- data/features/support/steps/file_steps.rb +2 -9
- data/gurke.gemspec +10 -9
- data/lib/gurke.rb +3 -0
- data/lib/gurke/background.rb +2 -0
- data/lib/gurke/builder.rb +10 -11
- data/lib/gurke/capybara.rb +2 -0
- data/lib/gurke/cli.rb +35 -27
- data/lib/gurke/configuration.rb +9 -6
- data/lib/gurke/dsl.rb +9 -5
- data/lib/gurke/feature.rb +6 -8
- data/lib/gurke/feature_list.rb +11 -7
- data/lib/gurke/reporter.rb +41 -34
- data/lib/gurke/reporters/compact_reporter.rb +137 -0
- data/lib/gurke/reporters/default_reporter.rb +57 -16
- data/lib/gurke/reporters/null_reporter.rb +4 -2
- data/lib/gurke/reporters/team_city_reporter.rb +11 -13
- data/lib/gurke/rspec.rb +2 -0
- data/lib/gurke/run_list.rb +2 -0
- data/lib/gurke/runner.rb +12 -6
- data/lib/gurke/scenario.rb +41 -2
- data/lib/gurke/step.rb +24 -14
- data/lib/gurke/step_definition.rb +3 -1
- data/lib/gurke/steps.rb +3 -1
- data/lib/gurke/tag.rb +5 -1
- data/lib/gurke/version.rb +5 -3
- data/spec/gurke/feature_list_spec.rb +4 -2
- data/spec/gurke/reporters/default_reporter_spec.rb +201 -0
- data/spec/gurke/run_list_spec.rb +2 -0
- data/spec/gurke/scenario_spec.rb +5 -3
- data/spec/gurke/step_definition_spec.rb +3 -1
- data/spec/spec_helper.rb +10 -1
- metadata +8 -6
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
# Colors
|
6
|
+
# :black, :red, :green, :yellow, :blue,
|
7
|
+
# :magenta, :cyan, :white, :default, :light_black,
|
8
|
+
# :light_red, :light_green, :light_yellow, :light_blue,
|
9
|
+
# :light_magenta, :light_cyan, :light_white
|
10
|
+
#
|
11
|
+
module Gurke::Reporters
|
12
|
+
#
|
13
|
+
class CompactReporter < NullReporter
|
14
|
+
attr_reader :io
|
15
|
+
|
16
|
+
def initialize(io = $stdout)
|
17
|
+
@io = io
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_step(result, scenario, *)
|
21
|
+
return unless result.state == :failed
|
22
|
+
|
23
|
+
io.print red 'E'
|
24
|
+
|
25
|
+
feature = scenario.feature
|
26
|
+
|
27
|
+
io.puts
|
28
|
+
io.print yellow('Feature')
|
29
|
+
io.print ': '
|
30
|
+
io.print scenario.feature.name
|
31
|
+
io.print ' '
|
32
|
+
io.print format_location(scenario.feature)
|
33
|
+
io.puts
|
34
|
+
|
35
|
+
io.print ' '
|
36
|
+
io.print yellow('Scenario')
|
37
|
+
io.print ': '
|
38
|
+
io.print scenario.name
|
39
|
+
io.print ' '
|
40
|
+
io.print format_location(scenario)
|
41
|
+
io.puts
|
42
|
+
|
43
|
+
background = feature.backgrounds.map(&:steps).flatten
|
44
|
+
|
45
|
+
catch(:break) do
|
46
|
+
if background.any?
|
47
|
+
io.print ' '
|
48
|
+
io.print light_black('Background')
|
49
|
+
io.print ':'
|
50
|
+
io.puts
|
51
|
+
|
52
|
+
background.each do |step|
|
53
|
+
io.print ' '
|
54
|
+
io.print yellow(step.keyword)
|
55
|
+
io.print ' '
|
56
|
+
io.print step.name.gsub(/"(.*?)"/, cyan('\0'))
|
57
|
+
io.puts
|
58
|
+
|
59
|
+
throw :break if step == result.step
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
scenario.steps.each do |step|
|
64
|
+
io.print ' '
|
65
|
+
io.print yellow(step.keyword)
|
66
|
+
io.print ' '
|
67
|
+
io.print step.name.gsub(/"(.*?)"/, cyan('\0'))
|
68
|
+
io.puts
|
69
|
+
|
70
|
+
throw :break if step == result.step
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
exout = format_exception(result.exception, backtrace: true)
|
75
|
+
io.puts red exout.join("\n").gsub(/^/, ' ')
|
76
|
+
io.puts
|
77
|
+
end
|
78
|
+
|
79
|
+
def after_scenario(scenario)
|
80
|
+
if scenario.failed?
|
81
|
+
# printed in after_step
|
82
|
+
elsif scenario.pending?
|
83
|
+
io.print yellow '?'
|
84
|
+
elsif scenario.passed?
|
85
|
+
io.print green '.'
|
86
|
+
elsif scenario.aborted?
|
87
|
+
io.puts
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def after_features(features)
|
92
|
+
io.puts
|
93
|
+
io.puts
|
94
|
+
|
95
|
+
scenarios = features.map(&:scenarios).flatten
|
96
|
+
|
97
|
+
size = scenarios.size
|
98
|
+
passed = scenarios.select(&:passed?).size
|
99
|
+
failed = scenarios.select(&:failed?).size
|
100
|
+
pending = scenarios.select(&:pending?).size
|
101
|
+
not_run = size - scenarios.select(&:run?).size
|
102
|
+
|
103
|
+
message = "#{scenarios.size} scenarios: "
|
104
|
+
message += "#{passed} passed, "
|
105
|
+
message += "#{failed} failing, #{pending} pending"
|
106
|
+
message += ", #{not_run} not run" if not_run.positive?
|
107
|
+
|
108
|
+
if failed.positive?
|
109
|
+
io.puts red message
|
110
|
+
elsif pending.positive? || not_run.positive?
|
111
|
+
io.puts yellow message
|
112
|
+
else
|
113
|
+
io.puts green message
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def format_location(obj)
|
120
|
+
file = obj.file.to_s
|
121
|
+
line = obj.line.to_s
|
122
|
+
cwd = Pathname.new(Dir.getwd)
|
123
|
+
path = Pathname.new(file).relative_path_from(cwd).to_s
|
124
|
+
path = file if path.length > file.length
|
125
|
+
|
126
|
+
light_black("# #{path}:#{line}")
|
127
|
+
end
|
128
|
+
|
129
|
+
%i[black red green yellow blue
|
130
|
+
magenta cyan white default light_black
|
131
|
+
light_red light_green light_yellow light_blue
|
132
|
+
light_magenta light_cyan light_white].each do |color|
|
133
|
+
|
134
|
+
define_method(color) {|str| io.tty? ? str.send(color) : str }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'colorize'
|
2
4
|
|
3
5
|
# Colors
|
@@ -15,24 +17,36 @@ module Gurke::Reporters
|
|
15
17
|
#
|
16
18
|
class DefaultReporter < NullReporter
|
17
19
|
attr_reader :io
|
20
|
+
|
18
21
|
def initialize(io = $stdout)
|
19
22
|
@io = io
|
20
23
|
end
|
21
24
|
|
22
25
|
def before_feature(feature)
|
23
|
-
io.
|
24
|
-
io.
|
26
|
+
io.print yellow('Feature')
|
27
|
+
io.print ': '
|
28
|
+
io.print feature.name
|
29
|
+
io.print ' '
|
30
|
+
io.print format_location(feature)
|
31
|
+
io.puts
|
32
|
+
|
33
|
+
io.print light_black(feature.description.gsub(/^/, ' '))
|
34
|
+
io.puts
|
25
35
|
io.puts
|
26
36
|
end
|
27
37
|
|
28
38
|
def before_scenario(scenario)
|
29
|
-
io.
|
39
|
+
io.print ' '
|
40
|
+
io.print yellow('Scenario')
|
41
|
+
io.print ': '
|
42
|
+
io.print scenario.name
|
43
|
+
io.print ' '
|
44
|
+
io.print format_location(scenario)
|
45
|
+
io.puts
|
30
46
|
end
|
31
47
|
|
32
48
|
def start_background(*)
|
33
|
-
unless @background
|
34
|
-
io.puts light_black(' Background:')
|
35
|
-
end
|
49
|
+
io.puts light_black(' Background:') unless @background
|
36
50
|
|
37
51
|
@background = true
|
38
52
|
end
|
@@ -45,6 +59,7 @@ module Gurke::Reporters
|
|
45
59
|
io.print ' ' if @background
|
46
60
|
io.print ' '
|
47
61
|
io.print yellow(step.keyword)
|
62
|
+
io.print ' '
|
48
63
|
io.print step.name.gsub(/"(.*?)"/, cyan('\0'))
|
49
64
|
end
|
50
65
|
|
@@ -52,7 +67,7 @@ module Gurke::Reporters
|
|
52
67
|
case step.state
|
53
68
|
when :pending then print_braces yellow 'pending'
|
54
69
|
when :failed then print_failed step
|
55
|
-
when :
|
70
|
+
when :passed then print_braces green 'passed'
|
56
71
|
else print_braces cyan 'skipped'
|
57
72
|
end
|
58
73
|
io.puts
|
@@ -70,14 +85,40 @@ module Gurke::Reporters
|
|
70
85
|
def after_features(features)
|
71
86
|
scenarios = features.map(&:scenarios).flatten
|
72
87
|
|
73
|
-
|
74
|
-
|
75
|
-
|
88
|
+
size = scenarios.size
|
89
|
+
passed = scenarios.select(&:passed?).size
|
90
|
+
failed = scenarios.select(&:failed?).size
|
91
|
+
pending = scenarios.select(&:pending?).size
|
92
|
+
not_run = size - scenarios.select(&:run?).size
|
93
|
+
|
94
|
+
message = "#{scenarios.size} scenarios: "
|
95
|
+
message += "#{passed} passed, " unless passed == size || passed.zero?
|
96
|
+
message += "#{failed} failing, #{pending} pending"
|
97
|
+
message += ", #{not_run} not run" if not_run.positive?
|
98
|
+
|
99
|
+
if failed.positive?
|
100
|
+
io.puts red message
|
101
|
+
elsif pending.positive? || not_run.positive?
|
102
|
+
io.puts yellow message
|
103
|
+
else
|
104
|
+
io.puts green message
|
105
|
+
end
|
106
|
+
|
76
107
|
io.puts
|
77
108
|
end
|
78
109
|
|
79
110
|
private
|
80
111
|
|
112
|
+
def format_location(obj)
|
113
|
+
file = obj.file.to_s
|
114
|
+
line = obj.line.to_s
|
115
|
+
cwd = Pathname.new(Dir.getwd)
|
116
|
+
path = Pathname.new(file).relative_path_from(cwd).to_s
|
117
|
+
path = file if path.length > file.length
|
118
|
+
|
119
|
+
light_black("# #{path}:#{line}")
|
120
|
+
end
|
121
|
+
|
81
122
|
def print_braces(str)
|
82
123
|
io.print " (#{str})"
|
83
124
|
end
|
@@ -87,15 +128,15 @@ module Gurke::Reporters
|
|
87
128
|
io.puts
|
88
129
|
|
89
130
|
exout = format_exception(step.exception)
|
90
|
-
io.puts exout.map{|s| red(" #{s}\n") }.join
|
131
|
+
io.puts exout.map {|s| red(" #{s}\n") }.join
|
91
132
|
end
|
92
133
|
|
93
|
-
[
|
94
|
-
|
95
|
-
|
96
|
-
|
134
|
+
%i[black red green yellow blue
|
135
|
+
magenta cyan white default light_black
|
136
|
+
light_red light_green light_yellow light_blue
|
137
|
+
light_magenta light_cyan light_white].each do |color|
|
97
138
|
|
98
|
-
define_method(color){|str|
|
139
|
+
define_method(color) {|str| io.tty? ? str.send(color) : str }
|
99
140
|
end
|
100
141
|
end
|
101
142
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gurke::Reporters
|
2
4
|
#
|
3
5
|
# The {NullReporter} does not do anything.
|
4
6
|
#
|
5
7
|
class NullReporter < Gurke::Reporter
|
6
8
|
Gurke::Reporter::CALLBACKS.each do |cb|
|
7
|
-
class_eval <<-
|
9
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
8
10
|
def #{cb}(*) end
|
9
|
-
|
11
|
+
RUBY
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gurke::Reporters
|
2
4
|
#
|
3
5
|
# The {TeamCityReporter} prints features, scenarios and
|
@@ -21,9 +23,7 @@ module Gurke::Reporters
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def start_background(*)
|
24
|
-
unless @background
|
25
|
-
io.puts ' Background:'
|
26
|
-
end
|
26
|
+
io.puts ' Background:' unless @background
|
27
27
|
|
28
28
|
@background = true
|
29
29
|
end
|
@@ -77,30 +77,28 @@ module Gurke::Reporters
|
|
77
77
|
io.print " (#{str})"
|
78
78
|
end
|
79
79
|
|
80
|
-
def print_pending(
|
80
|
+
def print_pending(_step)
|
81
81
|
return if @pending == @scenario # only once per scenario
|
82
82
|
publish :testIgnored,
|
83
|
-
|
84
|
-
|
83
|
+
name: @scenario.name,
|
84
|
+
message: 'Step definition missing'
|
85
85
|
@pending = @scenario
|
86
86
|
end
|
87
87
|
|
88
88
|
def print_failed(step)
|
89
89
|
publish :testFailed,
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
name: @scenario.name,
|
91
|
+
message: step.exception.inspect,
|
92
|
+
backtrace: step.exception.backtrace.join('\n')
|
93
93
|
@pending = @scenario
|
94
94
|
|
95
95
|
print_braces 'failure'
|
96
96
|
io.puts
|
97
97
|
|
98
98
|
exout = format_exception(step.exception)
|
99
|
-
io.puts exout.map{|s| " #{s}\n" }.join
|
99
|
+
io.puts exout.map {|s| " #{s}\n" }.join
|
100
100
|
end
|
101
101
|
|
102
|
-
|
103
|
-
private
|
104
102
|
def publish(message_name, args)
|
105
103
|
args = [] << message_name.to_s << escaped_array_of(args)
|
106
104
|
args = args.flatten.reject(&:nil?)
|
@@ -116,7 +114,7 @@ module Gurke::Reporters
|
|
116
114
|
return [] if args.nil?
|
117
115
|
|
118
116
|
if args.is_a? Hash
|
119
|
-
args.map {
|
117
|
+
args.map {|key, value| "#{key}='#{escape value.to_s}'" }
|
120
118
|
else
|
121
119
|
"'#{escape args}'"
|
122
120
|
end
|
data/lib/gurke/rspec.rb
CHANGED
data/lib/gurke/run_list.rb
CHANGED
data/lib/gurke/runner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gurke
|
2
4
|
class Runner
|
3
5
|
attr_reader :config, :options
|
@@ -9,7 +11,11 @@ module Gurke
|
|
9
11
|
|
10
12
|
def reporter
|
11
13
|
@reporter ||= begin
|
12
|
-
r = (options[:formatter] + '_reporter')
|
14
|
+
r = (options[:formatter] + '_reporter')
|
15
|
+
.split('_')
|
16
|
+
.map(&:capitalize)
|
17
|
+
.join
|
18
|
+
|
13
19
|
Reporters.const_get(r).new
|
14
20
|
end
|
15
21
|
end
|
@@ -21,10 +27,10 @@ module Gurke
|
|
21
27
|
def run(files, reporter = self.reporter)
|
22
28
|
files.map! do |file|
|
23
29
|
split = file.split(':')
|
24
|
-
[split[0], split[1..-1].map{|i| Integer(i) }]
|
30
|
+
[split[0], split[1..-1].map {|i| Integer(i) }]
|
25
31
|
end
|
26
32
|
|
27
|
-
features = builder.load
|
33
|
+
features = builder.load(files.map {|file, _| file })
|
28
34
|
features.filter(options, files).run self, reporter
|
29
35
|
end
|
30
36
|
|
@@ -34,10 +40,10 @@ module Gurke
|
|
34
40
|
|
35
41
|
def with_filtered_backtrace
|
36
42
|
yield
|
37
|
-
rescue => e
|
43
|
+
rescue StandardError => e
|
38
44
|
unless options[:backtrace]
|
39
45
|
base = File.expand_path(Gurke.root.dirname)
|
40
|
-
e.backtrace.select!{|l| File.expand_path(l)[0...base.size] == base }
|
46
|
+
e.backtrace.select! {|l| File.expand_path(l)[0...base.size] == base }
|
41
47
|
end
|
42
48
|
raise
|
43
49
|
end
|
@@ -53,7 +59,7 @@ module Gurke
|
|
53
59
|
class DRbServer < Runner
|
54
60
|
URI = 'druby://localhost:8789'
|
55
61
|
|
56
|
-
def run(
|
62
|
+
def run(_files)
|
57
63
|
require 'drb'
|
58
64
|
|
59
65
|
hook :system, nil, nil do
|
data/lib/gurke/scenario.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gurke
|
2
4
|
class Scenario
|
3
5
|
#
|
@@ -42,6 +44,7 @@ module Gurke
|
|
42
44
|
@line = line
|
43
45
|
@tags = tags
|
44
46
|
@raw = raw
|
47
|
+
@state = nil
|
45
48
|
end
|
46
49
|
|
47
50
|
# Return name of the scenario.
|
@@ -86,6 +89,28 @@ module Gurke
|
|
86
89
|
@state == :failed
|
87
90
|
end
|
88
91
|
|
92
|
+
# Check if scenario has passed.
|
93
|
+
#
|
94
|
+
# @return [Boolean] True if scenario passed, false otherwise.
|
95
|
+
#
|
96
|
+
def passed?
|
97
|
+
@state == :passed
|
98
|
+
end
|
99
|
+
|
100
|
+
# Check if scenario was aborted.
|
101
|
+
#
|
102
|
+
# @return [Boolean] True if aborted, false otherwise.
|
103
|
+
#
|
104
|
+
def aborted?
|
105
|
+
@state == :aborted
|
106
|
+
end
|
107
|
+
|
108
|
+
# Check if scenario was run and the state has changed.
|
109
|
+
#
|
110
|
+
def run?
|
111
|
+
!@state.nil?
|
112
|
+
end
|
113
|
+
|
89
114
|
# Exception that led to either pending or failed state.
|
90
115
|
#
|
91
116
|
# @return [Exception] Exception or nil of none given.
|
@@ -107,12 +132,24 @@ module Gurke
|
|
107
132
|
# @param error [Exception] Given an exception as reason.
|
108
133
|
#
|
109
134
|
def pending!(error)
|
110
|
-
return if failed?
|
111
|
-
|
112
135
|
@exception = error
|
113
136
|
@state = :pending
|
114
137
|
end
|
115
138
|
|
139
|
+
# @api private
|
140
|
+
#
|
141
|
+
def passed!
|
142
|
+
@exception = nil
|
143
|
+
@state = :passed
|
144
|
+
end
|
145
|
+
|
146
|
+
# @api private
|
147
|
+
#
|
148
|
+
def abort!
|
149
|
+
@exception = nil
|
150
|
+
@state = :aborted
|
151
|
+
end
|
152
|
+
|
116
153
|
# @api private
|
117
154
|
#
|
118
155
|
def run(runner, reporter)
|
@@ -132,6 +169,8 @@ module Gurke
|
|
132
169
|
|
133
170
|
feature.backgrounds.run runner, reporter, self, world
|
134
171
|
steps.run runner, reporter, self, world
|
172
|
+
|
173
|
+
passed! unless @state
|
135
174
|
ensure
|
136
175
|
reporter.invoke :end_scenario, self
|
137
176
|
end
|