gurke 2.4.2 → 3.0.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 +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
|