cucumber 0.1.6

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.
Files changed (153) hide show
  1. data/History.txt +3 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +152 -0
  4. data/README.txt +42 -0
  5. data/Rakefile +4 -0
  6. data/TODO.txt +26 -0
  7. data/bin/cucumber +4 -0
  8. data/config/hoe.rb +69 -0
  9. data/config/requirements.rb +15 -0
  10. data/cucumber.yml +1 -0
  11. data/examples/calculator/Rakefile +6 -0
  12. data/examples/calculator/cucumber.yml +1 -0
  13. data/examples/calculator/features/addition.feature +16 -0
  14. data/examples/calculator/features/division.feature +10 -0
  15. data/examples/calculator/features/steps/calculator_steps.rb +31 -0
  16. data/examples/calculator/lib/calculator.rb +16 -0
  17. data/examples/calculator_ruby_features/Rakefile +6 -0
  18. data/examples/calculator_ruby_features/features/addition.rb +23 -0
  19. data/examples/calculator_ruby_features/features/steps/calculator_steps.rb +43 -0
  20. data/examples/calculatrice_francaise_avec_soit_scenario/Rakefile +6 -0
  21. data/examples/calculatrice_francaise_avec_soit_scenario/features/addition.feature +13 -0
  22. data/examples/calculatrice_francaise_avec_soit_scenario/features/calculatrice_steps.rb +31 -0
  23. data/examples/cs/README.textile +22 -0
  24. data/examples/cs/Rakefile +12 -0
  25. data/examples/cs/features/hello.feature +11 -0
  26. data/examples/cs/features/steps/hello_steps.rb +25 -0
  27. data/examples/cs/features/steps/tree_steps.rb +14 -0
  28. data/examples/cs/features/tree.feature +9 -0
  29. data/examples/cs/src/Hello.cs +18 -0
  30. data/examples/danish_calculator/Rakefile +6 -0
  31. data/examples/danish_calculator/features/steps/kalkulator_steps.rb +22 -0
  32. data/examples/danish_calculator/features/summering.feature +17 -0
  33. data/examples/danish_calculator/lib/kalkulator.rb +11 -0
  34. data/examples/estonian_calculator/Rakefile +6 -0
  35. data/examples/estonian_calculator/features/kalkulaator_steps.rb +35 -0
  36. data/examples/estonian_calculator/features/liitmine.feature +16 -0
  37. data/examples/java/README.textile +22 -0
  38. data/examples/java/Rakefile +12 -0
  39. data/examples/java/features/hello.feature +11 -0
  40. data/examples/java/features/steps/hello_steps.rb +25 -0
  41. data/examples/java/features/steps/tree_steps.rb +14 -0
  42. data/examples/java/features/tree.feature +9 -0
  43. data/examples/java/src/cucumber/demo/Hello.java +16 -0
  44. data/examples/norwegian_calculator/Rakefile +6 -0
  45. data/examples/norwegian_calculator/features/steps/kalkulator_steps.rb +22 -0
  46. data/examples/norwegian_calculator/features/summering.feature +17 -0
  47. data/examples/norwegian_calculator/lib/kalkulator.rb +11 -0
  48. data/examples/portuguese_calculator/Rakefile +6 -0
  49. data/examples/portuguese_calculator/features/adicao.feature +10 -0
  50. data/examples/portuguese_calculator/features/calculadora_steps.rb +31 -0
  51. data/examples/selenium/Rakefile +6 -0
  52. data/examples/selenium/features/search.feature +9 -0
  53. data/examples/selenium/features/steps/stories_steps.rb +41 -0
  54. data/examples/spanish_calculator/Rakefile +6 -0
  55. data/examples/spanish_calculator/features/adicion.feature +17 -0
  56. data/examples/spanish_calculator/features/steps/calculador_steps.rb +22 -0
  57. data/examples/spanish_calculator/lib/Calculador.rb +11 -0
  58. data/examples/tickets/Rakefile +4 -0
  59. data/examples/tickets/features/steps/tickets_steps.rb +5 -0
  60. data/examples/tickets/features/tickets.feature +7 -0
  61. data/examples/watir/Rakefile +6 -0
  62. data/examples/watir/features/search.feature +9 -0
  63. data/examples/watir/features/steps/stories_steps.rb +51 -0
  64. data/features/see_features.feature +8 -0
  65. data/features/steps/features_steps.rb +9 -0
  66. data/gem_tasks/deployment.rake +34 -0
  67. data/gem_tasks/environment.rake +7 -0
  68. data/gem_tasks/features.rake +6 -0
  69. data/gem_tasks/fix_cr_lf.rake +10 -0
  70. data/gem_tasks/flog.rake +4 -0
  71. data/gem_tasks/gemspec.rake +6 -0
  72. data/gem_tasks/rspec.rake +21 -0
  73. data/gem_tasks/treetop.rake +27 -0
  74. data/generators/cucumber/cucumber_generator.rb +27 -0
  75. data/generators/cucumber/templates/common_webrat.rb +51 -0
  76. data/generators/cucumber/templates/cucumber +2 -0
  77. data/generators/cucumber/templates/cucumber.rake +7 -0
  78. data/generators/cucumber/templates/env.rb +8 -0
  79. data/generators/feature/feature_generator.rb +17 -0
  80. data/generators/feature/templates/feature.erb +27 -0
  81. data/generators/feature/templates/steps.erb +22 -0
  82. data/lib/cucumber.rb +32 -0
  83. data/lib/cucumber/cli.rb +163 -0
  84. data/lib/cucumber/core_ext/proc.rb +43 -0
  85. data/lib/cucumber/core_ext/string.rb +22 -0
  86. data/lib/cucumber/executor.rb +120 -0
  87. data/lib/cucumber/formatters.rb +1 -0
  88. data/lib/cucumber/formatters/ansicolor.rb +90 -0
  89. data/lib/cucumber/formatters/cucumber.css +132 -0
  90. data/lib/cucumber/formatters/cucumber.js +11 -0
  91. data/lib/cucumber/formatters/html_formatter.rb +125 -0
  92. data/lib/cucumber/formatters/jquery.js +32 -0
  93. data/lib/cucumber/formatters/pretty_formatter.rb +126 -0
  94. data/lib/cucumber/formatters/progress_formatter.rb +42 -0
  95. data/lib/cucumber/languages.yml +83 -0
  96. data/lib/cucumber/rails/rspec.rb +12 -0
  97. data/lib/cucumber/rails/world.rb +75 -0
  98. data/lib/cucumber/rake/task.rb +75 -0
  99. data/lib/cucumber/step_methods.rb +45 -0
  100. data/lib/cucumber/step_mother.rb +82 -0
  101. data/lib/cucumber/tree.rb +18 -0
  102. data/lib/cucumber/tree/feature.rb +53 -0
  103. data/lib/cucumber/tree/features.rb +21 -0
  104. data/lib/cucumber/tree/given_scenario.rb +13 -0
  105. data/lib/cucumber/tree/scenario.rb +110 -0
  106. data/lib/cucumber/tree/step.rb +123 -0
  107. data/lib/cucumber/tree/table.rb +26 -0
  108. data/lib/cucumber/tree/top_down_visitor.rb +23 -0
  109. data/lib/cucumber/treetop_parser/feature.treetop.erb +159 -0
  110. data/lib/cucumber/treetop_parser/feature_da.rb +1214 -0
  111. data/lib/cucumber/treetop_parser/feature_de.rb +1214 -0
  112. data/lib/cucumber/treetop_parser/feature_en.rb +1214 -0
  113. data/lib/cucumber/treetop_parser/feature_es.rb +1214 -0
  114. data/lib/cucumber/treetop_parser/feature_et.rb +1214 -0
  115. data/lib/cucumber/treetop_parser/feature_fr.rb +1214 -0
  116. data/lib/cucumber/treetop_parser/feature_no.rb +1214 -0
  117. data/lib/cucumber/treetop_parser/feature_parser.rb +32 -0
  118. data/lib/cucumber/treetop_parser/feature_pt.rb +1214 -0
  119. data/lib/cucumber/treetop_parser/feature_ru.rb +1214 -0
  120. data/lib/cucumber/treetop_parser/feature_se.rb +1214 -0
  121. data/lib/cucumber/version.rb +9 -0
  122. data/script/console +10 -0
  123. data/script/console.cmd +1 -0
  124. data/script/destroy +14 -0
  125. data/script/destroy.cmd +1 -0
  126. data/script/generate +14 -0
  127. data/script/generate.cmd +1 -0
  128. data/script/txt2html +74 -0
  129. data/script/txt2html.cmd +1 -0
  130. data/setup.rb +1585 -0
  131. data/spec/cucumber/cli_spec.rb +36 -0
  132. data/spec/cucumber/core_ext/proc_spec.rb +39 -0
  133. data/spec/cucumber/core_ext/string_spec.rb +34 -0
  134. data/spec/cucumber/executor_spec.rb +131 -0
  135. data/spec/cucumber/formatters/ansicolor_spec.rb +23 -0
  136. data/spec/cucumber/formatters/features.html +269 -0
  137. data/spec/cucumber/formatters/html_formatter_spec.rb +59 -0
  138. data/spec/cucumber/formatters/pretty_formatter_spec.rb +17 -0
  139. data/spec/cucumber/formatters/progress_formatter_spec.rb +44 -0
  140. data/spec/cucumber/sell_cucumbers.feature +9 -0
  141. data/spec/cucumber/step_mother_spec.rb +53 -0
  142. data/spec/cucumber/tree/scenario_spec.rb +15 -0
  143. data/spec/cucumber/treetop_parser/empty_feature.feature +4 -0
  144. data/spec/cucumber/treetop_parser/empty_scenario.feature +9 -0
  145. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +73 -0
  146. data/spec/cucumber/treetop_parser/fit_scenario.feature +7 -0
  147. data/spec/cucumber/treetop_parser/given_scenario.feature +9 -0
  148. data/spec/cucumber/treetop_parser/multiple_tables.feature +27 -0
  149. data/spec/cucumber/treetop_parser/spaces.feature +10 -0
  150. data/spec/cucumber/treetop_parser/with_comments.feature +6 -0
  151. data/spec/spec.opts +2 -0
  152. data/spec/spec_helper.rb +23 -0
  153. metadata +259 -0
@@ -0,0 +1,45 @@
1
+ require 'cucumber/step_mother'
2
+
3
+ module Cucumber
4
+ # Defines "global" methods that may be used in *_steps.rb files.
5
+ module StepMethods
6
+ # Each scenario will execute in the context of what the supplied block returns.
7
+ def World(&proc)
8
+ $executor.register_world_proc(&proc)
9
+ end
10
+
11
+ def Before(&proc)
12
+ $executor.register_before_scenario_proc(&proc)
13
+ end
14
+
15
+ def After(&proc)
16
+ $executor.register_after_scenario_proc(&proc)
17
+ end
18
+
19
+ def AfterStep(&proc)
20
+ $executor.register_after_step_proc(&proc)
21
+ end
22
+
23
+ def Given(key, &proc)
24
+ step_mother.register_step_proc(key, &proc)
25
+ end
26
+
27
+ def When(key, &proc)
28
+ step_mother.register_step_proc(key, &proc)
29
+ end
30
+
31
+ def Then(key, &proc)
32
+ step_mother.register_step_proc(key, &proc)
33
+ end
34
+
35
+ # Simple workaround for old skool steps
36
+ def steps_for(*_)
37
+ STDERR.puts "WARNING: In Cucumber the steps_for method is obsolete"
38
+ yield
39
+ end
40
+
41
+ def step_mother #:nodoc:
42
+ @step_mother ||= StepMother.new
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,82 @@
1
+ require 'cucumber/tree/top_down_visitor'
2
+ require 'cucumber/core_ext/proc'
3
+
4
+ module Cucumber
5
+ class Pending < StandardError
6
+ end
7
+
8
+ class Duplicate < StandardError
9
+ end
10
+
11
+ class Multiple < StandardError
12
+ end
13
+
14
+ class StepMother
15
+ PENDING = lambda do |*_|
16
+ raise Pending
17
+ end
18
+ PENDING.extend(CoreExt::CallIn)
19
+ PENDING.name = "PENDING"
20
+
21
+ def initialize
22
+ @step_procs = Hash.new(PENDING)
23
+ end
24
+
25
+ def register_step_proc(key, &proc)
26
+ regexp = case(key)
27
+ when String
28
+ # Replace the $foo and $bar style parameters
29
+ pattern = key.gsub(/\$\w+/, '(.*)')
30
+ Regexp.new("^#{pattern}$")
31
+ when Regexp
32
+ key
33
+ else
34
+ raise "Step patterns must be Regexp or String, but was: #{key.inspect}"
35
+ end
36
+ proc.extend(CoreExt::CallIn)
37
+ proc.name = key.inspect
38
+
39
+ if @step_procs.has_key?(regexp)
40
+ first_proc = @step_procs[regexp]
41
+ message = %{Duplicate step definitions:
42
+
43
+ #{first_proc.backtrace_line}
44
+ #{proc.backtrace_line}
45
+
46
+ }
47
+ raise Duplicate.new(message)
48
+ end
49
+
50
+ @step_procs[regexp] = proc
51
+ end
52
+
53
+ def regexp_args_proc(step_name)
54
+ candidates = @step_procs.map do |regexp, proc|
55
+ if step_name =~ regexp
56
+ [regexp, $~.captures, proc]
57
+ end
58
+ end.compact
59
+
60
+ case(candidates.length)
61
+ when 0
62
+ [nil, [], PENDING]
63
+ when 1
64
+ candidates[0]
65
+ else
66
+ message = %{Multiple step definitions match #{step_name.inspect}:
67
+
68
+ #{candidates.map{|regexp, args, proc| proc.backtrace_line}.join("\n")}
69
+
70
+ }
71
+ raise Multiple.new(message)
72
+ end
73
+ end
74
+
75
+ def proc_for(regexp)
76
+ @step_procs[regexp]
77
+ end
78
+
79
+ def execute(step)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,18 @@
1
+ %w{features feature scenario step given_scenario table top_down_visitor}.each{|f| require "cucumber/tree/#{f}"}
2
+ require 'cucumber/core_ext/proc'
3
+ require 'cucumber/core_ext/string'
4
+
5
+ module Cucumber
6
+ module Tree
7
+ def Feature(header, &proc)
8
+ feature = Feature.new("Feature: " + header, &proc)
9
+ feature.file, _, _ = *caller[0].split(':')
10
+ features << feature
11
+ feature
12
+ end
13
+
14
+ def features #:nodoc:
15
+ @features ||= Tree::Features.new
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,53 @@
1
+ module Cucumber
2
+ module Tree
3
+ class Feature
4
+ attr_accessor :file
5
+
6
+ def initialize(header, &proc)
7
+ @header = header
8
+ @scenarios = []
9
+ instance_eval(&proc) if block_given?
10
+ end
11
+
12
+ def add_scenario(name, &proc)
13
+ scenario = Scenario.new(self, name, &proc)
14
+ @scenarios << scenario
15
+ scenario
16
+ end
17
+
18
+ def add_row_scenario(template_scenario, values, line)
19
+ scenario = RowScenario.new(self, template_scenario, values, line)
20
+ @scenarios << scenario
21
+ scenario
22
+ end
23
+
24
+ def scenario_named(name)
25
+ @scenarios.find {|s| s.name == name}
26
+ end
27
+
28
+ def Scenario(name, &proc)
29
+ add_scenario(name, &proc)
30
+ end
31
+
32
+ def Table(matrix = [], &proc)
33
+ table = Table.new(matrix)
34
+ proc.call(table)
35
+ template_scenario = @scenarios.last
36
+ matrix[1..-1].each do |row|
37
+ @scenarios << RowScenario.new(self, template_scenario, row, row.line)
38
+ end
39
+ end
40
+
41
+ def accept(visitor)
42
+ visitor.visit_header(@header)
43
+ @scenarios.each do |scenario|
44
+ if scenario.row?
45
+ visitor.visit_row_scenario(scenario)
46
+ else
47
+ visitor.visit_regular_scenario(scenario)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ module Cucumber
2
+ module Tree
3
+ class Features
4
+ def initialize
5
+ @features = []
6
+ end
7
+
8
+ def length
9
+ @features.length
10
+ end
11
+
12
+ def <<(feature)
13
+ @features << feature
14
+ end
15
+
16
+ def accept(visitor)
17
+ @features.each{|feature| visitor.visit_feature(feature)}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module Cucumber
2
+ module Tree
3
+ class GivenScenario
4
+ def initialize(scenario, name, line)
5
+ @scenario, @name, @line = scenario, name, line
6
+ end
7
+
8
+ def steps
9
+ @scenario.given_scenario_steps(@name)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,110 @@
1
+ module Cucumber
2
+ module Tree
3
+ class BaseScenario
4
+ def file
5
+ @feature.file
6
+ end
7
+
8
+ def accept(visitor)
9
+ steps.each do |step|
10
+ if step.row?
11
+ visitor.visit_row_step(step)
12
+ else
13
+ visitor.visit_regular_step(step)
14
+ end
15
+ end
16
+ end
17
+
18
+ def at_line?(l)
19
+ line == l || steps.map{|s| s.line}.index(l)
20
+ end
21
+
22
+ def previous_step(step)
23
+ i = steps.index(step)
24
+ raise "Couldn't find #{step} among #{steps}" if i.nil?
25
+ steps[i-1]
26
+ end
27
+ end
28
+
29
+ class Scenario < BaseScenario
30
+
31
+ # If a table follows, the header will be stored here. Weird, but convenient.
32
+ attr_accessor :table_header
33
+
34
+ def initialize(feature, name, &proc)
35
+ @feature, @name = feature, name
36
+ @steps_and_given_scenarios = []
37
+ instance_eval(&proc) if block_given?
38
+ end
39
+
40
+ def steps
41
+ @steps ||= @steps_and_given_scenarios.map{|step| step.steps}.flatten
42
+ end
43
+
44
+ def given_scenario_steps(name)
45
+ sibling_named(name).steps
46
+ end
47
+
48
+ def sibling_named(name)
49
+ @feature.scenario_named(name)
50
+ end
51
+
52
+ def row?
53
+ false
54
+ end
55
+
56
+ def add_step(keyword, name, line)
57
+ @steps_and_given_scenarios << Step.new(self, keyword, name, line)
58
+ end
59
+
60
+ def add_given_scenario(name, line)
61
+ @steps_and_given_scenarios << GivenScenario.new(self, name, line)
62
+ end
63
+
64
+ def Given(name)
65
+ add_step('Given', name, *caller[0].split(':')[1].to_i)
66
+ end
67
+
68
+ def When(name)
69
+ add_step('When', name, *caller[0].split(':')[1].to_i)
70
+ end
71
+
72
+ def Then(name)
73
+ add_step('Then', name, *caller[0].split(':')[1].to_i)
74
+ end
75
+
76
+ def And(name)
77
+ add_step('And', name, *caller[0].split(':')[1].to_i)
78
+ end
79
+
80
+ attr_reader :name, :line
81
+
82
+ end
83
+
84
+ class RowScenario < BaseScenario
85
+ attr_reader :line
86
+
87
+ def initialize(feature, template_scenario, values, line)
88
+ @feature, @template_scenario, @values, @line = feature, template_scenario, values, line
89
+ end
90
+
91
+ def row?
92
+ true
93
+ end
94
+
95
+ def name
96
+ @template_scenario.name
97
+ end
98
+
99
+ def steps
100
+ @steps ||= @template_scenario.steps.map do |template_step|
101
+ args = []
102
+ template_step.arity.times do
103
+ args << @values.shift
104
+ end
105
+ RowStep.new(self, template_step, args)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,123 @@
1
+ module Cucumber
2
+ module Tree
3
+ class BaseStep
4
+ attr_accessor :error
5
+
6
+ def self.new_id!
7
+ @next_id ||= -1
8
+ @next_id += 1
9
+ end
10
+
11
+ attr_reader :error
12
+
13
+ def file
14
+ @scenario.file
15
+ end
16
+
17
+ def steps
18
+ self
19
+ end
20
+
21
+ if defined?(JRUBY_VERSION)
22
+ PENDING_ADJUSTMENT = 2
23
+ REGULAR_ADJUSTMENT = 1
24
+ else
25
+ PENDING_ADJUSTMENT = 3
26
+ REGULAR_ADJUSTMENT = 2
27
+ end
28
+
29
+ def execute_in(world, regexp, args, proc)
30
+ strip_pos = nil
31
+ begin
32
+ proc.call_in(world, *args)
33
+ rescue ArityMismatchError => e
34
+ e.backtrace[0] = proc.backtrace_line
35
+ strip_pos = e.backtrace.index("#{__FILE__}:#{__LINE__ - 3}:in `execute_in'")
36
+ format_error(strip_pos, proc, e)
37
+ rescue => e
38
+ method_line = "#{__FILE__}:#{__LINE__ - 6}:in `execute_in'"
39
+ method_line_pos = e.backtrace.index(method_line)
40
+ if method_line_pos
41
+ strip_pos = method_line_pos - (Pending === e ? PENDING_ADJUSTMENT : REGULAR_ADJUSTMENT)
42
+ else
43
+ # This happens with rails, because they screw up the backtrace
44
+ # before we get here (injecting erb stactrace and such)
45
+ end
46
+ format_error(strip_pos, proc, e)
47
+ end
48
+ end
49
+
50
+ def format_error(strip_pos, proc, e)
51
+ @error = e
52
+ # Remove lines underneath the plain text step
53
+ e.backtrace[strip_pos..-1] = nil unless strip_pos.nil?
54
+ e.backtrace.flatten
55
+ # Replace the step line with something more readable
56
+ e.backtrace.replace(e.backtrace.map{|l| l.gsub(/`#{proc.meth}'/, "`#{keyword} #{proc.name}'")})
57
+ if row?
58
+ e.backtrace << "#{file}:#{line}:in `#{proc.name}'"
59
+ else
60
+ e.backtrace << "#{file}:#{line}:in `#{keyword} #{name}'"
61
+ end
62
+ raise e
63
+ end
64
+
65
+ def id
66
+ @id ||= self.class.new_id!
67
+ end
68
+
69
+ def actual_keyword
70
+ keyword == Cucumber.language['and'] ? previous_step.actual_keyword : keyword
71
+ end
72
+
73
+ def previous_step
74
+ @scenario.previous_step(self)
75
+ end
76
+ end
77
+
78
+ class Step < BaseStep
79
+ attr_reader :keyword, :name, :line
80
+ attr_accessor :arity
81
+
82
+ def row?
83
+ false
84
+ end
85
+
86
+ def initialize(scenario, keyword, name, line)
87
+ @scenario, @keyword, @name, @line = scenario, keyword, name, line
88
+ end
89
+
90
+ def regexp_args_proc(step_mother)
91
+ regexp, args, proc = step_mother.regexp_args_proc(name)
92
+ @arity = args.length
93
+ [regexp, args, proc]
94
+ end
95
+
96
+ def format(regexp, format=nil, &proc)
97
+ regexp.nil? ? name : name.gzub(regexp, format, &proc)
98
+ end
99
+ end
100
+
101
+ class RowStep < BaseStep
102
+ attr_reader :keyword
103
+
104
+ def initialize(scenario, step, args)
105
+ @scenario, @step, @args = scenario, step, args
106
+ end
107
+
108
+ def regexp_args_proc(step_mother)
109
+ regexp, _, proc = @step.regexp_args_proc(step_mother)
110
+ [regexp, @args, proc]
111
+ end
112
+
113
+ def row?
114
+ true
115
+ end
116
+
117
+ def line
118
+ @scenario.line
119
+ end
120
+ end
121
+
122
+ end
123
+ end