cucumber 0.1.6 → 0.1.7
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.
- data/History.txt +53 -0
- data/Manifest.txt +4 -0
- data/Rakefile +1 -0
- data/examples/calculator/cucumber.yml +1 -1
- data/examples/dos_line_endings/Rakefile +6 -0
- data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
- data/examples/tickets/features/steps/tickets_steps.rb +13 -1
- data/examples/tickets/features/tickets.feature +5 -1
- data/gem_tasks/treetop.rake +10 -0
- data/generators/cucumber/templates/common_webrat.rb +1 -1
- data/lib/cucumber.rb +3 -1
- data/lib/cucumber/cli.rb +16 -15
- data/lib/cucumber/core_ext/proc.rb +11 -2
- data/lib/cucumber/executor.rb +32 -15
- data/lib/cucumber/formatters/ansicolor.rb +25 -3
- data/lib/cucumber/formatters/pretty_formatter.rb +44 -15
- data/lib/cucumber/languages.yml +10 -0
- data/lib/cucumber/step_methods.rb +8 -4
- data/lib/cucumber/step_mother.rb +4 -3
- data/lib/cucumber/tree/scenario.rb +22 -10
- data/lib/cucumber/tree/step.rb +9 -1
- data/lib/cucumber/treetop_parser/feature.treetop.erb +5 -5
- data/lib/cucumber/treetop_parser/feature_da.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_de.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_en.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_es.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_et.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_fr.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_no.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_parser.rb +4 -2
- data/lib/cucumber/treetop_parser/feature_pt.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_ru.rb +146 -108
- data/lib/cucumber/treetop_parser/feature_se.rb +146 -108
- data/lib/cucumber/version.rb +1 -1
- data/spec/cucumber/cli_spec.rb +14 -4
- data/spec/cucumber/executor_spec.rb +4 -3
- data/spec/cucumber/formatters/ansicolor_spec.rb +4 -0
- data/spec/cucumber/formatters/pretty_formatter_spec.rb +67 -2
- data/spec/cucumber/tree/scenario_spec.rb +2 -2
- data/spec/cucumber/tree/step_spec.rb +21 -0
- data/spec/cucumber/treetop_parser/feature_parser_spec.rb +5 -0
- data/spec/cucumber/treetop_parser/test_dos.feature +24 -0
- data/spec/spec_helper.rb +1 -7
- metadata +6 -2
data/History.txt
CHANGED
@@ -1,3 +1,56 @@
|
|
1
|
+
== 0.1.7
|
2
|
+
|
3
|
+
This release fixes a few bugs and adds some new features. The most notable features are:
|
4
|
+
|
5
|
+
=== Calling steps from steps
|
6
|
+
|
7
|
+
Step definitions are a little bit closer to having regular method semantics.
|
8
|
+
You define them, but now you can also call them from other steps. Here is an
|
9
|
+
example:
|
10
|
+
|
11
|
+
Given /I am logged in as an (.*) named (.*)$/ do |role, name|
|
12
|
+
Given "I am registered as #{role}, #{name}, secret"
|
13
|
+
When "I log in with #{name}, secret"
|
14
|
+
end
|
15
|
+
|
16
|
+
Given /I am registered as (.*), (.*), (.*)/ do |role, name, password|
|
17
|
+
# (Code removed for brevity)
|
18
|
+
end
|
19
|
+
|
20
|
+
When /I log in with (.*), (.*)/ do |name, password|
|
21
|
+
# (Code removed for brevity)
|
22
|
+
end
|
23
|
+
|
24
|
+
This means that steps can be reused in other steps. The GivenScenario feature achieves a similar
|
25
|
+
effect (on the scenario level), but this feature is something we're not very happy with, mostly
|
26
|
+
because it's not parameterisable. Calling steps from steps is.
|
27
|
+
|
28
|
+
GivenScenario will still be working several releases, but the plan is to remove it completely in
|
29
|
+
the 0.3.0 release.
|
30
|
+
|
31
|
+
=== Seeing where a step is defined
|
32
|
+
|
33
|
+
Prior to this release it could be hard to find out where the ruby step definition matching
|
34
|
+
a plain text step is defined. Not anymore! Cucumber will now output this:
|
35
|
+
|
36
|
+
Scenario: Regular numbers
|
37
|
+
Given I have entered 3 into the calculator # features/steps/calculator_steps.rb:12
|
38
|
+
And I have entered 2 into the calculator # features/steps/calculator_steps.rb:12
|
39
|
+
When I press divide # features/steps/calculator_steps.rb:16
|
40
|
+
Then the result should be 1.5 on the screen # features/steps/calculator_steps.rb:20
|
41
|
+
And the result class should be Float # features/steps/calculator_steps.rb:24
|
42
|
+
|
43
|
+
=== Bugfixes
|
44
|
+
* Fixed a bug in the command line args being lost when using --profile (#27, Joseph Wilk)
|
45
|
+
* Fixed a bug in Webrat selects (Tim Glen)
|
46
|
+
* Fixed parsing of DOS line endings (#2, #28, Aslak Hellesøy)
|
47
|
+
|
48
|
+
=== New features
|
49
|
+
* Steps can be called from other steps (#3, Bryan Helmkamp, Aslak Hellesøy)
|
50
|
+
* Added But keyword to all languages (#21, Aslak Hellesøy)
|
51
|
+
* Added --no-source option to display step definition location next to step text (#26, Joseph Wilk, Aslak Hellesøy)
|
52
|
+
* Added more Webrat steps (#25, Tim Glen)
|
53
|
+
|
1
54
|
== 0.1.6
|
2
55
|
|
3
56
|
First gem release!
|
data/Manifest.txt
CHANGED
@@ -31,6 +31,8 @@ examples/danish_calculator/Rakefile
|
|
31
31
|
examples/danish_calculator/features/steps/kalkulator_steps.rb
|
32
32
|
examples/danish_calculator/features/summering.feature
|
33
33
|
examples/danish_calculator/lib/kalkulator.rb
|
34
|
+
examples/dos_line_endings/Rakefile
|
35
|
+
examples/dos_line_endings/features/dos_line_endings.feature
|
34
36
|
examples/estonian_calculator/Rakefile
|
35
37
|
examples/estonian_calculator/features/kalkulaator_steps.rb
|
36
38
|
examples/estonian_calculator/features/liitmine.feature
|
@@ -140,6 +142,7 @@ spec/cucumber/formatters/progress_formatter_spec.rb
|
|
140
142
|
spec/cucumber/sell_cucumbers.feature
|
141
143
|
spec/cucumber/step_mother_spec.rb
|
142
144
|
spec/cucumber/tree/scenario_spec.rb
|
145
|
+
spec/cucumber/tree/step_spec.rb
|
143
146
|
spec/cucumber/treetop_parser/empty_feature.feature
|
144
147
|
spec/cucumber/treetop_parser/empty_scenario.feature
|
145
148
|
spec/cucumber/treetop_parser/feature_parser_spec.rb
|
@@ -147,6 +150,7 @@ spec/cucumber/treetop_parser/fit_scenario.feature
|
|
147
150
|
spec/cucumber/treetop_parser/given_scenario.feature
|
148
151
|
spec/cucumber/treetop_parser/multiple_tables.feature
|
149
152
|
spec/cucumber/treetop_parser/spaces.feature
|
153
|
+
spec/cucumber/treetop_parser/test_dos.feature
|
150
154
|
spec/cucumber/treetop_parser/with_comments.feature
|
151
155
|
spec/spec.opts
|
152
156
|
spec/spec_helper.rb
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
default: --format
|
1
|
+
default: --format pretty features
|
@@ -2,4 +2,16 @@ require 'spec'
|
|
2
2
|
|
3
3
|
Given "be_empty" do
|
4
4
|
[1,2].should_not be_empty
|
5
|
-
end
|
5
|
+
end
|
6
|
+
|
7
|
+
Given "nested step is called" do
|
8
|
+
Given "nested step"
|
9
|
+
end
|
10
|
+
|
11
|
+
Given "nested step" do
|
12
|
+
@magic = 'mushroom'
|
13
|
+
end
|
14
|
+
|
15
|
+
Then "nested step should be executed" do
|
16
|
+
@magic.should == 'mushroom'
|
17
|
+
end
|
data/gem_tasks/treetop.rake
CHANGED
@@ -9,12 +9,22 @@ class FeatureCompiler
|
|
9
9
|
|
10
10
|
langs.each do |lang, words|
|
11
11
|
grammar_file = File.dirname(__FILE__) + "/../lib/cucumber/treetop_parser/feature_#{lang}.treetop"
|
12
|
+
ruby_file = File.dirname(__FILE__) + "/../lib/cucumber/treetop_parser/feature_#{lang}.rb"
|
12
13
|
grammar = template.result(binding)
|
13
14
|
File.open(grammar_file, "wb") do |io|
|
14
15
|
io.write(grammar)
|
15
16
|
end
|
16
17
|
sh "#{tt} #{grammar_file}"
|
17
18
|
FileUtils.rm(grammar_file)
|
19
|
+
|
20
|
+
# Change code so it isn't part of RDoc
|
21
|
+
lines = IO.read(ruby_file).split("\n")
|
22
|
+
lines.each do |line|
|
23
|
+
if line =~ /\s*(def|class|module)/
|
24
|
+
line << " #:nodoc:"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
File.open(ruby_file, 'wb'){|io| io.write(lines.join("\n"))}
|
18
28
|
end
|
19
29
|
end
|
20
30
|
end
|
data/lib/cucumber.rb
CHANGED
@@ -13,6 +13,8 @@ require 'cucumber/treetop_parser/feature_parser'
|
|
13
13
|
require 'cucumber/cli'
|
14
14
|
|
15
15
|
module Cucumber
|
16
|
+
LANGUAGE_FILE = File.expand_path(File.dirname(__FILE__) + '/cucumber/languages.yml')
|
17
|
+
|
16
18
|
class << self
|
17
19
|
attr_reader :language
|
18
20
|
|
@@ -26,7 +28,7 @@ module Cucumber
|
|
26
28
|
|
27
29
|
def config
|
28
30
|
require 'yaml'
|
29
|
-
@config ||= YAML.load_file(
|
31
|
+
@config ||= YAML.load_file(LANGUAGE_FILE)
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
data/lib/cucumber/cli.rb
CHANGED
@@ -4,11 +4,11 @@ require 'cucumber'
|
|
4
4
|
module Cucumber
|
5
5
|
class CLI
|
6
6
|
class << self
|
7
|
-
attr_writer :step_mother, :features
|
7
|
+
attr_writer :step_mother, :executor, :features
|
8
8
|
|
9
9
|
def execute
|
10
10
|
@execute_called = true
|
11
|
-
parse(ARGV).execute!(@step_mother, @features)
|
11
|
+
parse(ARGV).execute!(@step_mother, @executor, @features)
|
12
12
|
end
|
13
13
|
|
14
14
|
def execute_called?
|
@@ -33,7 +33,7 @@ module Cucumber
|
|
33
33
|
return parse_args_from_profile('default') if args.empty?
|
34
34
|
args.extend(OptionParser::Arguable)
|
35
35
|
|
36
|
-
@options
|
36
|
+
@options ||= { :require => nil, :lang => 'en', :format => 'pretty', :dry_run => false, :source => true }
|
37
37
|
args.options do |opts|
|
38
38
|
opts.banner = "Usage: cucumber [options] FILES|DIRS"
|
39
39
|
opts.on("-r LIBRARY|DIR", "--require LIBRARY|DIR", "Require files before executing the features.",
|
@@ -46,7 +46,8 @@ module Cucumber
|
|
46
46
|
@options[:line] = v
|
47
47
|
end
|
48
48
|
opts.on("-a LANG", "--language LANG", "Specify language for features (Default: #{@options[:lang]})",
|
49
|
-
"Available languages: #{Cucumber.languages.join(", ")}"
|
49
|
+
"Available languages: #{Cucumber.languages.join(", ")}",
|
50
|
+
"Look at #{Cucumber::LANGUAGE_FILE} for keywords") do |v|
|
50
51
|
@options[:lang] = v
|
51
52
|
end
|
52
53
|
opts.on("-f FORMAT", "--format FORMAT", "How to format features (Default: #{@options[:format]})",
|
@@ -64,6 +65,9 @@ module Cucumber
|
|
64
65
|
opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.") do
|
65
66
|
@options[:dry_run] = true
|
66
67
|
end
|
68
|
+
opts.on("-n", "--no-source", "Don't show the file and line of the step definition with the steps.") do
|
69
|
+
@options[:source] = false
|
70
|
+
end
|
67
71
|
opts.on_tail("--version", "Show version") do
|
68
72
|
puts VERSION::STRING
|
69
73
|
exit
|
@@ -86,14 +90,14 @@ module Cucumber
|
|
86
90
|
parse_options!(args_from_yml.split(' '))
|
87
91
|
end
|
88
92
|
|
89
|
-
def execute!(step_mother, features)
|
93
|
+
def execute!(step_mother, executor, features)
|
90
94
|
Cucumber.load_language(@options[:lang])
|
91
|
-
|
95
|
+
executor.formatter = formatter(step_mother)
|
92
96
|
require_files
|
93
97
|
load_plain_text_features(features)
|
94
|
-
|
95
|
-
|
96
|
-
exit 1 if
|
98
|
+
executor.line = @options[:line].to_i if @options[:line]
|
99
|
+
executor.visit_features(features)
|
100
|
+
exit 1 if executor.failed
|
97
101
|
end
|
98
102
|
|
99
103
|
private
|
@@ -141,7 +145,7 @@ module Cucumber
|
|
141
145
|
def formatter(step_mother)
|
142
146
|
case @options[:format]
|
143
147
|
when 'pretty'
|
144
|
-
Formatters::PrettyFormatter.new(STDOUT)
|
148
|
+
Formatters::PrettyFormatter.new(STDOUT, step_mother, @options)
|
145
149
|
when 'progress'
|
146
150
|
Formatters::ProgressFormatter.new(STDOUT)
|
147
151
|
when 'html'
|
@@ -154,10 +158,7 @@ end
|
|
154
158
|
|
155
159
|
extend Cucumber::StepMethods
|
156
160
|
Cucumber::CLI.step_mother = step_mother
|
161
|
+
Cucumber::CLI.executor = executor
|
157
162
|
|
158
|
-
extend
|
163
|
+
extend Cucumber::Tree
|
159
164
|
Cucumber::CLI.features = features
|
160
|
-
|
161
|
-
at_exit do
|
162
|
-
Cucumber::CLI.execute unless Cucumber::CLI.execute_called?
|
163
|
-
end
|
@@ -23,10 +23,19 @@ module Cucumber
|
|
23
23
|
arity == -1 ? 0 : arity
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
|
26
|
+
def to_backtrace_line
|
27
|
+
"#{file}:in `#{name}'"
|
28
28
|
end
|
29
29
|
|
30
|
+
def to_comment_line
|
31
|
+
"# #{file}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def file
|
35
|
+
file = to_s.match(/[\d\w]+@(.*)>/)[1]
|
36
|
+
file =~ /^\.\/(.*)/ ? $1 : file
|
37
|
+
end
|
38
|
+
|
30
39
|
def meth
|
31
40
|
@meth ||= "__cucumber_#{object_id}"
|
32
41
|
end
|
data/lib/cucumber/executor.rb
CHANGED
@@ -3,17 +3,15 @@ require 'cucumber/core_ext/proc'
|
|
3
3
|
module Cucumber
|
4
4
|
class Executor
|
5
5
|
attr_reader :failed
|
6
|
+
attr_accessor :formatter
|
6
7
|
|
7
8
|
def line=(line)
|
8
9
|
@line = line
|
9
10
|
end
|
10
11
|
|
11
|
-
def initialize(
|
12
|
-
@formatter = formatter
|
12
|
+
def initialize(step_mother)
|
13
13
|
@world_proc = lambda do
|
14
|
-
|
15
|
-
world.extend(Spec::Matchers) if defined?(Spec::Matchers)
|
16
|
-
world
|
14
|
+
Object.new
|
17
15
|
end
|
18
16
|
@before_scenario_procs = []
|
19
17
|
@after_scenario_procs = []
|
@@ -42,9 +40,9 @@ module Cucumber
|
|
42
40
|
|
43
41
|
def visit_features(features)
|
44
42
|
raise "Line number can only be specified when there is 1 feature. There were #{features.length}." if @line && features.length != 1
|
45
|
-
|
43
|
+
formatter.visit_features(features) if formatter.respond_to?(:visit_features)
|
46
44
|
features.accept(self)
|
47
|
-
|
45
|
+
formatter.dump
|
48
46
|
end
|
49
47
|
|
50
48
|
def visit_feature(feature)
|
@@ -52,7 +50,7 @@ module Cucumber
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def visit_header(header)
|
55
|
-
|
53
|
+
formatter.header_executing(header) if formatter.respond_to?(:header_executing)
|
56
54
|
end
|
57
55
|
|
58
56
|
def visit_row_scenario(scenario)
|
@@ -67,12 +65,16 @@ module Cucumber
|
|
67
65
|
if @line.nil? || scenario.at_line?(@line)
|
68
66
|
@error = nil
|
69
67
|
@pending = nil
|
68
|
+
|
70
69
|
@world = @world_proc.call
|
71
|
-
@
|
70
|
+
@world.extend(Spec::Matchers) if defined?(Spec::Matchers)
|
71
|
+
define_step_call_methods(@world)
|
72
|
+
|
73
|
+
formatter.scenario_executing(scenario) if formatter.respond_to?(:scenario_executing)
|
72
74
|
@before_scenario_procs.each{|p| p.call_in(@world, *[])}
|
73
75
|
scenario.accept(self)
|
74
76
|
@after_scenario_procs.each{|p| p.call_in(@world, *[])}
|
75
|
-
|
77
|
+
formatter.scenario_executed(scenario) if formatter.respond_to?(:scenario_executed)
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
@@ -90,31 +92,46 @@ module Cucumber
|
|
90
92
|
regexp, args, proc = step.regexp_args_proc(@step_mother)
|
91
93
|
step.execute_in(@world, regexp, args, proc)
|
92
94
|
@after_step_procs.each{|p| p.call_in(@world, *[])}
|
93
|
-
|
95
|
+
formatter.step_passed(step, regexp, args)
|
94
96
|
rescue Pending
|
95
97
|
record_pending_step(step, regexp, args)
|
96
98
|
rescue => e
|
97
99
|
@failed = true
|
98
100
|
@error = step.error = e
|
99
|
-
|
101
|
+
formatter.step_failed(step, regexp, args)
|
100
102
|
end
|
101
103
|
else
|
102
104
|
begin
|
103
105
|
regexp, args, proc = step.regexp_args_proc(@step_mother)
|
104
106
|
step.execute_in(@world, regexp, args, proc)
|
105
|
-
|
107
|
+
formatter.step_skipped(step, regexp, args)
|
106
108
|
rescue Pending
|
107
109
|
record_pending_step(step, regexp, args)
|
108
110
|
rescue Exception
|
109
|
-
|
111
|
+
formatter.step_skipped(step, regexp, args)
|
110
112
|
end
|
111
113
|
end
|
112
114
|
end
|
113
115
|
|
114
116
|
def record_pending_step(step, regexp, args)
|
115
117
|
@pending = true
|
116
|
-
|
118
|
+
formatter.step_pending(step, regexp, args)
|
117
119
|
end
|
118
120
|
|
121
|
+
def define_step_call_methods(world)
|
122
|
+
world.instance_variable_set('@__executor', self)
|
123
|
+
world.instance_eval do
|
124
|
+
class << self
|
125
|
+
def run_step(name)
|
126
|
+
_, args, proc = @__executor.instance_variable_get(:@step_mother).regexp_args_proc(name)
|
127
|
+
proc.call_in(self, *args)
|
128
|
+
end
|
129
|
+
|
130
|
+
%w{given when then and but}.each do |keyword|
|
131
|
+
alias_method Cucumber.language[keyword], :run_step
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
119
136
|
end
|
120
137
|
end
|
@@ -1,11 +1,22 @@
|
|
1
|
+
gem 'term-ansicolor'
|
2
|
+
# Hack to work around Win32/Console, which bundles a licence-violating, outdated
|
3
|
+
# copy of term/ansicolor that doesn't implement Term::ANSIColor#coloring=.
|
4
|
+
# We want the official one!
|
5
|
+
$LOAD_PATH.each{|path| $LOAD_PATH.unshift($LOAD_PATH.delete(path)) if path =~ /term-ansicolor/}
|
6
|
+
|
1
7
|
require 'term/ansicolor'
|
8
|
+
require 'rbconfig'
|
9
|
+
|
10
|
+
win = Config::CONFIG['host_os'] =~ /mswin|mingw/
|
11
|
+
jruby = defined?(JRUBY_VERSION)
|
12
|
+
|
2
13
|
begin
|
3
|
-
require 'Win32/Console/ANSI' if
|
14
|
+
require 'Win32/Console/ANSI' if (win && !jruby)
|
4
15
|
rescue LoadError
|
5
16
|
STDERR.puts "You must gem install win32console to get coloured output on this ruby platform (#{PLATFORM})"
|
6
17
|
::Term::ANSIColor.coloring = false
|
7
18
|
end
|
8
|
-
::Term::ANSIColor.coloring = false if !STDOUT.tty?
|
19
|
+
::Term::ANSIColor.coloring = false if !STDOUT.tty? || (win && jruby)
|
9
20
|
|
10
21
|
module Cucumber
|
11
22
|
module Formatters
|
@@ -44,6 +55,7 @@ module Cucumber
|
|
44
55
|
# ** magenta
|
45
56
|
# ** cyan
|
46
57
|
# ** white
|
58
|
+
# ** grey
|
47
59
|
# ** on_black
|
48
60
|
# ** on_red
|
49
61
|
# ** on_green
|
@@ -67,7 +79,8 @@ module Cucumber
|
|
67
79
|
:failed_param => "#{param}red",
|
68
80
|
:skipped => 'bold,cyan',
|
69
81
|
:skipped_param => "#{param}cyan",
|
70
|
-
:pending => 'bold,yellow' # No pending_param
|
82
|
+
:pending => 'bold,yellow', # No pending_param
|
83
|
+
:comment => 'grey'
|
71
84
|
}
|
72
85
|
if ENV['CUCUMBER_COLORS']
|
73
86
|
ENV['CUCUMBER_COLORS'].split(':').each do |pair|
|
@@ -76,6 +89,15 @@ module Cucumber
|
|
76
89
|
end
|
77
90
|
end
|
78
91
|
|
92
|
+
#Not supported in Term::ANSIColor
|
93
|
+
def grey(m)
|
94
|
+
if ENV['CUCUMBER_COLORS_DISABLED'] == '1'
|
95
|
+
m
|
96
|
+
else
|
97
|
+
"\e[90m#{m}\e[0m"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
79
101
|
ALIASES.each do |m, color_string|
|
80
102
|
colors = color_string.split(",").reverse
|
81
103
|
define_method(m) do |*s|
|