cucumber 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/History.txt +86 -3
  2. data/Manifest.txt +93 -44
  3. data/Rakefile +5 -1
  4. data/bin/cucumber +1 -0
  5. data/cucumber.yml +1 -1
  6. data/examples/calculator_ruby_features/features/{steps → step_definitons}/calculator_steps.rb +0 -0
  7. data/examples/cs/features/{steps → step_definitons}/hello_steps.rb +0 -0
  8. data/examples/cs/features/{steps → step_definitons}/tree_steps.rb +0 -0
  9. data/examples/i18n/README.textile +18 -0
  10. data/examples/i18n/Rakefile +16 -0
  11. data/examples/i18n/ar/Rakefile +6 -0
  12. data/examples/i18n/ar/features/addition.feature +17 -0
  13. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +31 -0
  14. data/examples/i18n/ar/lib/calculator.rb +10 -0
  15. data/examples/i18n/da/Rakefile +6 -0
  16. data/examples/{danish_calculator/features/steps → i18n/da/features/step_definitons}/kalkulator_steps.rb +0 -0
  17. data/examples/{danish_calculator → i18n/da}/features/summering.feature +1 -1
  18. data/examples/{danish_calculator → i18n/da}/lib/kalkulator.rb +0 -0
  19. data/examples/{swedish_calculator → i18n/en}/Rakefile +1 -1
  20. data/examples/{calculator → i18n/en}/features/addition.feature +0 -0
  21. data/examples/{calculator → i18n/en}/features/division.feature +0 -0
  22. data/examples/{calculator/features/steps → i18n/en/features/step_definitons}/calculator_steps.rb +0 -0
  23. data/examples/{calculator → i18n/en}/lib/calculator.rb +0 -2
  24. data/examples/i18n/es/Rakefile +6 -0
  25. data/examples/{spanish_calculator → i18n/es}/features/adicion.feature +1 -1
  26. data/examples/{spanish_calculator/features/steps → i18n/es/features/step_definitons}/calculador_steps.rb +0 -0
  27. data/examples/{spanish_calculator/lib/Calculador.rb → i18n/es/lib/calculador.rb} +0 -0
  28. data/examples/i18n/et/Rakefile +6 -0
  29. data/examples/i18n/et/features/liitmine.feature +17 -0
  30. data/examples/{estonian_calculator/features → i18n/et/features/step_definitions}/kalkulaator_steps.rb +2 -11
  31. data/examples/i18n/et/lib/kalkulaator.rb +10 -0
  32. data/examples/i18n/fr/Rakefile +6 -0
  33. data/examples/{calculatrice_francaise_avec_soit_scenario → i18n/fr}/features/addition.feature +0 -0
  34. data/examples/{calculatrice_francaise_avec_soit_scenario/features → i18n/fr/features/step_definitions}/calculatrice_steps.rb +2 -11
  35. data/examples/i18n/fr/lib/calculatrice.rb +10 -0
  36. data/examples/i18n/id/Rakefile +6 -0
  37. data/examples/i18n/id/features/addition.feature +17 -0
  38. data/examples/i18n/id/features/division.feature +10 -0
  39. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +31 -0
  40. data/examples/i18n/id/lib/calculator.rb +14 -0
  41. data/examples/i18n/it/Rakefile +6 -0
  42. data/examples/i18n/it/features/somma.feature +10 -0
  43. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +22 -0
  44. data/examples/i18n/it/lib/calcolatrice.rb +11 -0
  45. data/examples/{calculator → i18n/ja}/README.txt +0 -0
  46. data/examples/i18n/ja/Rakefile +6 -0
  47. data/examples/i18n/ja/features/addition.feature +17 -0
  48. data/examples/i18n/ja/features/division.feature +10 -0
  49. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +30 -0
  50. data/examples/i18n/ja/lib/calculator.rb +14 -0
  51. data/examples/i18n/no/Rakefile +6 -0
  52. data/examples/{norwegian_calculator/features/steps → i18n/no/features/step_definitons}/kalkulator_steps.rb +0 -0
  53. data/examples/{norwegian_calculator → i18n/no}/features/summering.feature +0 -0
  54. data/examples/{norwegian_calculator → i18n/no}/lib/kalkulator.rb +0 -0
  55. data/examples/i18n/pt/Rakefile +6 -0
  56. data/examples/{portuguese_calculator → i18n/pt}/features/adicao.feature +0 -0
  57. data/examples/{portuguese_calculator/features → i18n/pt/features/step_definitions}/calculadora_steps.rb +2 -11
  58. data/examples/i18n/pt/lib/calculadora.rb +10 -0
  59. data/examples/i18n/ro/Rakefile +6 -0
  60. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +22 -0
  61. data/examples/i18n/ro/features/suma.feature +10 -0
  62. data/examples/i18n/ro/lib/calculator.rb +11 -0
  63. data/examples/i18n/se/Rakefile +6 -0
  64. data/examples/{swedish_calculator/features/steps → i18n/se/features/step_definitons}/kalkulator_steps.rb +0 -0
  65. data/examples/{swedish_calculator → i18n/se}/features/summering.feature +0 -0
  66. data/examples/{swedish_calculator → i18n/se}/lib/kalkulator.rb +0 -0
  67. data/examples/i18n/zh-CN/Rakefile +6 -0
  68. data/examples/{chinese_simplified_calculator → i18n/zh-CN}/features/addition.feature +0 -0
  69. data/examples/{chinese_simplified_calculator/features/steps → i18n/zh-CN/features/step_definitons}/calculator_steps.rb +0 -0
  70. data/examples/{chinese_simplified_calculator → i18n/zh-CN}/lib/calculator.rb +0 -0
  71. data/examples/java/features/{steps → step_definitons}/hello_steps.rb +0 -0
  72. data/examples/java/features/{steps → step_definitons}/tree_steps.rb +0 -0
  73. data/examples/selenium/features/{steps → step_definitons}/stories_steps.rb +0 -0
  74. data/examples/tickets/features/{steps → step_definitons}/tickets_steps.rb +0 -0
  75. data/examples/watir/features/search.feature +2 -2
  76. data/examples/watir/features/{steps → step_definitons}/stories_steps.rb +0 -0
  77. data/gem_tasks/treetop.rake +1 -9
  78. data/lib/autotest/cucumber.rb +6 -0
  79. data/lib/autotest/cucumber_mixin.rb +109 -0
  80. data/lib/autotest/cucumber_rails.rb +6 -0
  81. data/lib/autotest/cucumber_rails_rspec.rb +6 -0
  82. data/lib/autotest/cucumber_rspec.rb +6 -0
  83. data/lib/autotest/discover.rb +9 -0
  84. data/lib/cucumber.rb +4 -0
  85. data/lib/cucumber/broadcaster.rb +20 -0
  86. data/lib/cucumber/cli.rb +139 -48
  87. data/lib/cucumber/core_ext/proc.rb +2 -3
  88. data/lib/cucumber/executor.rb +59 -32
  89. data/lib/cucumber/formatters.rb +1 -1
  90. data/lib/cucumber/formatters/ansicolor.rb +3 -4
  91. data/lib/cucumber/formatters/autotest_formatter.rb +23 -0
  92. data/lib/cucumber/formatters/pretty_formatter.rb +99 -42
  93. data/lib/cucumber/formatters/progress_formatter.rb +21 -5
  94. data/lib/cucumber/languages.yml +125 -10
  95. data/lib/cucumber/rails/world.rb +1 -1
  96. data/lib/cucumber/rake/task.rb +52 -26
  97. data/lib/cucumber/step_mother.rb +7 -1
  98. data/lib/cucumber/tree/feature.rb +8 -6
  99. data/lib/cucumber/tree/scenario.rb +34 -15
  100. data/lib/cucumber/tree/step.rb +3 -1
  101. data/lib/cucumber/treetop_parser/feature.treetop.erb +15 -10
  102. data/lib/cucumber/treetop_parser/feature_ar.rb +1591 -0
  103. data/lib/cucumber/treetop_parser/feature_cy.rb +1591 -0
  104. data/lib/cucumber/treetop_parser/feature_da.rb +238 -240
  105. data/lib/cucumber/treetop_parser/feature_de.rb +238 -240
  106. data/lib/cucumber/treetop_parser/feature_en-tx.rb +1591 -0
  107. data/lib/cucumber/treetop_parser/feature_en.rb +238 -240
  108. data/lib/cucumber/treetop_parser/feature_es.rb +238 -240
  109. data/lib/cucumber/treetop_parser/feature_et.rb +238 -240
  110. data/lib/cucumber/treetop_parser/feature_fr.rb +238 -240
  111. data/lib/cucumber/treetop_parser/feature_id.rb +1591 -0
  112. data/lib/cucumber/treetop_parser/feature_it.rb +1591 -0
  113. data/lib/cucumber/treetop_parser/feature_ja.rb +1591 -0
  114. data/lib/cucumber/treetop_parser/feature_nl.rb +238 -240
  115. data/lib/cucumber/treetop_parser/feature_no.rb +238 -240
  116. data/lib/cucumber/treetop_parser/feature_pl.rb +1591 -0
  117. data/lib/cucumber/treetop_parser/feature_pt.rb +238 -240
  118. data/lib/cucumber/treetop_parser/feature_ro.rb +1591 -0
  119. data/lib/cucumber/treetop_parser/feature_ro2.rb +1591 -0
  120. data/lib/cucumber/treetop_parser/feature_ru.rb +238 -240
  121. data/lib/cucumber/treetop_parser/feature_se.rb +238 -240
  122. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +238 -240
  123. data/lib/cucumber/version.rb +1 -1
  124. data/rails_generators/cucumber/USAGE +11 -0
  125. data/rails_generators/cucumber/cucumber_generator.rb +9 -6
  126. data/rails_generators/cucumber/templates/cucumber +6 -1
  127. data/rails_generators/cucumber/templates/{common_webrat.rb → webrat_steps.rb} +4 -0
  128. data/rails_generators/feature/USAGE +12 -0
  129. data/rails_generators/feature/feature_generator.rb +3 -4
  130. data/spec/cucumber/broadcaster_spec.rb +27 -0
  131. data/spec/cucumber/cli_spec.rb +211 -23
  132. data/spec/cucumber/executor_spec.rb +104 -14
  133. data/spec/cucumber/formatters/ansicolor_spec.rb +9 -1
  134. data/spec/cucumber/formatters/autotest_formatter_spec.rb +26 -0
  135. data/spec/cucumber/formatters/pretty_formatter_spec.rb +119 -26
  136. data/spec/cucumber/formatters/profile_formatter_spec.rb +1 -2
  137. data/spec/cucumber/formatters/progress_formatter_spec.rb +22 -1
  138. data/spec/cucumber/sell_cucumbers.feature +10 -0
  139. data/spec/cucumber/step_mother_spec.rb +21 -0
  140. data/spec/cucumber/tree/row_scenario_spec.rb +25 -0
  141. data/spec/cucumber/tree/scenario_spec.rb +47 -8
  142. data/spec/cucumber/tree/step_spec.rb +19 -0
  143. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +2 -0
  144. data/spec/cucumber/treetop_parser/multiline_steps.feature +7 -3
  145. data/spec/spec_helper.rb +2 -0
  146. metadata +97 -48
  147. data/examples/calculator/Rakefile +0 -5
  148. data/examples/calculatrice_francaise_avec_soit_scenario/Rakefile +0 -6
  149. data/examples/chinese_simplified_calculator/Rakefile +0 -6
  150. data/examples/danish_calculator/Rakefile +0 -6
  151. data/examples/estonian_calculator/Rakefile +0 -6
  152. data/examples/estonian_calculator/features/liitmine.feature +0 -16
  153. data/examples/norwegian_calculator/Rakefile +0 -6
  154. data/examples/portuguese_calculator/Rakefile +0 -6
  155. data/examples/spanish_calculator/Rakefile +0 -6
@@ -10,10 +10,9 @@ module Cucumber
10
10
 
11
11
  def call_in(obj, *args)
12
12
  obj.extend(mod)
13
- a = arity == -1 ? 0 : arity
14
- if self != StepMother::PENDING && args.length != a
13
+ if self != StepMother::PENDING && args.length != arity2
15
14
  # We have to manually raise when the block has arity -1 (no pipes)
16
- raise ArityMismatchError.new("expected #{arity == -1 ? 0 : arity} block argument(s), got #{args.length}")
15
+ raise ArityMismatchError.new("expected #{arity2} block argument(s), got #{args.length}")
17
16
  else
18
17
  obj.__send__(meth, *args)
19
18
  end
@@ -3,22 +3,26 @@ require 'cucumber/core_ext/proc'
3
3
  module Cucumber
4
4
  class Executor
5
5
  attr_reader :failed
6
- attr_accessor :formatter
7
-
6
+ attr_accessor :formatters
7
+ attr_writer :scenario_names
8
+
8
9
  def line=(line)
9
10
  @line = line
10
11
  end
11
12
 
12
13
  def initialize(step_mother)
13
- @world_proc = lambda do
14
+ @world_proc = lambda do
14
15
  Object.new
15
16
  end
16
17
  @before_scenario_procs = []
17
18
  @after_scenario_procs = []
18
19
  @after_step_procs = []
19
20
  @step_mother = step_mother
21
+
22
+ @executed_scenarios = {}
23
+ @regular_scenario_cache = {}
20
24
  end
21
-
25
+
22
26
  def register_world_proc(&proc)
23
27
  @world_proc = proc
24
28
  end
@@ -40,47 +44,65 @@ module Cucumber
40
44
 
41
45
  def visit_features(features)
42
46
  raise "Line number can only be specified when there is 1 feature. There were #{features.length}." if @line && features.length != 1
43
- formatter.visit_features(features) if formatter.respond_to?(:visit_features)
47
+ formatters.visit_features(features)
44
48
  features.accept(self)
45
- formatter.dump
49
+ formatters.dump
46
50
  end
47
51
 
48
52
  def visit_feature(feature)
49
- formatter.visit_feature(feature) if formatter.respond_to?(:visit_feature)
50
- feature.accept(self)
53
+ if accept_feature?(feature)
54
+ formatters.feature_executing(feature)
55
+ feature.accept(self)
56
+ @executed_scenarios = {}
57
+ @regular_scenario_cache = {}
58
+ end
51
59
  end
52
60
 
53
61
  def visit_header(header)
54
- formatter.header_executing(header) if formatter.respond_to?(:header_executing)
62
+ formatters.header_executing(header)
55
63
  end
56
64
 
57
65
  def visit_row_scenario(scenario)
66
+ execute_scenario(@regular_scenario_cache[scenario.name]) if executing_unprepared_row_scenario?(scenario)
58
67
  visit_scenario(scenario)
59
68
  end
60
69
 
61
70
  def visit_regular_scenario(scenario)
71
+ @regular_scenario_cache[scenario.name] = scenario
62
72
  visit_scenario(scenario)
63
73
  end
64
74
 
65
75
  def visit_scenario(scenario)
66
- if accept?(scenario)
67
- @error = nil
68
- @pending = nil
69
-
70
- @world = @world_proc.call
71
- @world.extend(Spec::Matchers) if defined?(Spec::Matchers)
72
- define_step_call_methods(@world)
73
-
74
- formatter.scenario_executing(scenario) if formatter.respond_to?(:scenario_executing)
75
- @before_scenario_procs.each{|p| p.call_in(@world, *[])}
76
- scenario.accept(self)
77
- @after_scenario_procs.each{|p| p.call_in(@world, *[])}
78
- formatter.scenario_executed(scenario) if formatter.respond_to?(:scenario_executed)
76
+ if accept_scenario?(scenario)
77
+ @executed_scenarios[scenario.name] = true
78
+ execute_scenario(scenario)
79
79
  end
80
80
  end
81
+
82
+ def execute_scenario(scenario)
83
+ @error = nil
84
+ @pending = nil
85
+
86
+ @world = @world_proc.call
87
+ @world.extend(Spec::Matchers) if defined?(Spec::Matchers)
88
+ define_step_call_methods(@world)
89
+
90
+ formatters.scenario_executing(scenario)
91
+ @before_scenario_procs.each{|p| p.call_in(@world, *[])}
92
+ scenario.accept(self)
93
+ @after_scenario_procs.each{|p| p.call_in(@world, *[])}
94
+ formatters.scenario_executed(scenario)
95
+ end
81
96
 
82
- def accept?(scenario)
83
- @line.nil? || scenario.at_line?(@line)
97
+ def accept_scenario?(scenario)
98
+ accept = true
99
+ accept &&= scenario.at_line?(@line) if @line
100
+ accept &&= @scenario_names.include? scenario.name if @scenario_names && !@scenario_names.empty?
101
+ accept
102
+ end
103
+
104
+ def accept_feature?(feature)
105
+ feature.scenarios.any? { |s| accept_scenario?(s) }
84
106
  end
85
107
 
86
108
  def visit_row_step(step)
@@ -95,33 +117,33 @@ module Cucumber
95
117
  unless @pending || @error
96
118
  begin
97
119
  regexp, args, proc = step.regexp_args_proc(@step_mother)
98
- formatter.step_executing(step, regexp, args) if formatter.respond_to?(:step_executing)
120
+ formatters.step_executing(step, regexp, args)
99
121
  step.execute_in(@world, regexp, args, proc)
100
122
  @after_step_procs.each{|p| p.call_in(@world, *[])}
101
- formatter.step_passed(step, regexp, args)
123
+ formatters.step_passed(step, regexp, args)
102
124
  rescue Pending
103
125
  record_pending_step(step, regexp, args)
104
126
  rescue => e
105
127
  @failed = true
106
128
  @error = step.error = e
107
- formatter.step_failed(step, regexp, args)
129
+ formatters.step_failed(step, regexp, args)
108
130
  end
109
131
  else
110
132
  begin
111
133
  regexp, args, proc = step.regexp_args_proc(@step_mother)
112
134
  step.execute_in(@world, regexp, args, proc)
113
- formatter.step_skipped(step, regexp, args)
135
+ formatters.step_skipped(step, regexp, args)
114
136
  rescue Pending
115
137
  record_pending_step(step, regexp, args)
116
138
  rescue Exception
117
- formatter.step_skipped(step, regexp, args)
139
+ formatters.step_skipped(step, regexp, args)
118
140
  end
119
141
  end
120
142
  end
121
-
143
+
122
144
  def record_pending_step(step, regexp, args)
123
145
  @pending = true
124
- formatter.step_pending(step, regexp, args)
146
+ formatters.step_pending(step, regexp, args)
125
147
  end
126
148
 
127
149
  def define_step_call_methods(world)
@@ -139,5 +161,10 @@ module Cucumber
139
161
  end
140
162
  end
141
163
  end
164
+
165
+ def executing_unprepared_row_scenario?(scenario)
166
+ accept_scenario?(scenario) && !@executed_scenarios[scenario.name]
167
+ end
168
+
142
169
  end
143
- end
170
+ end
@@ -1 +1 @@
1
- %w{html pretty progress profile}.each{|n| require "cucumber/formatters/#{n}_formatter"}
1
+ %w{html pretty progress profile autotest}.each{|n| require "cucumber/formatters/#{n}_formatter"}
@@ -91,17 +91,16 @@ module Cucumber
91
91
 
92
92
  #Not supported in Term::ANSIColor
93
93
  def grey(m)
94
- if ENV['CUCUMBER_COLORS_DISABLED'] == '1'
95
- m
96
- else
94
+ if ::Term::ANSIColor.coloring?
97
95
  "\e[90m#{m}\e[0m"
96
+ else
97
+ m
98
98
  end
99
99
  end
100
100
 
101
101
  ALIASES.each do |m, color_string|
102
102
  colors = color_string.split(",").reverse
103
103
  define_method(m) do |*s|
104
- ::Term::ANSIColor.coloring = false if ENV['CUCUMBER_COLORS_DISABLED'] == '1'
105
104
  clear + colors.inject(s[0]) do |memo, color|
106
105
  s[0].nil? ? __send__(color) + memo.to_s : __send__(color, memo.to_s)
107
106
  end
@@ -0,0 +1,23 @@
1
+ require 'cucumber/formatters/ansicolor'
2
+
3
+ module Cucumber
4
+ module Formatters
5
+ class AutotestFormatter
6
+ def initialize(io)
7
+ @io = io
8
+ @failed_scenarios = []
9
+ end
10
+
11
+ def step_didnt_pass(step, regexp, args)
12
+ unless @failed_scenarios.include? step.scenario.name
13
+ @failed_scenarios << step.scenario.name
14
+ @io.puts step.scenario.name
15
+ end
16
+ end
17
+
18
+ alias step_failed step_didnt_pass
19
+ alias step_pending step_didnt_pass
20
+ alias step_skipped step_didnt_pass
21
+ end
22
+ end
23
+ end
@@ -7,21 +7,23 @@ module Cucumber
7
7
 
8
8
  INDENT = "\n "
9
9
  BACKTRACE_FILTER_PATTERNS = [/vendor\/rails/, /vendor\/plugins\/cucumber/, /spec\/expectations/, /spec\/matchers/]
10
-
10
+
11
11
  def initialize(io, step_mother, options={})
12
12
  @io = (io == STDOUT) ? Kernel : io
13
13
  @options = options
14
14
  @step_mother = step_mother
15
- @passed = []
16
- @failed = []
17
- @pending = []
18
- @skipped = []
15
+ @pending_scenarios = []
16
+ @passed = []
17
+ @failed = []
18
+ @pending_steps = []
19
+ @skipped = []
20
+ @last_executed_was_row = false
19
21
  end
20
-
21
- def visit_feature(feature)
22
+
23
+ def feature_executing(feature)
22
24
  @feature = feature
23
25
  end
24
-
26
+
25
27
  def header_executing(header)
26
28
  @io.puts if @feature_newline
27
29
  @feature_newline = true
@@ -31,18 +33,27 @@ module Cucumber
31
33
  @io.print line
32
34
  if @options[:source] && index==0
33
35
  @io.print padding_spaces(@feature)
34
- @io.print comment("# #{@feature.file}")
36
+ @io.print comment("# #{@feature.file}")
35
37
  end
36
38
  @io.puts
37
39
  end
38
40
  end
39
-
41
+
40
42
  def scenario_executing(scenario)
41
43
  @scenario_failed = false
44
+ @io.puts if @last_executed_was_row && !scenario.row?
42
45
  if scenario.row?
46
+ @last_executed_was_row = true
43
47
  @io.print " |"
44
48
  else
45
- @io.print passed(" #{Cucumber.language['scenario']}: #{scenario.name}")
49
+ if scenario.pending?
50
+ @pending_scenarios << scenario
51
+ @io.print pending(" #{Cucumber.language['scenario']}: #{scenario.name}")
52
+ else
53
+ @io.print passed(" #{Cucumber.language['scenario']}: #{scenario.name}")
54
+ end
55
+ @last_executed_was_row = false
56
+
46
57
  if @options[:source]
47
58
  @io.print padding_spaces(scenario)
48
59
  @io.print comment("# #{scenario.file}:#{scenario.line}")
@@ -54,57 +65,59 @@ module Cucumber
54
65
  def scenario_executed(scenario)
55
66
  @io.puts
56
67
  if !scenario.row? && scenario.table_header
68
+ @table_column_widths = scenario.table_column_widths
69
+ @current_column = -1
57
70
  @io.print " |"
58
- scenario.table_header.each { |h| @io.print h ; @io.print "|" }
71
+ print_row(scenario.table_header)
59
72
  @io.puts
60
73
  elsif scenario.row? && @scenario_failed
61
74
  @io.puts
62
- output_failing_step(@failed.last)
75
+ output_failing_step(@failed.last)
63
76
  end
64
77
  end
65
-
78
+
66
79
  def step_passed(step, regexp, args)
67
80
  if step.row?
68
81
  @passed << step
69
- args.each{|arg| @io.print passed(arg) ; @io.print "|"}
82
+ print_passed_args(args)
70
83
  else
71
84
  @passed << step
72
85
  @io.print passed(" #{step.keyword} #{step.format(regexp){|param| passed_param(param) << passed}}")
73
86
  if @options[:source]
74
87
  @io.print padding_spaces(step)
75
- @io.print source_comment(step)
88
+ @io.print source_comment(step)
76
89
  end
77
90
  @io.puts
78
91
  end
79
92
  end
80
-
93
+
81
94
  def step_failed(step, regexp, args)
82
95
  if step.row?
83
96
  @failed << step
84
97
  @scenario_failed = true
85
- args.each{|arg| @io.print failed(arg) ; @io.print "|"}
98
+ print_failed_args(args)
86
99
  else
87
100
  @failed << step
88
101
  @scenario_failed = true
89
- @io.print failed(" #{step.keyword} #{step.format(regexp){|param| failed_param(param) << failed}}")
102
+ @io.print failed(" #{step.keyword} #{step.format(regexp){|param| failed_param(param) << failed}}")
90
103
  if @options[:source]
91
104
  @io.print padding_spaces(step)
92
- @io.print source_comment(step)
105
+ @io.print source_comment(step)
93
106
  end
94
107
  @io.puts
95
108
  output_failing_step(step)
96
109
  end
97
110
  end
98
-
111
+
99
112
  def step_skipped(step, regexp, args)
100
113
  @skipped << step
101
114
  if step.row?
102
- args.each{|arg| @io.print skipped(arg) ; @io.print "|"}
115
+ print_skipped_args(args)
103
116
  else
104
- @io.print skipped(" #{step.keyword} #{step.format(regexp){|param| skipped_param(param) << skipped}}")
117
+ @io.print skipped(" #{step.keyword} #{step.format(regexp){|param| skipped_param(param) << skipped}}")
105
118
  if @options[:source]
106
119
  @io.print padding_spaces(step)
107
- @io.print source_comment(step)
120
+ @io.print source_comment(step)
108
121
  end
109
122
  @io.puts
110
123
  end
@@ -112,10 +125,10 @@ module Cucumber
112
125
 
113
126
  def step_pending(step, regexp, args)
114
127
  if step.row?
115
- @pending << step
116
- args.each{|arg| @io.print pending(arg) ; @io.print "|"}
128
+ @pending_steps << step
129
+ print_pending_args(args)
117
130
  else
118
- @pending << step
131
+ @pending_steps << step
119
132
  @io.print pending(" #{step.keyword} #{step.name}")
120
133
  if @options[:source]
121
134
  @io.print padding_spaces(step)
@@ -124,7 +137,7 @@ module Cucumber
124
137
  @io.puts
125
138
  end
126
139
  end
127
-
140
+
128
141
  def output_failing_step(step)
129
142
  backtrace = step.error.backtrace || []
130
143
  clean_backtrace = backtrace.map {|b| b.split("\n") }.flatten.reject do |line|
@@ -136,42 +149,86 @@ module Cucumber
136
149
 
137
150
  def dump
138
151
  @io.puts
139
- @io.puts passed("#{@passed.length} steps passed") unless @passed.empty?
140
- @io.puts failed("#{@failed.length} steps failed") unless @failed.empty?
141
- @io.puts skipped("#{@skipped.length} steps skipped") unless @skipped.empty?
142
- @io.puts pending("#{@pending.length} steps pending") unless @pending.empty?
152
+
153
+ @io.puts pending("#{@pending_scenarios.length} scenarios pending") if @pending_scenarios.any?
154
+
155
+ @io.puts passed("#{@passed.length} steps passed") if @passed.any?
156
+ @io.puts failed("#{@failed.length} steps failed") if @failed.any?
157
+ @io.puts skipped("#{@skipped.length} steps skipped") if @skipped.any?
158
+ @io.puts pending("#{@pending_steps.length} steps pending") if @pending_steps.any?
159
+
143
160
  @io.print reset
144
- print_snippets
161
+
162
+ print_snippets if @options[:snippets]
145
163
  end
146
-
164
+
147
165
  def print_snippets
148
- unless @pending.empty?
166
+ snippets = @pending_steps
167
+ snippets.delete_if {|snippet| snippet.row? || @step_mother.has_step_definition?(snippet.name)}
168
+
169
+ unless snippets.empty?
149
170
  @io.puts "\nYou can use these snippets to implement pending steps:\n\n"
150
-
171
+
151
172
  prev_keyword = nil
152
- snippets = @pending.map do |step|
153
- next if step.row?
154
- snippet = "#{step.actual_keyword} /^#{step.name}$/ do\nend\n\n"
173
+ snippets = snippets.map do |step|
174
+ snippet = "#{step.actual_keyword} /^#{escape_regexp_characters(step.name)}$/ do\nend\n\n"
155
175
  prev_keyword = step.keyword
156
176
  snippet
157
177
  end.compact.uniq
158
-
178
+
159
179
  snippets.each do |snippet|
160
180
  @io.puts snippet
161
181
  end
162
182
  end
163
183
  end
164
-
184
+
165
185
  private
166
186
 
187
+ def escape_regexp_characters(string)
188
+ Regexp.escape(string).gsub('\ ', ' ').gsub('/', '\/') unless string.nil?
189
+ end
190
+
167
191
  def source_comment(step)
168
192
  _, _, proc = step.regexp_args_proc(@step_mother)
169
193
  comment(proc.to_comment_line)
170
194
  end
171
-
195
+
172
196
  def padding_spaces(tree_item)
173
197
  " " * tree_item.padding_length
174
198
  end
199
+
200
+ def next_column_index
201
+ @current_column ||= -1
202
+ @current_column += 1
203
+ @current_column = 0 if @current_column >= @table_column_widths.size
204
+ @current_column
205
+ end
206
+
207
+ def print_row row_args, &colorize_proc
208
+ colorize_proc = Proc.new{|row_element| row_element} unless colorize_proc
209
+
210
+ row_args.each do |row_arg|
211
+ column_index = next_column_index
212
+ @io.print colorize_proc[row_arg.ljust(@table_column_widths[column_index])]
213
+ @io.print "|"
214
+ end
215
+ end
216
+
217
+ def print_passed_args args
218
+ print_row(args) {|arg| passed(arg)}
219
+ end
220
+
221
+ def print_skipped_args args
222
+ print_row(args) {|arg| skipped(arg)}
223
+ end
224
+
225
+ def print_failed_args args
226
+ print_row(args) {|arg| failed(arg)}
227
+ end
228
+
229
+ def print_pending_args args
230
+ print_row(args) {|arg| pending(arg)}
231
+ end
175
232
  end
176
233
  end
177
234
  end