cucumber 0.1.7 → 0.1.8

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 (80) hide show
  1. data/History.txt +81 -0
  2. data/Manifest.txt +30 -9
  3. data/README.txt +1 -2
  4. data/bin/cucumber +1 -1
  5. data/examples/calculator/README.txt +5 -0
  6. data/examples/calculator/Rakefile +1 -2
  7. data/examples/calculator/features/addition.feature +1 -0
  8. data/examples/chinese_simplified_calculator/Rakefile +6 -0
  9. data/examples/chinese_simplified_calculator/features/addition.feature +17 -0
  10. data/examples/chinese_simplified_calculator/features/steps/calculator_steps.rb +24 -0
  11. data/examples/chinese_simplified_calculator/lib/calculator.rb +10 -0
  12. data/examples/java/features/steps/hello_steps.rb +1 -1
  13. data/examples/swedish_calculator/Rakefile +5 -0
  14. data/examples/swedish_calculator/features/steps/kalkulator_steps.rb +22 -0
  15. data/examples/swedish_calculator/features/summering.feature +17 -0
  16. data/examples/swedish_calculator/lib/kalkulator.rb +11 -0
  17. data/examples/tickets/Rakefile +8 -1
  18. data/examples/tickets/cucumber.yml +2 -0
  19. data/examples/tickets/features/steps/tickets_steps.rb +15 -0
  20. data/examples/tickets/features/tickets.feature +12 -1
  21. data/gem_tasks/treetop.rake +35 -23
  22. data/lib/cucumber.rb +1 -0
  23. data/lib/cucumber/cli.rb +19 -5
  24. data/lib/cucumber/core_ext/proc.rb +8 -5
  25. data/lib/cucumber/executor.rb +7 -1
  26. data/lib/cucumber/formatters.rb +1 -1
  27. data/lib/cucumber/formatters/html_formatter.rb +6 -3
  28. data/lib/cucumber/formatters/pretty_formatter.rb +29 -7
  29. data/lib/cucumber/formatters/profile_formatter.rb +92 -0
  30. data/lib/cucumber/languages.yml +39 -12
  31. data/lib/cucumber/model.rb +1 -0
  32. data/lib/cucumber/model/table.rb +28 -0
  33. data/lib/cucumber/rails/world.rb +1 -3
  34. data/lib/cucumber/rake/task.rb +1 -1
  35. data/lib/cucumber/tree/feature.rb +8 -2
  36. data/lib/cucumber/tree/scenario.rb +23 -6
  37. data/lib/cucumber/tree/step.rb +5 -4
  38. data/lib/cucumber/treetop_parser/feature.treetop.erb +54 -12
  39. data/lib/cucumber/treetop_parser/feature_da.rb +415 -74
  40. data/lib/cucumber/treetop_parser/feature_de.rb +415 -74
  41. data/lib/cucumber/treetop_parser/feature_en.rb +415 -74
  42. data/lib/cucumber/treetop_parser/feature_es.rb +415 -74
  43. data/lib/cucumber/treetop_parser/feature_et.rb +415 -74
  44. data/lib/cucumber/treetop_parser/feature_fr.rb +415 -74
  45. data/lib/cucumber/treetop_parser/feature_nl.rb +1593 -0
  46. data/lib/cucumber/treetop_parser/feature_no.rb +415 -74
  47. data/lib/cucumber/treetop_parser/feature_pt.rb +415 -74
  48. data/lib/cucumber/treetop_parser/feature_ru.rb +415 -74
  49. data/lib/cucumber/treetop_parser/feature_se.rb +419 -78
  50. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +1593 -0
  51. data/lib/cucumber/version.rb +1 -1
  52. data/{generators → rails_generators}/cucumber/cucumber_generator.rb +0 -0
  53. data/{generators → rails_generators}/cucumber/templates/common_webrat.rb +1 -10
  54. data/{generators → rails_generators}/cucumber/templates/cucumber +0 -0
  55. data/{generators → rails_generators}/cucumber/templates/cucumber.rake +0 -0
  56. data/{generators → rails_generators}/cucumber/templates/env.rb +0 -0
  57. data/{generators → rails_generators}/feature/feature_generator.rb +0 -0
  58. data/{generators → rails_generators}/feature/templates/feature.erb +1 -0
  59. data/{generators → rails_generators}/feature/templates/steps.erb +0 -0
  60. data/spec/cucumber/cli_spec.rb +11 -3
  61. data/spec/cucumber/core_ext/proc_spec.rb +6 -0
  62. data/spec/cucumber/formatters/html_formatter_spec.rb +16 -1
  63. data/spec/cucumber/formatters/pretty_formatter_spec.rb +54 -25
  64. data/spec/cucumber/formatters/profile_formatter_spec.rb +193 -0
  65. data/spec/cucumber/model/table_spec.rb +20 -0
  66. data/spec/cucumber/rails/stubs/mini_rails.rb +17 -0
  67. data/spec/cucumber/rails/stubs/test_help.rb +1 -0
  68. data/spec/cucumber/rails/world_spec.rb +11 -0
  69. data/spec/cucumber/tree/feature_spec.rb +12 -0
  70. data/spec/cucumber/tree/scenario_spec.rb +22 -0
  71. data/spec/cucumber/tree/step_spec.rb +12 -2
  72. data/spec/cucumber/treetop_parser/empty_scenario.feature +1 -1
  73. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +18 -0
  74. data/spec/cucumber/treetop_parser/fit_scenario.feature +1 -0
  75. data/spec/cucumber/treetop_parser/multiline_steps.feature +13 -0
  76. data/spec/cucumber/treetop_parser/multiple_tables.feature +2 -0
  77. data/spec/cucumber/treetop_parser/test_dos.feature +1 -0
  78. data/spec/cucumber/treetop_parser/with_comments.feature +6 -2
  79. metadata +34 -12
  80. data/examples/calculator/cucumber.yml +0 -1
@@ -2,7 +2,7 @@ module Cucumber #:nodoc:
2
2
  class VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- TINY = 7
5
+ TINY = 8
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -13,7 +13,7 @@ When /^I fill in "(.*)" with "(.*)"$/ do |field, value|
13
13
  fills_in(field, :with => value)
14
14
  end
15
15
 
16
- When /^I select "(.*)" from "(.*)"$/ do |field, value|
16
+ When /^I select "(.*)" from "(.*)"$/ do |value, field|
17
17
  selects(value, :from => field)
18
18
  end
19
19
 
@@ -33,15 +33,6 @@ When /^I attach the file at "(.*)" to "(.*)" $/ do |path, field|
33
33
  attaches_file(field, path)
34
34
  end
35
35
 
36
- When /^I go to (.*)$/ do |page|
37
- visits case page
38
- when "the home page"
39
- "/"
40
- else
41
- raise "Can't find mapping from \"#{page}\" to a path"
42
- end
43
- end
44
-
45
36
  Then /^I should see "(.*)"$/ do |text|
46
37
  response.body.should =~ /#{text}/m
47
38
  end
@@ -22,6 +22,7 @@ Feature: Manage <%= plural_name %>
22
22
  When I delete the first <%= singular_name %>
23
23
  Then there should be 3 <%= plural_name %> left
24
24
 
25
+ More Examples:
25
26
  | initial | after |
26
27
  | 100 | 99 |
27
28
  | 1 | 0 |
@@ -15,7 +15,8 @@ module Cucumber
15
15
  :require => ['from/yml'],
16
16
  :dry_run => false,
17
17
  :lang => 'en',
18
- :source => true
18
+ :source => true,
19
+ :out => STDOUT
19
20
  }
20
21
  end
21
22
 
@@ -31,16 +32,23 @@ module Cucumber
31
32
  :require => ['from/yml'],
32
33
  :dry_run => false,
33
34
  :lang => 'en',
34
- :source => true
35
+ :source => true,
36
+ :out => STDOUT
35
37
  }
36
38
  end
37
39
 
38
- it "should accept source option" do
40
+ it "should accept --no-source option" do
39
41
  cli = CLI.new
40
42
  cli.parse_options!(%w{--no-source})
41
43
 
42
44
  cli.options[:source].should be_false
43
45
  end
46
+
47
+ it "should accept --out option" do
48
+ cli = CLI.new
49
+ File.should_receive(:open).with('jalla.txt', 'w')
50
+ cli.parse_options!(%w{--out jalla.txt})
51
+ end
44
52
 
45
53
  end
46
54
  end
@@ -34,6 +34,12 @@ module Cucumber
34
34
  proc.call_in(Object.new, 1)
35
35
  }.should raise_error(Cucumber::ArityMismatchError, "expected 2 block argument(s), got 1")
36
36
  end
37
+
38
+ it "should remove extraneous path info for file" do
39
+ proc = lambda {|a,b|}
40
+ proc.extend CallIn
41
+ proc.file_colon_line.should == "spec/cucumber/core_ext/proc_spec.rb:39"
42
+ end
37
43
  end
38
44
  end
39
45
  end
@@ -41,7 +41,8 @@ module Cucumber
41
41
  @features << p.parse_feature(f)
42
42
  end
43
43
  @io = StringIO.new
44
- @formatter = HtmlFormatter.new(@io)
44
+ step_mother = mock('step mother')
45
+ @formatter = HtmlFormatter.new(@io, step_mother)
45
46
  @me = MiniExecutor.new(@formatter)
46
47
  end
47
48
 
@@ -54,6 +55,20 @@ module Cucumber
54
55
  #File.open(expected_html, 'w') {|io| io.write(@io.string)}
55
56
  @io.string.should eql(IO.read(expected_html))
56
57
  end
58
+
59
+ it "should render FIT table headers" do
60
+ scenario = mock('scenario', :name => 'test', :accept => nil)
61
+ row_scenario = mock('row scenario', :name => 'test', :accept => nil)
62
+ scenario.stub!(:table_header).and_return(['test', 'fit', 'headers'])
63
+
64
+ @formatter.visit_regular_scenario(scenario)
65
+ @formatter.visit_row_scenario(row_scenario)
66
+
67
+ ['test', 'fit' ,'headers'].each do |column_header|
68
+ @io.string.should include(column_header)
69
+ end
70
+ end
71
+
57
72
  end
58
73
  end
59
74
  end
@@ -12,6 +12,16 @@ module Cucumber
12
12
  :error => nil,
13
13
  :row? => false}.merge(stubs))
14
14
  end
15
+
16
+ def mock_scenario(stubs={})
17
+ stub('scenario', {
18
+ :name => 'test',
19
+ :row? => false }.merge(stubs))
20
+ end
21
+
22
+ def mock_feature(stubs={})
23
+ stub("feature", stubs)
24
+ end
15
25
 
16
26
  def mock_error(stubs={})
17
27
  stub('error', {
@@ -35,47 +45,66 @@ module Cucumber
35
45
 
36
46
  describe "show source option true" do
37
47
 
48
+ before(:each) do
49
+ @io = StringIO.new
50
+ step_mother = mock('step_mother')
51
+ @formatter = PrettyFormatter.new @io, step_mother, :source => true
52
+ end
53
+
38
54
  %w{passed failed skipped}.each do |result|
39
55
  it "should display step source for passed step" do
40
- io = StringIO.new
41
-
42
- step_mother = mock('step_mother')
43
- formatter = PrettyFormatter.new io, step_mother, :source => true
44
- formatter.send("step_#{result}".to_sym, mock_step(:regexp_args_proc => [nil, nil, mock_proc], :error => StandardError.new, :padding_length => 2), nil, nil)
56
+ @formatter.send("step_#{result}".to_sym, mock_step(:regexp_args_proc => [nil, nil, mock_proc], :error => StandardError.new, :padding_length => 2), nil, nil)
45
57
 
46
- io.string.should include("Given formatted yes # steps/example_steps.rb:11")
58
+ @io.string.should include("Given formatted yes # steps/example_steps.rb:11")
47
59
  end
48
60
  end
61
+
62
+ it "should display feature file and line for pending step" do
63
+ @formatter.step_pending(mock_step(:name => 'test', :file => 'features/example.feature', :line => 5, :padding_length => 2), nil, nil)
64
+
65
+ @io.string.should include("Given test # features/example.feature:5")
66
+ end
49
67
 
50
- it "should align step comments" do
51
- io = StringIO.new
68
+ it "should display file and line for scenario" do
69
+ @formatter.scenario_executing(mock_scenario(:name => "title", :file => 'features/example.feature', :line => 2 , :padding_length => 2))
52
70
 
71
+ @io.string.should include("Scenario: title # features/example.feature:2")
72
+ end
73
+
74
+ it "should display file for feature" do
75
+ @formatter.visit_feature(mock_feature(:file => 'features/example.feature', :padding_length => 2))
76
+ @formatter.header_executing("Feature: test\n In order to ...\n As a ...\n I want to ...\n")
77
+
78
+ @io.string.should include("Feature: test # features/example.feature\n")
79
+ @io.string.should include("In order to ...\n")
80
+ @io.string.should include("As a ...\n")
81
+ @io.string.should include("I want to ...\n")
82
+ end
83
+
84
+ it "should align step comments" do
53
85
  step_1 = mock_step(:regexp_args_proc => [nil, nil, mock_proc], :format => "1", :padding_length => 10)
54
86
  step_4 = mock_step(:regexp_args_proc => [nil, nil, mock_proc], :format => "4444", :padding_length => 7)
55
87
  step_9 = mock_step(:regexp_args_proc => [nil, nil, mock_proc], :format => "999999999", :padding_length => 2)
56
-
57
- step_mother = mock('step_mother')
58
- formatter = PrettyFormatter.new io, step_mother, :source => true
59
88
 
60
- formatter.step_passed(step_1, nil, nil)
61
- formatter.step_passed(step_4, nil, nil)
62
- formatter.step_passed(step_9, nil, nil)
89
+ @formatter.step_passed(step_1, nil, nil)
90
+ @formatter.step_passed(step_4, nil, nil)
91
+ @formatter.step_passed(step_9, nil, nil)
63
92
 
64
- io.string.should include("Given 1 # steps/example_steps.rb:11")
65
- io.string.should include("Given 4444 # steps/example_steps.rb:11")
66
- io.string.should include("Given 999999999 # steps/example_steps.rb:11")
93
+ @io.string.should include("Given 1 # steps/example_steps.rb:11")
94
+ @io.string.should include("Given 4444 # steps/example_steps.rb:11")
95
+ @io.string.should include("Given 999999999 # steps/example_steps.rb:11")
67
96
  end
68
-
69
- it "should NOT display step source for pending step" do
70
- io = StringIO.new
71
- step_mother = mock('step_mother')
97
+
98
+ it "should align step comments with respect to their scenario's comment" do
99
+ step = mock_step(:regexp_args_proc => [nil, nil, mock_proc], :error => StandardError.new, :padding_length => 6)
72
100
 
73
- formatter = PrettyFormatter.new io, step_mother, :source => true
74
- formatter.step_pending(mock_step(:regexp_args_proc => [nil, nil, mock_proc]), nil, nil)
101
+ @formatter.scenario_executing(mock_scenario(:name => "very long title", :file => 'features/example.feature', :line => 5, :steps => [step], :padding_length => 2))
102
+ @formatter.step_passed(step, nil, nil)
75
103
 
76
- io.string.should_not include("steps/example_steps.rb:11")
104
+ @io.string.should include("Scenario: very long title # features/example.feature:5")
105
+ @io.string.should include(" Given formatted yes # steps/example_steps.rb:11")
77
106
  end
78
-
107
+
79
108
  end
80
109
  end
81
110
  end
@@ -0,0 +1,193 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module Cucumber
4
+ module Formatters
5
+ describe ProfileFormatter do
6
+ attr_reader :io, :formatter
7
+
8
+ def mock_proc(stubs={})
9
+ stub(Proc, {:to_comment_line => '# steps/example_steps.rb:11'}.merge(stubs))
10
+ end
11
+
12
+ def mock_step(stubs={})
13
+ stub('step', {:keyword => 'Given',
14
+ :actual_keyword => 'Given',
15
+ :format => 'test',
16
+ :row? => false,
17
+ :file => 'test.feature',
18
+ :line => 5,
19
+ :regexp_args_proc => [nil, nil, mock_proc]}.merge(stubs))
20
+ end
21
+
22
+ before(:each) do
23
+ @io = StringIO.new
24
+ step_mother = stub('step_mother')
25
+ @formatter = ProfileFormatter.new(io, step_mother)
26
+ end
27
+
28
+ it "should print a heading" do
29
+ formatter.visit_features(nil)
30
+
31
+ io.string.should eql("Profiling enabled.\n")
32
+ end
33
+
34
+ it "should record the current time when starting a new step" do
35
+ now = Time.now
36
+ Time.stub!(:now).and_return(now)
37
+ formatter.step_executing('should foo', nil, nil)
38
+
39
+ formatter.instance_variable_get("@step_time").should == now
40
+ end
41
+
42
+ describe "grouping recorded passed steps" do
43
+
44
+ before(:each) do
45
+ now = Time.now
46
+ formatter.instance_variable_set("@step_time", now)
47
+ Time.stub!(:now).and_return(now, now)
48
+ end
49
+
50
+ it "should group by regular expressions and actual keyword" do
51
+ step_1 = mock_step(:actual_keyword => 'Given')
52
+ step_2 = mock_step(:actual_keyword => 'Given')
53
+
54
+ formatter.step_passed(step_1, /nihon/, nil)
55
+ formatter.step_passed(step_2, /ichiban/, nil)
56
+
57
+ step_times = formatter.instance_variable_get("@step_times")
58
+
59
+ step_times.has_key?('Given /nihon/').should be_true
60
+ step_times.has_key?('Given /ichiban/').should be_true
61
+ end
62
+
63
+ it "should use a previous step's keyword when recording row steps" do
64
+ step = mock_step(:actual_keyword => 'Given')
65
+ step_row = mock_step(:row? => true)
66
+
67
+ formatter.step_passed(step, /nihon/, [])
68
+ formatter.step_passed(step_row, /nihon/, [])
69
+
70
+ step_times = formatter.instance_variable_get("@step_times")
71
+
72
+ step_times['Given /nihon/'].length.should == 2
73
+ end
74
+
75
+ end
76
+
77
+ it "should correctly record a passed step" do
78
+ formatter.step_executing(nil, nil, nil)
79
+ formatter.step_passed(mock_step(:format => 'she doth teach the torches to burn bright', :actual_keyword => 'Given'), nil, nil)
80
+ formatter.dump
81
+
82
+ io.string.should include('Given she doth teach the torches to burn bright')
83
+ end
84
+
85
+ it "should correctly record a passed step row" do
86
+ formatter.step_executing(nil, nil, nil)
87
+ formatter.step_passed(mock_step(:row? => true), /example/, ['fitty'])
88
+ formatter.dump
89
+
90
+ io.string.should include('fitty')
91
+ end
92
+
93
+ it "should calculate the mean step execution time" do
94
+ now = Time.now
95
+ Time.stub!(:now).and_return(now, now+5, now, now+1)
96
+
97
+ 2.times do
98
+ formatter.step_executing(mock_step, nil, nil)
99
+ formatter.step_passed(mock_step, nil, nil)
100
+ end
101
+
102
+ formatter.dump
103
+
104
+ io.string.should include('3.0000000')
105
+ end
106
+
107
+ it "should display file and line comment for step invocation" do
108
+ step = mock_step(:format => 'test', :actual_keyword => 'Given', :file => 'test.feature', :line => 5)
109
+
110
+ formatter.step_executing(step, nil, nil)
111
+ formatter.step_passed(step, nil, nil)
112
+ formatter.dump
113
+
114
+ @io.string.should include("# test.feature:5")
115
+ end
116
+
117
+ it "should display file and line comment for step definition" do
118
+ step = mock_step(:format => 'test', :actual_keyword => 'Given',
119
+ :regexp_args_proc => [/test/, nil, mock_proc(:to_comment_line => '# steps/example_steps.rb:11')])
120
+
121
+ formatter.step_executing(step, nil, nil)
122
+ formatter.step_passed(step, nil, nil)
123
+ formatter.dump
124
+
125
+ @io.string.should include("# steps/example_steps.rb:11")
126
+ end
127
+
128
+ it "should show the performance times of the step invocations for a step definition" do
129
+ now = Time.now
130
+ Time.stub!(:now).and_return(now, now+5, now, now+1)
131
+
132
+ step = mock_step(:format => 'step invocation', :actual_keyword => 'Given')
133
+
134
+ 2.times do
135
+ formatter.step_executing(step, /example/, nil)
136
+ formatter.step_passed(step, /example/, nil)
137
+ end
138
+
139
+ formatter.dump
140
+
141
+ io.string.should include("3.0000000 Given /example/")
142
+ io.string.should include("5.0000000 Given step invocation")
143
+ io.string.should include("1.0000000 Given step invocation")
144
+ end
145
+
146
+ it "should sort the step invocations in descending order" do
147
+ now = Time.now
148
+ Time.stub!(:now).and_return(now, now+1, now, now+5)
149
+
150
+ step = mock_step(:format => 'step invocation', :actual_keyword => 'Given')
151
+
152
+ 2.times do
153
+ formatter.step_executing(step, /example 1/, nil)
154
+ formatter.step_passed(step, /example 1/, nil)
155
+ end
156
+
157
+ formatter.dump
158
+ io_string_lines = io.string.split("\n")
159
+
160
+ io_string_lines.at(-2).should include('5.0000000')
161
+ io_string_lines.at(-1).should include('1.0000000')
162
+ end
163
+
164
+ it "should print the top average 10 step results" do
165
+ formatter.instance_variable_set("@step_time", Time.now)
166
+
167
+ 11.times do |test_number|
168
+ step_regexp = Regexp.new "unique_test_#{test_number}"
169
+ formatter.step_passed(mock_step(:format => 'test', :actual_keyword => 'Given',
170
+ :regexp_args_proc => [step_regexp, nil, mock_proc]), step_regexp, nil)
171
+ end
172
+
173
+ formatter.dump
174
+
175
+ io.string.scan(/unique_test_\d+/).length.should == 10
176
+ end
177
+
178
+ it "should print the top 5 step invocations for step definition" do
179
+ formatter.instance_variable_set("@step_time", Time.now)
180
+ step_definition_put = 1
181
+
182
+ 10.times do |test_number|
183
+ formatter.step_passed(mock_step(:format => 'please invocate me', :actual_keyword => 'Given'), nil, nil)
184
+ end
185
+
186
+ formatter.dump
187
+
188
+ io.string.scan(/please invocate me/).length.should == 5
189
+ end
190
+
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,20 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module Cucumber
4
+ module Model
5
+ describe Table do
6
+ it "should convert into hash-array" do
7
+ raw = [
8
+ %w{name gender},
9
+ %w{aslak male},
10
+ %w{patty female},
11
+ ]
12
+ ha = Table.new(raw).hashes
13
+ ha.should == [
14
+ {'name' => 'aslak', 'gender' => 'male'},
15
+ {'name' => 'patty', 'gender' => 'female'}
16
+ ]
17
+ end
18
+ end
19
+ end
20
+ end