cucumber 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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|
|