aslakhellesoy-cucumber 0.1.99.23 → 0.1.100.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/History.txt +2 -6
  2. data/Manifest.txt +8 -2
  3. data/examples/i18n/et/features/jagamine.feature +9 -0
  4. data/examples/jbehave/README.textile +4 -1
  5. data/examples/jbehave/features/trading.feature +4 -0
  6. data/examples/jbehave/pom.xml +5 -0
  7. data/examples/jbehave/src/main/java/cukes/jbehave/examples/trader/scenarios/TraderSteps.java +6 -1
  8. data/examples/selenium/features/step_definitons/search_steps.rb +13 -0
  9. data/examples/selenium/features/support/env.rb +19 -0
  10. data/examples/selenium_webrat/Rakefile +6 -0
  11. data/examples/selenium_webrat/features/search.feature +9 -0
  12. data/examples/selenium_webrat/features/step_definitons/search_steps.rb +13 -0
  13. data/examples/selenium_webrat/features/support/env.rb +41 -0
  14. data/examples/self_test/features/background/failing_background.feature +1 -0
  15. data/examples/self_test/features/step_definitions/sample_steps.rb +1 -1
  16. data/examples/self_test/features/support/tag_count_formatter.rb +1 -1
  17. data/features/background.feature +9 -11
  18. data/features/cucumber_cli.feature +24 -1
  19. data/features/cucumber_cli_outlines.feature +10 -19
  20. data/features/report_called_undefined_steps.feature +2 -0
  21. data/gem_tasks/rspec.rake +2 -0
  22. data/lib/cucumber.rb +7 -15
  23. data/lib/cucumber/ast.rb +3 -3
  24. data/lib/cucumber/ast/background.rb +28 -66
  25. data/lib/cucumber/ast/examples.rb +15 -3
  26. data/lib/cucumber/ast/feature.rb +20 -24
  27. data/lib/cucumber/ast/feature_element.rb +46 -0
  28. data/lib/cucumber/ast/features.rb +2 -21
  29. data/lib/cucumber/ast/outline_table.rb +46 -14
  30. data/lib/cucumber/ast/py_string.rb +8 -3
  31. data/lib/cucumber/ast/scenario.rb +34 -73
  32. data/lib/cucumber/ast/scenario_outline.rb +40 -42
  33. data/lib/cucumber/ast/step.rb +53 -89
  34. data/lib/cucumber/ast/step_collection.rb +66 -0
  35. data/lib/cucumber/ast/step_invocation.rb +106 -0
  36. data/lib/cucumber/ast/table.rb +38 -19
  37. data/lib/cucumber/ast/tags.rb +4 -11
  38. data/lib/cucumber/ast/visitor.rb +31 -19
  39. data/lib/cucumber/broadcaster.rb +1 -1
  40. data/lib/cucumber/cli/configuration.rb +24 -16
  41. data/lib/cucumber/cli/language_help_formatter.rb +4 -4
  42. data/lib/cucumber/cli/main.rb +5 -4
  43. data/lib/cucumber/core_ext/proc.rb +2 -2
  44. data/lib/cucumber/formatter/ansicolor.rb +0 -1
  45. data/lib/cucumber/formatter/console.rb +18 -34
  46. data/lib/cucumber/formatter/html.rb +13 -10
  47. data/lib/cucumber/formatter/pretty.rb +48 -36
  48. data/lib/cucumber/formatter/profile.rb +6 -6
  49. data/lib/cucumber/formatter/progress.rb +12 -20
  50. data/lib/cucumber/formatter/rerun.rb +5 -5
  51. data/lib/cucumber/jbehave.rb +21 -26
  52. data/lib/cucumber/parser/feature.rb +26 -29
  53. data/lib/cucumber/parser/feature.tt +17 -12
  54. data/lib/cucumber/parser/treetop_ext.rb +13 -13
  55. data/lib/cucumber/platform.rb +0 -1
  56. data/lib/cucumber/rails/world.rb +2 -2
  57. data/lib/cucumber/rake/task.rb +0 -1
  58. data/lib/cucumber/step_definition.rb +21 -12
  59. data/lib/cucumber/step_match.rb +49 -0
  60. data/lib/cucumber/step_mother.rb +98 -80
  61. data/lib/cucumber/version.rb +2 -2
  62. data/lib/cucumber/world.rb +42 -0
  63. data/rails_generators/cucumber/templates/paths.rb +1 -1
  64. data/rails_generators/cucumber/templates/webrat_steps.rb +17 -17
  65. data/rails_generators/feature/feature_generator.rb +4 -0
  66. data/rails_generators/feature/templates/steps.erb +0 -4
  67. data/spec/cucumber/ast/background_spec.rb +32 -41
  68. data/spec/cucumber/ast/feature_factory.rb +10 -1
  69. data/spec/cucumber/ast/feature_spec.rb +7 -30
  70. data/spec/cucumber/ast/scenario_outline_spec.rb +3 -0
  71. data/spec/cucumber/ast/scenario_spec.rb +8 -25
  72. data/spec/cucumber/ast/step_collection_spec.rb +8 -0
  73. data/spec/cucumber/ast/step_spec.rb +37 -29
  74. data/spec/cucumber/ast/tags_spec.rb +2 -18
  75. data/spec/cucumber/cli/configuration_spec.rb +7 -0
  76. data/spec/cucumber/cli/main_spec.rb +1 -1
  77. data/spec/cucumber/parser/feature_parser_spec.rb +6 -5
  78. data/spec/cucumber/step_definition_spec.rb +5 -5
  79. data/spec/cucumber/step_mother_spec.rb +6 -6
  80. data/spec/cucumber/world/pending_spec.rb +1 -1
  81. metadata +17 -5
  82. data/lib/cucumber/ast/filter.rb +0 -22
  83. data/lib/cucumber/ast/steps.rb +0 -13
@@ -18,7 +18,7 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
18
18
  [lang, Cucumber::LANGUAGES[lang]['name'], Cucumber::LANGUAGES[lang]['native']]
19
19
  end
20
20
  table = Ast::Table.new(raw)
21
- new(nil, io, {:check_lang=>true}, '').visit_multiline_arg(table, :passed)
21
+ new(nil, io, {:check_lang=>true}, '').visit_multiline_arg(table)
22
22
  end
23
23
 
24
24
  def self.list_keywords(io, lang)
@@ -26,17 +26,17 @@ http://wiki.github.com/aslakhellesoy/cucumber/spoken-languages
26
26
  [key, Cucumber::LANGUAGES[lang][key]]
27
27
  end
28
28
  table = Ast::Table.new(raw)
29
- new(nil, io, {:incomplete => Cucumber.language_incomplete?(lang)}, '').visit_multiline_arg(table, :passed)
29
+ new(nil, io, {:incomplete => Cucumber.language_incomplete?(lang)}, '').visit_multiline_arg(table)
30
30
  end
31
31
 
32
- def visit_multiline_arg(table, status)
32
+ def visit_multiline_arg(table)
33
33
  if @options[:incomplete]
34
34
  @io.puts(format_string(INCOMPLETE, :failed))
35
35
  end
36
36
  super
37
37
  end
38
38
 
39
- def visit_table_row(table_row, status)
39
+ def visit_table_row(table_row)
40
40
  @col = 1
41
41
  super
42
42
  end
@@ -45,8 +45,10 @@ module Cucumber
45
45
 
46
46
  visitor = configuration.build_formatter_broadcaster(step_mother)
47
47
  visitor.visit_features(features)
48
-
49
- failure = features.steps[:failed].any? || (configuration.strict? && features.steps[:undefined].any?)
48
+
49
+ failure = step_mother.steps(:failed).any? ||
50
+ (configuration.strict? && step_mother.steps(:undefined).any?)
51
+
50
52
  Kernel.exit(failure ? 1 : 0)
51
53
  end
52
54
 
@@ -75,8 +77,7 @@ module Cucumber
75
77
  end
76
78
 
77
79
  def load_plain_text_features
78
- filter = configuration.ast_filter
79
- features = Ast::Features.new(filter)
80
+ features = Ast::Features.new
80
81
  parser = Parser::FeatureParser.new
81
82
 
82
83
  verbose_log("Features:")
@@ -3,7 +3,7 @@ class Proc
3
3
  PROC_PATTERN = /[\d\w]+@(.*):(.*)>/
4
4
 
5
5
  if Proc.new{}.to_s =~ PROC_PATTERN
6
- def to_backtrace_line(name)
6
+ def backtrace_line(name)
7
7
  "#{file_colon_line}:in `#{name}'"
8
8
  end
9
9
 
@@ -22,7 +22,7 @@ class Proc
22
22
  # This Ruby implementation doesn't implement Proc#to_s correctly
23
23
  STDERR.puts "*** THIS RUBY IMPLEMENTATION DOESN'T REPORT FILE AND LINE FOR PROCS ***"
24
24
 
25
- def to_backtrace_line
25
+ def backtrace_line
26
26
  nil
27
27
  end
28
28
 
@@ -70,7 +70,6 @@ module Cucumber
70
70
  'pending' => 'yellow',
71
71
  'failed' => 'red',
72
72
  'passed' => 'green',
73
- 'thead' => 'cyan',
74
73
  'outline' => 'cyan',
75
74
  'skipped' => 'cyan',
76
75
  'comment' => 'grey',
@@ -6,21 +6,16 @@ module Cucumber
6
6
  extend ANSIColor
7
7
  FORMATS = Hash.new{|hash, format| hash[format] = method(format).to_proc}
8
8
 
9
- def format_step(keyword, step_name, status, step_definition, source_indent)
10
- comment = if source_indent && step_definition
11
- c = (' # ' + step_definition.file_colon_line).indent(source_indent)
9
+ def format_step(keyword, step_match, status, source_indent)
10
+ comment = if source_indent
11
+ c = (' # ' + step_match.file_colon_line).indent(source_indent)
12
12
  format_string(c, :comment)
13
13
  else
14
14
  ''
15
15
  end
16
16
 
17
- begin
18
- line = keyword + " " + step_definition.format_args(step_name, format_for(status, :param)) + comment
19
- rescue
20
- # It didn't match. This often happens for :outline steps
21
- line = keyword + " " + step_name + comment
22
- end
23
-
17
+ format = format_for(status, :param)
18
+ line = keyword + " " + step_match.format_args(format) + comment
24
19
  format_string(line, status)
25
20
  end
26
21
 
@@ -33,13 +28,8 @@ module Cucumber
33
28
  end
34
29
  end
35
30
 
36
- def print_undefined_scenarios(features)
37
- elements = features.scenarios.select{|scenario| scenario.undefined?}
38
- print_elements(elements, :undefined, 'scenarios')
39
- end
40
-
41
- def print_steps(features, status)
42
- print_elements(features.steps[status], status, 'steps')
31
+ def print_steps(status)
32
+ print_elements(step_mother.steps(status), status, 'steps')
43
33
  end
44
34
 
45
35
  def print_elements(elements, status, kind)
@@ -51,7 +41,7 @@ module Cucumber
51
41
 
52
42
  elements.each_with_index do |element, i|
53
43
  if status == :failed
54
- print_exception(element.exception, 0)
44
+ print_exception(element.exception, status, 0)
55
45
  else
56
46
  @io.puts(format_string(element.backtrace_line, status))
57
47
  end
@@ -60,26 +50,27 @@ module Cucumber
60
50
  end
61
51
  end
62
52
 
63
- def print_counts(features)
64
- @io.puts dump_count(features.scenarios.length, "scenario")
53
+ def print_counts
54
+ @io.puts dump_count(step_mother.scenarios.length, "scenario")
65
55
 
66
56
  [:failed, :skipped, :undefined, :pending, :passed].each do |status|
67
- if features.steps[status].any?
68
- count_string = dump_count(features.steps[status].length, "step", status.to_s)
57
+ if step_mother.steps(status).any?
58
+ count_string = dump_count(step_mother.steps(status).length, "step", status.to_s)
69
59
  @io.puts format_string(count_string, status)
70
60
  @io.flush
71
61
  end
72
62
  end
73
63
  end
74
64
 
75
- def print_exception(e, indent)
76
- status = Cucumber::EXCEPTION_STATUS[e.class]
77
- @io.puts(format_string("#{e.message} (#{e.class})\n#{e.backtrace.join("\n")}".indent(indent), status))
65
+ def print_exception(e, status, indent)
66
+ if @options[:strict] || !(Undefined === e) || e.nested?
67
+ @io.puts(format_string("#{e.message} (#{e.class})\n#{e.backtrace.join("\n")}".indent(indent), status))
68
+ end
78
69
  end
79
70
 
80
- def print_snippets(features, options)
71
+ def print_snippets(options)
81
72
  return unless options[:snippets]
82
- undefined = features.steps[:undefined]
73
+ undefined = step_mother.steps(:undefined)
83
74
  return if undefined.empty?
84
75
  snippets = undefined.map do |step|
85
76
  step_name = Undefined === step.exception ? step.exception.step_name : step.name
@@ -97,13 +88,6 @@ module Cucumber
97
88
 
98
89
  private
99
90
 
100
- def with_color
101
- c = Term::ANSIColor.coloring?
102
- Term::ANSIColor.coloring = @io.tty?
103
- yield
104
- Term::ANSIColor.coloring = c
105
- end
106
-
107
91
  def dump_count(count, what, state=nil)
108
92
  [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(" ")
109
93
  end
@@ -54,12 +54,14 @@ module Cucumber
54
54
 
55
55
  def visit_background(background)
56
56
  @builder.div(:class => 'background') do
57
- @builder.ol do
58
- super
59
- end
57
+ super
60
58
  end
61
59
  end
62
60
 
61
+ def visit_background_name(keyword, name, file_colon_line, source_indent)
62
+ @builder.h3("#{keyword} #{name}")
63
+ end
64
+
63
65
  def visit_feature_element(feature_element)
64
66
  @builder.div(:class => 'scenario') do
65
67
  super
@@ -67,7 +69,7 @@ module Cucumber
67
69
  @open_step_list = true
68
70
  end
69
71
 
70
- def visit_scenario_name(keyword, name, file_line, source_indent)
72
+ def visit_scenario_name(keyword, name, file_colon_line, source_indent)
71
73
  @builder.h3("#{keyword} #{name}")
72
74
  end
73
75
 
@@ -87,25 +89,26 @@ module Cucumber
87
89
  end
88
90
  end
89
91
 
90
- def visit_step_name(keyword, step_name, status, step_definition, source_indent)
92
+ def visit_step_name(keyword, step_match, status, source_indent, background)
93
+ step_name = step_match.format_args(lambda{|param| "<span>#{param}</span>"})
91
94
  @builder.li("#{keyword} #{step_name}", :class => status)
92
95
  end
93
96
 
94
- def visit_multiline_arg(multiline_arg, status)
97
+ def visit_multiline_arg(multiline_arg)
95
98
  if Ast::Table === multiline_arg
96
99
  @builder.table do
97
- super(multiline_arg, status)
100
+ super
98
101
  end
99
102
  else
100
103
  @builder.p do
101
- super(multiline_arg, status)
104
+ super
102
105
  end
103
106
  end
104
107
  end
105
108
 
106
- def visit_table_row(table_row, status)
109
+ def visit_table_row(table_row)
107
110
  @builder.tr do
108
- super(table_row, status)
111
+ super
109
112
  end
110
113
  end
111
114
 
@@ -23,7 +23,7 @@ module Cucumber
23
23
 
24
24
  def visit_features(features)
25
25
  super
26
- print_summary(features) unless @options[:autoformat]
26
+ print_summary unless @options[:autoformat]
27
27
  end
28
28
 
29
29
  def visit_feature(feature)
@@ -34,14 +34,10 @@ module Cucumber
34
34
  mkdir_p(dir) unless File.directory?(dir)
35
35
  File.open(file, Cucumber.file_mode('w')) do |io|
36
36
  @io = io
37
- with_color do
38
- feature.accept(self)
39
- end
37
+ super
40
38
  end
41
39
  else
42
- with_color do
43
- feature.accept(self)
44
- end
40
+ super
45
41
  end
46
42
  end
47
43
 
@@ -79,21 +75,22 @@ module Cucumber
79
75
 
80
76
  def visit_feature_element(feature_element)
81
77
  @indent = 2
82
- @last_undefined = feature_element.undefined?
83
- feature_element.accept(self)
78
+ super
84
79
  @io.puts
85
80
  @io.flush
86
81
  end
87
82
 
88
- def visit_background(background)
83
+ def visit_background(background)
89
84
  @indent = 2
90
- background_already_visible = background.already_visited_steps?
91
- background.accept(self)
92
- @io.puts unless background_already_visible
85
+ @in_background = true
86
+ super
87
+ @in_background = nil
88
+ @io.puts
89
+ @io.flush
93
90
  end
94
91
 
95
- def visit_examples(examples)
96
- examples.accept(self)
92
+ def visit_background_name(keyword, name, file_colon_line, source_indent)
93
+ visit_feature_element_name(keyword, name, file_colon_line, source_indent)
97
94
  end
98
95
 
99
96
  def visit_examples_name(keyword, name)
@@ -102,12 +99,15 @@ module Cucumber
102
99
  @indent = 4
103
100
  end
104
101
 
105
- def visit_scenario_name(keyword, name, file_line, source_indent)
102
+ def visit_scenario_name(keyword, name, file_colon_line, source_indent)
103
+ visit_feature_element_name(keyword, name, file_colon_line, source_indent)
104
+ end
105
+
106
+ def visit_feature_element_name(keyword, name, file_colon_line, source_indent)
106
107
  line = " #{keyword} #{name}"
107
- line = format_string(line, :undefined) if @last_undefined
108
108
  @io.print(line)
109
109
  if @options[:source]
110
- line_comment = " # #{file_line}".indent(source_indent)
110
+ line_comment = " # #{file_colon_line}".indent(source_indent)
111
111
  @io.print(format_string(line_comment, :comment))
112
112
  end
113
113
  @io.puts
@@ -116,27 +116,39 @@ module Cucumber
116
116
 
117
117
  def visit_step(step)
118
118
  @indent = 6
119
- exception = step.accept(self)
120
- print_exception(exception, @indent) if exception
119
+ super
121
120
  end
122
121
 
123
- def visit_step_name(keyword, step_name, status, step_definition, source_indent)
124
- source_indent = nil unless @options[:source]
125
- formatted_step_name = format_step(keyword, step_name, status, step_definition, source_indent)
126
- @io.puts(" " + formatted_step_name)
127
- @io.flush
122
+ def visit_step_name(keyword, step_match, status, source_indent, background)
123
+ @step_matches ||= []
124
+
125
+ non_failed_background_step_outside_background = !@in_background && background && (status != :failed)
126
+ @skip_step = @step_matches.index(step_match) || non_failed_background_step_outside_background
127
+
128
+ unless(@skip_step)
129
+ source_indent = nil unless @options[:source]
130
+ formatted_step_name = format_step(keyword, step_match, status, source_indent)
131
+ @io.puts(" " + formatted_step_name)
132
+ end
133
+ @step_matches << step_match
134
+ end
135
+
136
+ def visit_multiline_arg(multiline_arg)
137
+ return if @options[:no_multiline] || @skip_step
138
+ super
128
139
  end
129
140
 
130
- def visit_multiline_arg(multiline_arg, status)
131
- return if @options[:no_multiline]
132
- multiline_arg.accept(self, status)
141
+ def visit_exception(exception, status)
142
+ return if @skip_step
143
+ print_exception(exception, status, @indent)
144
+ @io.flush
133
145
  end
134
146
 
135
- def visit_table_row(table_row, status)
147
+ def visit_table_row(table_row)
136
148
  @io.print @delim.indent(@indent)
137
- exception = table_row.accept(self, status)
149
+ super
138
150
  @io.puts
139
- print_exception(exception, 6) if exception
151
+ print_exception(table_row.exception, :failed, @indent) if table_row.exception
140
152
  end
141
153
 
142
154
  def visit_py_string(string, status)
@@ -146,8 +158,8 @@ module Cucumber
146
158
  @io.flush
147
159
  end
148
160
 
149
- def visit_table_cell(table_cell, status)
150
- table_cell.accept(self, status)
161
+ def visit_table_cell(table_cell)
162
+ super
151
163
  end
152
164
 
153
165
  def visit_table_cell_value(value, width, status)
@@ -157,9 +169,9 @@ module Cucumber
157
169
 
158
170
  private
159
171
 
160
- def print_summary(features)
161
- print_counts(features)
162
- print_snippets(features, @options)
172
+ def print_summary
173
+ print_counts
174
+ print_snippets(@options)
163
175
  end
164
176
 
165
177
  end
@@ -17,17 +17,17 @@ module Cucumber
17
17
  super
18
18
  end
19
19
 
20
- def visit_step_name(keyword, step_name, status, step_definition, source_indent)
20
+ def visit_step_name(keyword, step_match, status, source_indent, background)
21
21
  duration = Time.now - @step_duration
22
22
  super
23
23
 
24
- if step_definition # nil for outline steps
25
- description = format_step(keyword, step_name, status, step_definition, nil)
26
- @step_definition_durations[step_definition] << [duration, description, @step.file_line]
24
+ if step_match.step_definition
25
+ description = format_step(keyword, step_match, status, nil)
26
+ @step_definition_durations[step_match.step_definition] << [duration, description, @step.file_colon_line]
27
27
  end
28
28
  end
29
29
 
30
- def print_summary(features)
30
+ def print_summary
31
31
  super
32
32
  @io.puts "\n\nTop #{NUMBER_OF_STEP_DEFINITONS_TO_SHOW} average slowest steps with #{NUMBER_OF_STEP_INVOCATIONS_TO_SHOW} slowest matches:\n"
33
33
 
@@ -60,7 +60,7 @@ module Cucumber
60
60
 
61
61
  def print_step_definition(step_definition, mean_duration)
62
62
  duration = sprintf("%.7f", mean_duration)
63
- @io.puts format_string("#{duration} #{step_definition.to_backtrace_line}", :failed)
63
+ @io.puts format_string("#{duration} #{step_definition.backtrace_line}", :failed)
64
64
  end
65
65
 
66
66
  def print_step_definitions(duration_description_location, step_definition)
@@ -12,26 +12,19 @@ module Cucumber
12
12
  end
13
13
 
14
14
  def visit_features(features)
15
- with_color do
16
- super
17
- @io.puts
18
- @io.puts
19
- print_summary(features)
20
- end
15
+ super
16
+ @io.puts
17
+ @io.puts
18
+ print_summary
21
19
  end
22
20
 
23
- def visit_multiline_arg(multiline_arg, status)
21
+ def visit_multiline_arg(multiline_arg)
24
22
  @multiline_arg = true
25
23
  super
26
24
  @multiline_arg = false
27
25
  end
28
26
 
29
- def visit_feature_element(feature_element)
30
- progress(:undefined) if feature_element.undefined?
31
- super
32
- end
33
-
34
- def visit_step_name(keyword, step_name, status, step_definition, source_indent)
27
+ def visit_step_name(keyword, step_match, status, source_indent, background)
35
28
  progress(status) unless status == :outline
36
29
  end
37
30
 
@@ -41,12 +34,11 @@ module Cucumber
41
34
 
42
35
  private
43
36
 
44
- def print_summary(features)
45
- print_undefined_scenarios(features)
46
- print_steps(features, :pending)
47
- print_steps(features, :failed)
48
- print_counts(features)
49
- print_snippets(features, @options)
37
+ def print_summary
38
+ print_steps(:pending)
39
+ print_steps(:failed)
40
+ print_counts
41
+ print_snippets(@options)
50
42
  end
51
43
 
52
44
  CHARS = {
@@ -54,7 +46,7 @@ module Cucumber
54
46
  :failed => 'F',
55
47
  :undefined => 'U',
56
48
  :pending => 'P',
57
- :skipped => 'S'
49
+ :skipped => '-'
58
50
  }
59
51
 
60
52
  def progress(status)