aslakhellesoy-cucumber 0.1.16.4 → 0.1.16.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/History.txt +75 -1
  2. data/Manifest.txt +58 -65
  3. data/examples/cs/features/step_definitons/calculator_steps.rb +1 -1
  4. data/examples/i18n/Rakefile +3 -3
  5. data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +1 -6
  6. data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +1 -1
  7. data/examples/i18n/de/features/addition.feature +6 -6
  8. data/examples/i18n/de/features/step_definitons/calculator_steps.rb +2 -2
  9. data/examples/i18n/en/features/addition.feature +6 -6
  10. data/examples/i18n/en/features/step_definitons/calculator_steps.rb +2 -2
  11. data/examples/i18n/es/features/step_definitons/calculador_steps.rb +1 -1
  12. data/examples/i18n/et/features/liitmine.feature +7 -6
  13. data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +1 -1
  14. data/examples/i18n/fi/features/step_definitons/laskin_steps.rb +1 -1
  15. data/examples/i18n/fi/features/yhteenlasku.feature +2 -2
  16. data/examples/i18n/fr/features/addition.feature +2 -2
  17. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
  18. data/examples/i18n/id/features/addition.feature +6 -6
  19. data/examples/i18n/id/features/step_definitons/calculator_steps.rb +2 -2
  20. data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +1 -1
  21. data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +2 -3
  22. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
  23. data/examples/i18n/lt/features/addition.feature +7 -6
  24. data/examples/i18n/lt/features/step_definitons/calculator_steps.rb +2 -2
  25. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +7 -7
  26. data/examples/i18n/no/features/summering.feature +1 -0
  27. data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +1 -1
  28. data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +1 -1
  29. data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +1 -1
  30. data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +2 -2
  31. data/examples/jbehave/README.textile +17 -0
  32. data/examples/jbehave/features/support/env.rb +7 -0
  33. data/examples/jbehave/features/trading.feature +24 -0
  34. data/examples/jbehave/pom.xml +48 -0
  35. data/examples/self_test/README.textile +4 -1
  36. data/examples/self_test/features/call_undefined_step_from_step_def.feature +7 -0
  37. data/examples/self_test/features/lots_of_undefined.feature +8 -0
  38. data/examples/self_test/features/outline_sample.feature +8 -5
  39. data/examples/self_test/features/sample.feature +5 -3
  40. data/examples/self_test/features/step_definitions/sample_steps.rb +15 -3
  41. data/features/cucumber_cli.feature +199 -97
  42. data/features/cucumber_cli_outlines.feature +46 -38
  43. data/features/report_called_undefined_steps.feature +31 -0
  44. data/features/step_definitions/cucumber_steps.rb +7 -3
  45. data/features/step_definitions/extra_steps.rb +1 -1
  46. data/features/support/env.rb +1 -1
  47. data/gem_tasks/features.rake +1 -1
  48. data/gem_tasks/flog.rake +1 -1
  49. data/lib/autotest/cucumber_mixin.rb +16 -23
  50. data/lib/cucumber/ast/comment.rb +26 -0
  51. data/lib/cucumber/ast/examples.rb +22 -0
  52. data/lib/cucumber/ast/feature.rb +60 -0
  53. data/lib/cucumber/ast/features.rb +39 -0
  54. data/lib/cucumber/ast/filter.rb +22 -0
  55. data/lib/cucumber/ast/outline_table.rb +49 -0
  56. data/lib/cucumber/ast/py_string.rb +52 -0
  57. data/lib/cucumber/ast/scenario.rb +91 -0
  58. data/lib/cucumber/ast/scenario_outline.rb +83 -0
  59. data/lib/cucumber/ast/step.rb +130 -0
  60. data/lib/cucumber/ast/table.rb +214 -0
  61. data/lib/cucumber/ast/tags.rb +33 -0
  62. data/lib/cucumber/ast/visitor.rb +93 -0
  63. data/lib/cucumber/ast.rb +27 -0
  64. data/lib/cucumber/broadcaster.rb +1 -6
  65. data/lib/cucumber/cli.rb +178 -128
  66. data/lib/cucumber/core_ext/exception.rb +41 -8
  67. data/lib/cucumber/core_ext/instance_exec.rb +54 -0
  68. data/lib/cucumber/core_ext/proc.rb +29 -65
  69. data/lib/cucumber/core_ext/string.rb +19 -0
  70. data/lib/cucumber/{formatters → formatter}/ansicolor.rb +11 -10
  71. data/lib/cucumber/formatter/console.rb +116 -0
  72. data/lib/cucumber/formatter/pretty.rb +158 -0
  73. data/lib/cucumber/formatter/profile.rb +77 -0
  74. data/lib/cucumber/formatter/progress.rb +68 -0
  75. data/lib/cucumber/formatter.rb +1 -0
  76. data/lib/cucumber/formatters/autotest_formatter.rb +0 -2
  77. data/lib/cucumber/formatters/html_formatter.rb +4 -3
  78. data/lib/cucumber/formatters/pretty_formatter.rb +1 -1
  79. data/lib/cucumber/formatters/unicode.rb +3 -3
  80. data/lib/cucumber/jbehave.rb +104 -0
  81. data/lib/cucumber/languages.yml +100 -73
  82. data/lib/cucumber/parser/basic.rb +0 -0
  83. data/lib/cucumber/parser/feature.rb +1694 -0
  84. data/lib/cucumber/parser/feature.tt +206 -0
  85. data/lib/cucumber/parser/file_parser.rb +50 -0
  86. data/lib/cucumber/parser/i18n.tt +26 -0
  87. data/lib/cucumber/parser/treetop_ext.rb +9 -0
  88. data/lib/cucumber/parser.rb +27 -0
  89. data/lib/cucumber/platform.rb +3 -17
  90. data/lib/cucumber/step_definition.rb +83 -0
  91. data/lib/cucumber/step_mother.rb +128 -72
  92. data/lib/cucumber/version.rb +1 -1
  93. data/lib/cucumber.rb +56 -9
  94. data/spec/cucumber/ast/feature_factory.rb +54 -0
  95. data/spec/cucumber/ast/feature_spec.rb +60 -0
  96. data/spec/cucumber/ast/py_string_spec.rb +40 -0
  97. data/spec/cucumber/ast/scenario_outline_spec.rb +64 -0
  98. data/spec/cucumber/ast/scenario_spec.rb +82 -0
  99. data/spec/cucumber/ast/step_spec.rb +45 -0
  100. data/spec/cucumber/ast/table_spec.rb +81 -0
  101. data/spec/cucumber/broadcaster_spec.rb +4 -17
  102. data/spec/cucumber/cli_spec.rb +43 -148
  103. data/spec/cucumber/core_ext/proc_spec.rb +27 -35
  104. data/spec/cucumber/core_ext/string_spec.rb +8 -0
  105. data/spec/cucumber/{formatters → formatter}/ansicolor_spec.rb +2 -2
  106. data/spec/cucumber/formatter/html/cucumber.css +37 -0
  107. data/spec/cucumber/formatter/html/cucumber.js +11 -0
  108. data/spec/cucumber/formatter/html/index.html +45 -0
  109. data/spec/cucumber/formatter/html/jquery-1.3.min.js +19 -0
  110. data/spec/cucumber/formatter/html/jquery.uitableedit.js +100 -0
  111. data/spec/cucumber/formatters/autotest_formatter_spec.rb +1 -0
  112. data/spec/cucumber/formatters/profile_formatter_spec.rb +17 -16
  113. data/spec/cucumber/parser/feature_parser_spec.rb +247 -0
  114. data/spec/cucumber/parser/table_parser_spec.rb +48 -0
  115. data/spec/cucumber/step_definition_spec.rb +62 -0
  116. data/spec/cucumber/step_mom_spec.rb +49 -0
  117. data/spec/cucumber/treetop_parser/empty_feature.feature +1 -1
  118. data/spec/cucumber/treetop_parser/spaces.feature +3 -1
  119. data/spec/cucumber/treetop_parser/with_comments.feature +1 -1
  120. data/spec/cucumber/treetop_parser/with_tags.feature +18 -0
  121. data/spec/cucumber/world/pending_spec.rb +13 -12
  122. data/spec/spec_helper.rb +1 -1
  123. metadata +59 -67
  124. data/examples/calculator_ruby_features/Rakefile +0 -6
  125. data/examples/calculator_ruby_features/features/addition.rb +0 -39
  126. data/examples/calculator_ruby_features/features/step_definitons/calculator_steps.rb +0 -43
  127. data/gem_tasks/treetop.rake +0 -41
  128. data/lib/cucumber/executor.rb +0 -205
  129. data/lib/cucumber/formatters/profile_formatter.rb +0 -92
  130. data/lib/cucumber/formatters/progress_formatter.rb +0 -61
  131. data/lib/cucumber/formatters.rb +0 -1
  132. data/lib/cucumber/model/table.rb +0 -32
  133. data/lib/cucumber/model.rb +0 -1
  134. data/lib/cucumber/step_methods.rb +0 -49
  135. data/lib/cucumber/tree/feature.rb +0 -105
  136. data/lib/cucumber/tree/features.rb +0 -21
  137. data/lib/cucumber/tree/given_scenario.rb +0 -13
  138. data/lib/cucumber/tree/scenario.rb +0 -240
  139. data/lib/cucumber/tree/step.rb +0 -173
  140. data/lib/cucumber/tree/table.rb +0 -26
  141. data/lib/cucumber/tree/top_down_visitor.rb +0 -23
  142. data/lib/cucumber/tree.rb +0 -16
  143. data/lib/cucumber/treetop_parser/feature.treetop.erb +0 -254
  144. data/lib/cucumber/treetop_parser/feature_ar.rb +0 -1951
  145. data/lib/cucumber/treetop_parser/feature_cy.rb +0 -1951
  146. data/lib/cucumber/treetop_parser/feature_da.rb +0 -1951
  147. data/lib/cucumber/treetop_parser/feature_de.rb +0 -1951
  148. data/lib/cucumber/treetop_parser/feature_en-lol.rb +0 -1951
  149. data/lib/cucumber/treetop_parser/feature_en-tx.rb +0 -1951
  150. data/lib/cucumber/treetop_parser/feature_en.rb +0 -1951
  151. data/lib/cucumber/treetop_parser/feature_es.rb +0 -1951
  152. data/lib/cucumber/treetop_parser/feature_et.rb +0 -1951
  153. data/lib/cucumber/treetop_parser/feature_fr.rb +0 -1951
  154. data/lib/cucumber/treetop_parser/feature_id.rb +0 -1951
  155. data/lib/cucumber/treetop_parser/feature_it.rb +0 -1951
  156. data/lib/cucumber/treetop_parser/feature_ja.rb +0 -1951
  157. data/lib/cucumber/treetop_parser/feature_ko.rb +0 -1951
  158. data/lib/cucumber/treetop_parser/feature_lt.rb +0 -1951
  159. data/lib/cucumber/treetop_parser/feature_nl.rb +0 -1951
  160. data/lib/cucumber/treetop_parser/feature_no.rb +0 -1951
  161. data/lib/cucumber/treetop_parser/feature_parser.rb +0 -36
  162. data/lib/cucumber/treetop_parser/feature_pl.rb +0 -1951
  163. data/lib/cucumber/treetop_parser/feature_pt.rb +0 -1951
  164. data/lib/cucumber/treetop_parser/feature_ro.rb +0 -1951
  165. data/lib/cucumber/treetop_parser/feature_ro2.rb +0 -1951
  166. data/lib/cucumber/treetop_parser/feature_ru.rb +0 -1951
  167. data/lib/cucumber/treetop_parser/feature_se.rb +0 -1951
  168. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +0 -1951
  169. data/lib/cucumber/world/pending.rb +0 -22
  170. data/lib/cucumber/world.rb +0 -1
  171. data/setup.rb +0 -1585
  172. data/spec/cucumber/executor_spec.rb +0 -382
  173. data/spec/cucumber/formatters/html_formatter_spec.rb +0 -104
  174. data/spec/cucumber/formatters/pretty_formatter_spec.rb +0 -410
  175. data/spec/cucumber/formatters/progress_formatter_spec.rb +0 -81
  176. data/spec/cucumber/model/table_spec.rb +0 -32
  177. data/spec/cucumber/step_mother_spec.rb +0 -74
  178. data/spec/cucumber/tree/feature_spec.rb +0 -122
  179. data/spec/cucumber/tree/row_scenario_outline_spec.rb +0 -73
  180. data/spec/cucumber/tree/row_scenario_spec.rb +0 -55
  181. data/spec/cucumber/tree/row_step_outline_spec.rb +0 -38
  182. data/spec/cucumber/tree/scenario_outline_spec.rb +0 -50
  183. data/spec/cucumber/tree/scenario_spec.rb +0 -134
  184. data/spec/cucumber/tree/step_outline_spec.rb +0 -17
  185. data/spec/cucumber/tree/step_spec.rb +0 -59
  186. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +0 -120
@@ -1,69 +1,33 @@
1
- module Cucumber
2
- class ArityMismatchError < StandardError
3
- end
4
-
5
- module CoreExt
6
- # Proc extension that allows a proc to be called in the context of any object.
7
- # Also makes it possible to tack a name onto a Proc.
8
- module CallIn
9
- PROC_PATTERN = /[\d\w]+@(.*):(.*)>/
10
-
11
- if Proc.new{}.to_s =~ PROC_PATTERN
12
- def to_backtrace_line
13
- "#{file_colon_line}:in `#{name}'"
14
- end
15
-
16
- def to_comment_line
17
- "# #{file_colon_line}"
18
- end
19
-
20
- def file_colon_line
21
- path, line = *to_s.match(PROC_PATTERN)[1..2]
22
- path = File.expand_path(path)
23
- pwd = Dir.pwd
24
- path = path[pwd.length+1..-1]
25
- "#{path}:#{line}"
26
- end
27
- else
28
- # This Ruby implementation doesn't implement Proc#to_s correctly
29
- STDERR.puts "*** THIS RUBY IMPLEMENTATION DOESN'T REPORT FILE AND LINE FOR PROCS ***"
30
-
31
- def to_backtrace_line
32
- nil
33
- end
34
-
35
- def to_comment_line
36
- ""
37
- end
38
- end
39
-
40
- attr_accessor :name
41
-
42
- def call_in(obj, *args)
43
- obj.extend(mod)
44
- if self != StepMother::PENDING && args.length != arity2
45
- # We have to manually raise when the block has arity -1 (no pipes)
46
- raise ArityMismatchError.new("expected #{arity2} block argument(s), got #{args.length}")
47
- else
48
- obj.__send__(meth, *args)
49
- end
50
- end
1
+ # Proc extension to get more location info out of a proc
2
+ class Proc
3
+ PROC_PATTERN = /[\d\w]+@(.*):(.*)>/
4
+
5
+ if Proc.new{}.to_s =~ PROC_PATTERN
6
+ def to_backtrace_line(name)
7
+ "#{file_colon_line}:in `#{name}'"
8
+ end
51
9
 
52
- def arity2
53
- arity == -1 ? 0 : arity
54
- end
10
+ def to_comment_line
11
+ "# #{file_colon_line}"
12
+ end
55
13
 
56
- def meth
57
- @meth ||= "__cucumber_#{object_id}"
58
- end
14
+ def file_colon_line
15
+ path, line = *to_s.match(PROC_PATTERN)[1..2]
16
+ path = File.expand_path(path)
17
+ pwd = Dir.pwd
18
+ path = path[pwd.length+1..-1]
19
+ "#{path}:#{line}"
20
+ end
21
+ else
22
+ # This Ruby implementation doesn't implement Proc#to_s correctly
23
+ STDERR.puts "*** THIS RUBY IMPLEMENTATION DOESN'T REPORT FILE AND LINE FOR PROCS ***"
24
+
25
+ def to_backtrace_line
26
+ nil
27
+ end
59
28
 
60
- def mod
61
- p = self
62
- m = meth
63
- @mod ||= Module.new do
64
- define_method(m, &p)
65
- end
66
- end
67
- end
29
+ def to_comment_line
30
+ ""
31
+ end
68
32
  end
69
- end
33
+ end
@@ -1,4 +1,21 @@
1
1
  class String
2
+ def indent(n)
3
+ if n >= 0
4
+ gsub(/^/, ' ' * n)
5
+ else
6
+ gsub(/^ {0,#{-n}}/, "")
7
+ end
8
+ end
9
+
10
+ # re.source.gsub(/\([^)]*\)/, '$var')
11
+ # Cumulative #sub
12
+ def subs(re, *args)
13
+ args.inject(self) do |s,arg|
14
+ s.sub(re, arg)
15
+ end
16
+ end
17
+
18
+ # TODO: Use subs instead...
2
19
  def gzub(regexp, format=nil, &proc)
3
20
  md = match(regexp)
4
21
  raise "#{self.inspect} doesn't match #{regexp.inspect}" if md.nil?
@@ -8,6 +25,8 @@ class String
8
25
  md.captures.each_with_index do |m, n|
9
26
  replacement = if block_given?
10
27
  proc.call(m)
28
+ elsif Proc === format
29
+ format.call(m)
11
30
  else
12
31
  format % m
13
32
  end
@@ -17,7 +17,7 @@ end
17
17
  Term::ANSIColor.coloring = false if !STDOUT.tty? || (Cucumber::WINDOWS && !Cucumber::WINDOWS_MRI)
18
18
 
19
19
  module Cucumber
20
- module Formatters
20
+ module Formatter
21
21
  # Defines aliases for coloured output. You can tweak the colours by defining
22
22
  # a <tt>CUCUMBER_COLORS</tt> variable in your shell, very much like you can
23
23
  # tweak the familiar POSIX command <tt>ls</tt> with
@@ -25,7 +25,7 @@ module Cucumber
25
25
  #
26
26
  # The colours that you can change are:
27
27
  #
28
- # * <tt>missing</tt> - defaults to <tt>yellow</tt>
28
+ # * <tt>undefined</tt> - defaults to <tt>yellow</tt>
29
29
  # * <tt>pending</tt> - defaults to <tt>yellow</tt>
30
30
  # * <tt>pending_param</tt> - defaults to <tt>yellow,bold</tt>
31
31
  # * <tt>failed</tt> - defaults to <tt>red</tt>
@@ -69,14 +69,15 @@ module Cucumber
69
69
  h[$1] + ',bold'
70
70
  end
71
71
  end.merge({
72
- 'missing' => 'yellow',
73
- 'pending' => 'yellow',
74
- 'failed' => 'red',
75
- 'passed' => 'green',
76
- 'outline' => 'cyan',
77
- 'skipped' => 'cyan',
78
- 'comment' => 'grey',
79
- 'tag' => 'blue'
72
+ 'undefined' => 'yellow',
73
+ 'pending' => 'yellow',
74
+ 'failed' => 'red',
75
+ 'passed' => 'green',
76
+ 'thead' => 'cyan',
77
+ 'outline' => 'cyan',
78
+ 'skipped' => 'cyan',
79
+ 'comment' => 'grey',
80
+ 'tag' => 'blue'
80
81
  })
81
82
 
82
83
  if ENV['CUCUMBER_COLORS'] # Example: export CUCUMBER_COLORS="passed=red:failed=yellow"
@@ -0,0 +1,116 @@
1
+ require 'cucumber/formatter/ansicolor'
2
+
3
+ module Cucumber
4
+ module Formatter
5
+ module Console
6
+ extend ANSIColor
7
+ FORMATS = Hash.new{|hash, format| hash[format] = method(format).to_proc}
8
+
9
+ def format_step(keyword, step_name, status, step_definition, source_indent)
10
+ line = if step_definition # nil for :outline
11
+ comment = if source_indent
12
+ c = (' # ' + step_definition.file_colon_line).indent(source_indent)
13
+ format_string(c, :comment)
14
+ else
15
+ ''
16
+ end
17
+ keyword + " " + step_definition.format_args(step_name, format_for(status, :param)) + comment
18
+ else
19
+ keyword + " " + step_name
20
+ end
21
+ format_string(line, status)
22
+ end
23
+
24
+ def format_string(string, status)
25
+ fmt = format_for(status)
26
+ if Proc === fmt
27
+ fmt.call(string)
28
+ else
29
+ fmt % string
30
+ end
31
+ end
32
+
33
+ def print_undefined_scenarios(features)
34
+ elements = features.scenarios.select{|scenario| scenario.undefined?}
35
+ print_elements(elements, :undefined, 'scenarios')
36
+ end
37
+
38
+ def print_steps(features, status)
39
+ print_elements(features.steps[status], status, 'steps')
40
+ end
41
+
42
+ def print_elements(elements, status, kind)
43
+ if elements.any?
44
+ @io.puts(format_string("(::) #{status} #{kind} (::)", status))
45
+ @io.puts
46
+ @io.flush
47
+ end
48
+
49
+ elements.each_with_index do |element, i|
50
+ if status == :failed
51
+ print_exception(element.exception, 0)
52
+ else
53
+ @io.puts(format_string(element.backtrace_line, status))
54
+ end
55
+ @io.puts
56
+ @io.flush
57
+ end
58
+ end
59
+
60
+ def print_counts(features)
61
+ @io.puts dump_count(features.scenarios.length, "scenario")
62
+
63
+ [:failed, :skipped, :undefined, :pending, :passed].each do |status|
64
+ if features.steps[status].any?
65
+ count_string = dump_count(features.steps[status].length, "step", status.to_s)
66
+ @io.puts format_string(count_string, status)
67
+ @io.flush
68
+ end
69
+ end
70
+ end
71
+
72
+ def print_exception(e, indent)
73
+ status = Cucumber::EXCEPTION_STATUS[e.class]
74
+ @io.puts(format_string("#{e.message} (#{e.class})\n#{e.backtrace.join("\n")}".indent(indent), status))
75
+ end
76
+
77
+ def print_snippets(features, options)
78
+ return unless options[:snippets]
79
+ undefined = features.steps[:undefined]
80
+ return if undefined.empty?
81
+ snippets = undefined.map do |step|
82
+ step_name = StepMother::Undefined === step.exception ? step.exception.step_name : step.name
83
+ snippet = @step_mother.snippet_text(step.actual_keyword, step_name)
84
+ snippet
85
+ end.compact.uniq
86
+
87
+ text = "\nYou can implement step definitions for missing steps with these snippets:\n\n"
88
+ text += snippets.join("\n\n")
89
+
90
+ @io.puts format_string(text, :undefined)
91
+ @io.puts
92
+ @io.flush
93
+ end
94
+
95
+ private
96
+
97
+ def with_color
98
+ c = Term::ANSIColor.coloring?
99
+ Term::ANSIColor.coloring = @io.tty?
100
+ yield
101
+ Term::ANSIColor.coloring = c
102
+ end
103
+
104
+ def dump_count(count, what, state=nil)
105
+ [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(" ")
106
+ end
107
+
108
+ def format_for(*keys)
109
+ key = keys.join('_').to_sym
110
+ fmt = FORMATS[key]
111
+ raise "No format for #{key.inspect}: #{FORMATS.inspect}" if fmt.nil?
112
+ fmt
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,158 @@
1
+ require 'cucumber/formatter/console'
2
+ require 'fileutils'
3
+
4
+ module Cucumber
5
+ module Formatter
6
+ # This formatter prints features to plain text - exactly how they were parsed,
7
+ # just prettier. That means with proper indentation and alignment of table columns.
8
+ #
9
+ # If the output is STDOUT (and not a file), there are bright colours to watch too.
10
+ #
11
+ class Pretty < Ast::Visitor
12
+ include FileUtils
13
+ include Console
14
+ attr_writer :indent
15
+
16
+ def initialize(step_mother, io, options, delim='|')
17
+ super(step_mother)
18
+ @io = io
19
+ @options = options
20
+ @delim = delim
21
+ end
22
+
23
+ def visit_features(features)
24
+ super
25
+ print_summary(features) unless @options[:autoformat]
26
+ end
27
+
28
+ def visit_feature(feature)
29
+ @indent = 0
30
+ if @options[:autoformat]
31
+ file = File.join(@options[:autoformat], feature.file)
32
+ dir = File.dirname(file)
33
+ mkdir_p(dir) unless File.directory?(dir)
34
+ File.open(file, Cucumber.file_mode('w')) do |io|
35
+ @io = io
36
+ with_color do
37
+ feature.accept(self)
38
+ end
39
+ end
40
+ else
41
+ with_color do
42
+ feature.accept(self)
43
+ end
44
+ end
45
+ end
46
+
47
+ def visit_comment(comment)
48
+ comment.accept(self)
49
+ end
50
+
51
+ def visit_comment_line(comment_line)
52
+ unless comment_line.blank?
53
+ @io.puts(comment_line.indent(@indent))
54
+ @io.flush
55
+ end
56
+ end
57
+
58
+ def visit_tags(tags)
59
+ tags.accept(self)
60
+ if @indent == 1
61
+ @io.puts
62
+ @io.flush
63
+ end
64
+ end
65
+
66
+ def visit_tag_name(tag_name)
67
+ tag = format_string("@#{tag_name}", :tag).indent(@indent)
68
+ @io.print(tag)
69
+ @io.flush
70
+ @indent = 1
71
+ end
72
+
73
+ def visit_feature_name(name)
74
+ @io.puts(name)
75
+ @io.puts
76
+ @io.flush
77
+ end
78
+
79
+ def visit_feature_element(feature_element)
80
+ @indent = 2
81
+ @last_undefined = feature_element.undefined?
82
+ feature_element.accept(self)
83
+ @io.puts
84
+ @io.flush
85
+ end
86
+
87
+ def visit_examples(examples)
88
+ examples.accept(self)
89
+ end
90
+
91
+ def visit_examples_name(keyword, name)
92
+ @io.puts("\n #{keyword} #{name}")
93
+ @io.flush
94
+ @indent = 4
95
+ end
96
+
97
+ def visit_scenario_name(keyword, name, file_line, source_indent)
98
+ line = " #{keyword} #{name}"
99
+ line = format_string(line, :undefined) if @last_undefined
100
+ @io.print(line)
101
+ if @options[:source]
102
+ line_comment = " # #{file_line}".indent(source_indent)
103
+ @io.print(format_string(line_comment, :comment))
104
+ end
105
+ @io.puts
106
+ @io.flush
107
+ end
108
+
109
+ def visit_step(step)
110
+ @indent = 6
111
+ exception = step.accept(self)
112
+ print_exception(exception, @indent) if exception
113
+ end
114
+
115
+ def visit_step_name(keyword, step_name, status, step_definition, source_indent)
116
+ source_indent = nil unless @options[:source]
117
+ formatted_step_name = format_step(keyword, step_name, status, step_definition, source_indent)
118
+ @io.puts(" " + formatted_step_name)
119
+ @io.flush
120
+ end
121
+
122
+ def visit_multiline_arg(multiline_arg, status)
123
+ multiline_arg.accept(self, status)
124
+ end
125
+
126
+ def visit_table_row(table_row, status)
127
+ @io.print @delim.indent(@indent)
128
+ exception = table_row.accept(self, status)
129
+ @io.puts
130
+ print_exception(exception, 6) if exception
131
+ end
132
+
133
+ def visit_py_string(string, status)
134
+ s = "\"\"\"\n#{string}\n\"\"\"".indent(@indent)
135
+ s = s.split("\n").map{|l| l =~ /^\s+$/ ? '' : l}.join("\n")
136
+ @io.puts(format_string(s, status))
137
+ @io.flush
138
+ end
139
+
140
+ def visit_table_cell(table_cell, status)
141
+ table_cell.accept(self, status)
142
+ end
143
+
144
+ def visit_table_cell_value(value, width, status)
145
+ @io.print(' ' + format_string((value || '').ljust(width), status) + " #{@delim}")
146
+ @io.flush
147
+ end
148
+
149
+ private
150
+
151
+ def print_summary(features)
152
+ print_counts(features)
153
+ print_snippets(features, @options)
154
+ end
155
+
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,77 @@
1
+ require 'cucumber/formatter/progress'
2
+
3
+ module Cucumber
4
+ module Formatter
5
+ class Profile < Progress
6
+ NUMBER_OF_STEP_DEFINITONS_TO_SHOW = 10
7
+ NUMBER_OF_STEP_INVOCATIONS_TO_SHOW = 5
8
+
9
+ def initialize(step_mother, io, options)
10
+ super
11
+ @step_definition_durations = Hash.new { |h,step_definition| h[step_definition] = [] }
12
+ end
13
+
14
+ def visit_step(step)
15
+ @step_duration = Time.now
16
+ @step = step
17
+ super
18
+ end
19
+
20
+ def visit_step_name(keyword, step_name, status, step_definition, source_indent)
21
+ duration = Time.now - @step_duration
22
+ super
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]
27
+ end
28
+ end
29
+
30
+ def print_summary(features)
31
+ super
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
+
34
+ mean_durations = map_to_mean_durations(@step_definition_durations)
35
+ mean_durations = mean_durations.sort_by do |duration_description_location, step_definition, mean_duration|
36
+ mean_duration
37
+ end.reverse
38
+
39
+ mean_durations[0...NUMBER_OF_STEP_DEFINITONS_TO_SHOW].each do |duration_description_location, step_definition, mean_duration|
40
+ print_step_definition(step_definition, mean_duration)
41
+ duration_description_location = duration_description_location.sort_by do |duration, description, location|
42
+ duration
43
+ end.reverse
44
+ print_step_definitions(duration_description_location, step_definition)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def map_to_mean_durations(step_definition_durations)
51
+ mean_durations = []
52
+ step_definition_durations.each do |step_definition, duration_description_location|
53
+ total_duration = duration_description_location.inject(0) { |sum, step_details| step_details[0] + sum }
54
+ mean_duration = total_duration / duration_description_location.length
55
+
56
+ mean_durations << [duration_description_location, step_definition, mean_duration]
57
+ end
58
+ mean_durations
59
+ end
60
+
61
+ def print_step_definition(step_definition, mean_duration)
62
+ duration = sprintf("%.7f", mean_duration)
63
+ @io.puts format_string("#{duration} #{step_definition.to_backtrace_line}", :failed)
64
+ end
65
+
66
+ def print_step_definitions(duration_description_location, step_definition)
67
+ max_length = duration_description_location[0...NUMBER_OF_STEP_INVOCATIONS_TO_SHOW].map{|_, d, _| d.jlength}.max
68
+ duration_description_location[0...NUMBER_OF_STEP_INVOCATIONS_TO_SHOW].each do |duration, description, location|
69
+ @io.print format_string(" #{sprintf("%.7f", duration)}", :pending)
70
+ @io.print " #{description}"
71
+ @io.print format_string(" # #{location}".indent(max_length - description.jlength), :comment)
72
+ @io.puts
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,68 @@
1
+ require 'cucumber/formatter/console'
2
+
3
+ module Cucumber
4
+ module Formatter
5
+ class Progress < Ast::Visitor
6
+ include Console
7
+
8
+ def initialize(step_mother, io, options)
9
+ super(step_mother)
10
+ @io = io
11
+ @options = options
12
+ end
13
+
14
+ def visit_features(features)
15
+ with_color do
16
+ super
17
+ @io.puts
18
+ @io.puts
19
+ print_summary(features)
20
+ end
21
+ end
22
+
23
+ def visit_multiline_arg(multiline_arg, status)
24
+ @multiline_arg = true
25
+ super
26
+ @multiline_arg = false
27
+ end
28
+
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)
35
+ progress(status) unless status == :outline
36
+ end
37
+
38
+ def visit_table_cell_value(value, width, status)
39
+ progress(status) if (status != :thead) && !@multiline_arg
40
+ end
41
+
42
+ private
43
+
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)
50
+ end
51
+
52
+ CHARS = {
53
+ :passed => '.',
54
+ :failed => 'F',
55
+ :undefined => 'U',
56
+ :pending => 'P',
57
+ :skipped => 'S'
58
+ }
59
+
60
+ def progress(status)
61
+ char = CHARS[status]
62
+ @io.print(format_string(char, status))
63
+ @io.flush
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1 @@
1
+ %w{pretty progress profile rerun}.each{|n| require "cucumber/formatter/#{n}"}
@@ -1,5 +1,3 @@
1
- require 'cucumber/formatters/ansicolor'
2
-
3
1
  module Cucumber
4
2
  module Formatters
5
3
  class AutotestFormatter
@@ -55,16 +55,16 @@ HTML
55
55
  end
56
56
 
57
57
  def visit_regular_scenario(scenario)
58
- visit_scenario(scenario, Cucumber.language['scenario'])
58
+ visit_scenario(scenario, Cucumber.keywords['scenario'])
59
59
  end
60
60
 
61
61
  def visit_scenario_outline(scenario)
62
- visit_scenario(scenario, Cucumber.language['scenario_outline'])
62
+ visit_scenario(scenario, Cucumber.keywords['scenario_outline'])
63
63
  end
64
64
 
65
65
  def visit_row_scenario(scenario)
66
66
  @io.puts %{ <dl class="new">}
67
- @io.puts %{ <dt>#{Cucumber.language['scenario']}: #{scenario.name}</dt>}
67
+ @io.puts %{ <dt>#{Cucumber.keywords['scenario']}: #{scenario.name}</dt>}
68
68
  @io.puts %{ <dd>}
69
69
  @io.puts %{ <table cellpadding="3">}
70
70
  @io.puts %{ <thead>}
@@ -130,6 +130,7 @@ HTML
130
130
  </body>
131
131
  </html>
132
132
  HTML
133
+ @io.flush
133
134
  end
134
135
 
135
136
  private
@@ -170,7 +170,7 @@ module Cucumber
170
170
 
171
171
  def output_failing_step(step)
172
172
  @io.puts failed(" #{step.error.message.split("\n").join(INDENT)} (#{step.error.class})")
173
- @io.puts failed(" #{step.error.cucumber_backtrace.join(INDENT)}")
173
+ @io.puts failed(" #{step.error.backtrace.join(INDENT)}")
174
174
  end
175
175
 
176
176
  def dump
@@ -1,6 +1,6 @@
1
1
  # Require this file if you need Unicode support.
2
2
  require 'cucumber/platform'
3
- require 'cucumber/formatters/ansicolor'
3
+ require 'cucumber/formatter/ansicolor'
4
4
 
5
5
  $KCODE='u' unless Cucumber::RUBY_1_9
6
6
 
@@ -16,7 +16,7 @@ if Cucumber::WINDOWS_MRI && `chcp` =~ /Active code page: (\d+)/
16
16
  alias cucumber_print print
17
17
  def print(*a)
18
18
  begin
19
- cucumber_print *Iconv.iconv(Cucumber::CODEPAGE, "UTF-8", *a)
19
+ cucumber_print(*Iconv.iconv(Cucumber::CODEPAGE, "UTF-8", *a))
20
20
  rescue Iconv::IllegalSequence
21
21
  cucumber_print(*a)
22
22
  end
@@ -25,7 +25,7 @@ if Cucumber::WINDOWS_MRI && `chcp` =~ /Active code page: (\d+)/
25
25
  alias cucumber_puts puts
26
26
  def puts(*a)
27
27
  begin
28
- cucumber_puts *Iconv.iconv(Cucumber::CODEPAGE, "UTF-8", *a)
28
+ cucumber_puts(*Iconv.iconv(Cucumber::CODEPAGE, "UTF-8", *a))
29
29
  rescue Iconv::IllegalSequence
30
30
  cucumber_puts(*a)
31
31
  end