elight-cucumber 0.1.9
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 +150 -0
- data/License.txt +20 -0
- data/Manifest.txt +186 -0
- data/README.txt +41 -0
- data/Rakefile +5 -0
- data/TODO.txt +26 -0
- data/bin/cucumber +4 -0
- data/config/hoe.rb +69 -0
- data/config/requirements.rb +15 -0
- data/cucumber.yml +1 -0
- data/examples/calculator/README.txt +5 -0
- data/examples/calculator/Rakefile +5 -0
- data/examples/calculator/features/addition.feature +17 -0
- data/examples/calculator/features/division.feature +10 -0
- data/examples/calculator/features/steps/calculator_steps.rb +31 -0
- data/examples/calculator/lib/calculator.rb +16 -0
- data/examples/calculator_ruby_features/Rakefile +6 -0
- data/examples/calculator_ruby_features/features/addition.rb +23 -0
- data/examples/calculator_ruby_features/features/steps/calculator_steps.rb +43 -0
- data/examples/calculatrice_francaise_avec_soit_scenario/Rakefile +6 -0
- data/examples/calculatrice_francaise_avec_soit_scenario/features/addition.feature +13 -0
- data/examples/calculatrice_francaise_avec_soit_scenario/features/calculatrice_steps.rb +31 -0
- data/examples/chinese_simplified_calculator/Rakefile +6 -0
- data/examples/chinese_simplified_calculator/features/addition.feature +17 -0
- data/examples/chinese_simplified_calculator/features/steps/calculator_steps.rb +24 -0
- data/examples/chinese_simplified_calculator/lib/calculator.rb +10 -0
- data/examples/cs/README.textile +22 -0
- data/examples/cs/Rakefile +12 -0
- data/examples/cs/features/hello.feature +11 -0
- data/examples/cs/features/steps/hello_steps.rb +25 -0
- data/examples/cs/features/steps/tree_steps.rb +14 -0
- data/examples/cs/features/tree.feature +9 -0
- data/examples/cs/src/Hello.cs +18 -0
- data/examples/danish_calculator/Rakefile +6 -0
- data/examples/danish_calculator/features/steps/kalkulator_steps.rb +22 -0
- data/examples/danish_calculator/features/summering.feature +17 -0
- data/examples/danish_calculator/lib/kalkulator.rb +11 -0
- data/examples/dos_line_endings/Rakefile +6 -0
- data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
- data/examples/estonian_calculator/Rakefile +6 -0
- data/examples/estonian_calculator/features/kalkulaator_steps.rb +35 -0
- data/examples/estonian_calculator/features/liitmine.feature +16 -0
- data/examples/japanese_calculator/README.txt +5 -0
- data/examples/japanese_calculator/Rakefile +6 -0
- data/examples/japanese_calculator/features/addition.feature +17 -0
- data/examples/japanese_calculator/features/division.feature +10 -0
- data/examples/japanese_calculator/features/steps/calculator_steps.rb +30 -0
- data/examples/japanese_calculator/lib/calculator.rb +16 -0
- data/examples/java/README.textile +22 -0
- data/examples/java/Rakefile +12 -0
- data/examples/java/features/hello.feature +11 -0
- data/examples/java/features/steps/hello_steps.rb +25 -0
- data/examples/java/features/steps/tree_steps.rb +14 -0
- data/examples/java/features/tree.feature +9 -0
- data/examples/java/src/cucumber/demo/Hello.java +16 -0
- data/examples/norwegian_calculator/Rakefile +6 -0
- data/examples/norwegian_calculator/features/steps/kalkulator_steps.rb +22 -0
- data/examples/norwegian_calculator/features/summering.feature +17 -0
- data/examples/norwegian_calculator/lib/kalkulator.rb +11 -0
- data/examples/portuguese_calculator/Rakefile +6 -0
- data/examples/portuguese_calculator/features/adicao.feature +10 -0
- data/examples/portuguese_calculator/features/calculadora_steps.rb +31 -0
- data/examples/selenium/Rakefile +6 -0
- data/examples/selenium/features/search.feature +9 -0
- data/examples/selenium/features/steps/stories_steps.rb +41 -0
- data/examples/spanish_calculator/Rakefile +6 -0
- data/examples/spanish_calculator/features/adicion.feature +17 -0
- data/examples/spanish_calculator/features/steps/calculador_steps.rb +22 -0
- data/examples/swedish_calculator/Rakefile +5 -0
- data/examples/swedish_calculator/features/steps/kalkulator_steps.rb +22 -0
- data/examples/swedish_calculator/features/summering.feature +17 -0
- data/examples/swedish_calculator/lib/kalkulator.rb +11 -0
- data/examples/tickets/Rakefile +11 -0
- data/examples/tickets/cucumber.yml +2 -0
- data/examples/tickets/features/steps/tickets_steps.rb +32 -0
- data/examples/tickets/features/tickets.feature +22 -0
- data/examples/watir/Rakefile +6 -0
- data/examples/watir/features/search.feature +9 -0
- data/examples/watir/features/steps/stories_steps.rb +51 -0
- data/features/see_features.feature +8 -0
- data/features/steps/features_steps.rb +9 -0
- data/gem_tasks/deployment.rake +34 -0
- data/gem_tasks/environment.rake +7 -0
- data/gem_tasks/features.rake +6 -0
- data/gem_tasks/fix_cr_lf.rake +10 -0
- data/gem_tasks/flog.rake +4 -0
- data/gem_tasks/gemspec.rake +6 -0
- data/gem_tasks/rspec.rake +21 -0
- data/gem_tasks/treetop.rake +49 -0
- data/lib/cucumber.rb +35 -0
- data/lib/cucumber/cli.rb +191 -0
- data/lib/cucumber/core_ext/proc.rb +55 -0
- data/lib/cucumber/core_ext/string.rb +22 -0
- data/lib/cucumber/executor.rb +143 -0
- data/lib/cucumber/formatters.rb +1 -0
- data/lib/cucumber/formatters/ansicolor.rb +112 -0
- data/lib/cucumber/formatters/cucumber.css +132 -0
- data/lib/cucumber/formatters/cucumber.js +11 -0
- data/lib/cucumber/formatters/html_formatter.rb +128 -0
- data/lib/cucumber/formatters/jquery.js +32 -0
- data/lib/cucumber/formatters/pretty_formatter.rb +211 -0
- data/lib/cucumber/formatters/profile_formatter.rb +92 -0
- data/lib/cucumber/formatters/progress_formatter.rb +51 -0
- data/lib/cucumber/languages.yml +142 -0
- data/lib/cucumber/model.rb +1 -0
- data/lib/cucumber/model/table.rb +28 -0
- data/lib/cucumber/rails/rspec.rb +12 -0
- data/lib/cucumber/rails/world.rb +73 -0
- data/lib/cucumber/rake/task.rb +75 -0
- data/lib/cucumber/step_methods.rb +49 -0
- data/lib/cucumber/step_mother.rb +83 -0
- data/lib/cucumber/tree.rb +18 -0
- data/lib/cucumber/tree/feature.rb +60 -0
- data/lib/cucumber/tree/features.rb +21 -0
- data/lib/cucumber/tree/given_scenario.rb +13 -0
- data/lib/cucumber/tree/scenario.rb +150 -0
- data/lib/cucumber/tree/step.rb +133 -0
- data/lib/cucumber/tree/table.rb +26 -0
- data/lib/cucumber/tree/top_down_visitor.rb +23 -0
- data/lib/cucumber/treetop_parser/feature.treetop.erb +201 -0
- data/lib/cucumber/treetop_parser/feature_da.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_de.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_en-tx.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_en.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_es.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_et.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_fr.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_ja.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_nl.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_no.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_parser.rb +34 -0
- data/lib/cucumber/treetop_parser/feature_pt.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_ru.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_se.rb +1593 -0
- data/lib/cucumber/treetop_parser/feature_zh-CN.rb +1593 -0
- data/lib/cucumber/version.rb +9 -0
- data/rails_generators/cucumber/cucumber_generator.rb +29 -0
- data/rails_generators/cucumber/templates/common_webrat.rb +42 -0
- data/rails_generators/cucumber/templates/cucumber +2 -0
- data/rails_generators/cucumber/templates/cucumber.rake +12 -0
- data/rails_generators/cucumber/templates/cucumber.yml +1 -0
- data/rails_generators/cucumber/templates/env.rb +8 -0
- data/rails_generators/feature/feature_generator.rb +17 -0
- data/rails_generators/feature/templates/feature.erb +28 -0
- data/rails_generators/feature/templates/steps.erb +22 -0
- data/script/console +10 -0
- data/script/console.cmd +1 -0
- data/script/destroy +14 -0
- data/script/destroy.cmd +1 -0
- data/script/generate +14 -0
- data/script/generate.cmd +1 -0
- data/script/txt2html +74 -0
- data/script/txt2html.cmd +1 -0
- data/setup.rb +1585 -0
- data/spec/cucumber/cli_spec.rb +56 -0
- data/spec/cucumber/core_ext/proc_spec.rb +45 -0
- data/spec/cucumber/core_ext/string_spec.rb +34 -0
- data/spec/cucumber/executor_spec.rb +130 -0
- data/spec/cucumber/formatters/ansicolor_spec.rb +35 -0
- data/spec/cucumber/formatters/features.html +269 -0
- data/spec/cucumber/formatters/html_formatter_spec.rb +74 -0
- data/spec/cucumber/formatters/pretty_formatter_spec.rb +111 -0
- data/spec/cucumber/formatters/profile_formatter_spec.rb +193 -0
- data/spec/cucumber/formatters/progress_formatter_spec.rb +45 -0
- data/spec/cucumber/model/table_spec.rb +20 -0
- data/spec/cucumber/rails/stubs/mini_rails.rb +17 -0
- data/spec/cucumber/rails/stubs/test_help.rb +1 -0
- data/spec/cucumber/rails/world_spec.rb +11 -0
- data/spec/cucumber/sell_cucumbers.feature +9 -0
- data/spec/cucumber/step_mother_spec.rb +53 -0
- data/spec/cucumber/tree/feature_spec.rb +12 -0
- data/spec/cucumber/tree/scenario_spec.rb +37 -0
- data/spec/cucumber/tree/step_spec.rb +31 -0
- data/spec/cucumber/treetop_parser/empty_feature.feature +4 -0
- data/spec/cucumber/treetop_parser/empty_scenario.feature +9 -0
- data/spec/cucumber/treetop_parser/feature_parser_spec.rb +96 -0
- data/spec/cucumber/treetop_parser/fit_scenario.feature +8 -0
- data/spec/cucumber/treetop_parser/given_scenario.feature +9 -0
- data/spec/cucumber/treetop_parser/multiline_steps.feature +13 -0
- data/spec/cucumber/treetop_parser/multiple_tables.feature +29 -0
- data/spec/cucumber/treetop_parser/spaces.feature +10 -0
- data/spec/cucumber/treetop_parser/test_dos.feature +25 -0
- data/spec/cucumber/treetop_parser/with_comments.feature +10 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +19 -0
- metadata +288 -0
data/lib/cucumber.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'treetop/runtime'
|
|
5
|
+
require 'treetop/ruby_extensions'
|
|
6
|
+
require 'cucumber/version'
|
|
7
|
+
require 'cucumber/step_methods'
|
|
8
|
+
require 'cucumber/tree'
|
|
9
|
+
require 'cucumber/model'
|
|
10
|
+
require 'cucumber/executor'
|
|
11
|
+
require 'cucumber/step_mother'
|
|
12
|
+
require 'cucumber/formatters'
|
|
13
|
+
require 'cucumber/treetop_parser/feature_parser'
|
|
14
|
+
require 'cucumber/cli'
|
|
15
|
+
|
|
16
|
+
module Cucumber
|
|
17
|
+
LANGUAGE_FILE = File.expand_path(File.dirname(__FILE__) + '/cucumber/languages.yml')
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
attr_reader :language
|
|
21
|
+
|
|
22
|
+
def load_language(lang)
|
|
23
|
+
@language = config[lang]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def languages
|
|
27
|
+
config.keys.sort
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def config
|
|
31
|
+
require 'yaml'
|
|
32
|
+
@config ||= YAML.load_file(LANGUAGE_FILE)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/cucumber/cli.rb
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
require 'cucumber'
|
|
3
|
+
|
|
4
|
+
module Cucumber
|
|
5
|
+
class CLI
|
|
6
|
+
class << self
|
|
7
|
+
attr_writer :step_mother, :executor, :features
|
|
8
|
+
|
|
9
|
+
def execute
|
|
10
|
+
@execute_called = true
|
|
11
|
+
parse(ARGV).execute!(@step_mother, @executor, @features)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def execute_called?
|
|
15
|
+
@execute_called
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse(args)
|
|
19
|
+
cli = new
|
|
20
|
+
cli.parse_options!(args)
|
|
21
|
+
cli
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
attr_reader :options
|
|
26
|
+
FORMATS = %w{pretty profile progress html}
|
|
27
|
+
|
|
28
|
+
def initialize
|
|
29
|
+
@paths = []
|
|
30
|
+
@options = {
|
|
31
|
+
:require => nil,
|
|
32
|
+
:lang => 'en',
|
|
33
|
+
:format => 'pretty',
|
|
34
|
+
:dry_run => false,
|
|
35
|
+
:source => true,
|
|
36
|
+
:out => STDOUT,
|
|
37
|
+
:excludes => []
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def parse_options!(args)
|
|
42
|
+
return parse_args_from_profile('default') if args.empty?
|
|
43
|
+
args.extend(OptionParser::Arguable)
|
|
44
|
+
|
|
45
|
+
args.options do |opts|
|
|
46
|
+
opts.banner = "Usage: cucumber [options] FILES|DIRS"
|
|
47
|
+
opts.on("-r LIBRARY|DIR", "--require LIBRARY|DIR", "Require files before executing the features.",
|
|
48
|
+
"If this option is not specified, all *.rb files that",
|
|
49
|
+
"are siblings or below the features will be autorequired") do |v|
|
|
50
|
+
@options[:require] ||= []
|
|
51
|
+
@options[:require] << v
|
|
52
|
+
end
|
|
53
|
+
opts.on("-l LINE", "--line LINE", "Only execute the scenario at the given line") do |v|
|
|
54
|
+
@options[:line] = v
|
|
55
|
+
end
|
|
56
|
+
opts.on("-a LANG", "--language LANG", "Specify language for features (Default: #{@options[:lang]})",
|
|
57
|
+
"Available languages: #{Cucumber.languages.join(", ")}",
|
|
58
|
+
"Look at #{Cucumber::LANGUAGE_FILE} for keywords") do |v|
|
|
59
|
+
@options[:lang] = v
|
|
60
|
+
end
|
|
61
|
+
opts.on("-f FORMAT", "--format FORMAT", "How to format features (Default: #{@options[:format]})",
|
|
62
|
+
"Available formats: #{FORMATS.join(", ")}") do |v|
|
|
63
|
+
unless FORMATS.index(v)
|
|
64
|
+
STDERR.puts "Invalid format: #{v}\n"
|
|
65
|
+
STDERR.puts opts.help
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
@options[:format] = v
|
|
69
|
+
end
|
|
70
|
+
opts.on("--exclude=PATTERN", "Don't run features matching a pattern") do |v|
|
|
71
|
+
@options[:excludes] << v
|
|
72
|
+
end
|
|
73
|
+
opts.on("-p=PROFILE", "--profile=PROFILE", "Pull commandline arguments from cucumber.yml.") do |v|
|
|
74
|
+
parse_args_from_profile(v)
|
|
75
|
+
end
|
|
76
|
+
opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.") do
|
|
77
|
+
@options[:dry_run] = true
|
|
78
|
+
end
|
|
79
|
+
opts.on("-n", "--no-source", "Don't show the file and line of the step definition with the steps.") do
|
|
80
|
+
@options[:source] = false
|
|
81
|
+
end
|
|
82
|
+
opts.on("-o", "--out=FILE", "Write output to a file instead of STDOUT.") do |v|
|
|
83
|
+
@options[:out] = File.open(v, 'w')
|
|
84
|
+
end
|
|
85
|
+
opts.on_tail("--version", "Show version") do
|
|
86
|
+
puts VERSION::STRING
|
|
87
|
+
exit
|
|
88
|
+
end
|
|
89
|
+
opts.on_tail("--help", "You're looking at it") do
|
|
90
|
+
puts opts.help
|
|
91
|
+
exit
|
|
92
|
+
end
|
|
93
|
+
end.parse!
|
|
94
|
+
|
|
95
|
+
# Whatever is left after option parsing is the FILE arguments
|
|
96
|
+
@paths += args
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def parse_args_from_profile(profile)
|
|
100
|
+
return unless File.exist?('cucumber.yml')
|
|
101
|
+
require 'yaml'
|
|
102
|
+
cucumber_yml = YAML::load(IO.read('cucumber.yml'))
|
|
103
|
+
args_from_yml = cucumber_yml[profile]
|
|
104
|
+
raise "Expected to find a String, got #{args_from_yml.inspect}. cucumber.yml:\n#{cucumber_yml}" unless String === args_from_yml
|
|
105
|
+
parse_options!(args_from_yml.split(' '))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def execute!(step_mother, executor, features)
|
|
109
|
+
Cucumber.load_language(@options[:lang])
|
|
110
|
+
executor.formatter = formatter(step_mother)
|
|
111
|
+
require_files
|
|
112
|
+
load_plain_text_features(features)
|
|
113
|
+
executor.line = @options[:line].to_i if @options[:line]
|
|
114
|
+
executor.visit_features(features)
|
|
115
|
+
exit 1 if executor.failed
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
# Requires files - typically step files and ruby feature files.
|
|
121
|
+
def require_files
|
|
122
|
+
ARGV.clear # Shut up RSpec
|
|
123
|
+
require "cucumber/treetop_parser/feature_#{@options[:lang]}"
|
|
124
|
+
require "cucumber/treetop_parser/feature_parser"
|
|
125
|
+
|
|
126
|
+
requires = @options[:require] || feature_dirs
|
|
127
|
+
libs = requires.map do |path|
|
|
128
|
+
path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
|
|
129
|
+
File.directory?(path) ? Dir["#{path}/**/*.rb"] : path
|
|
130
|
+
end.flatten.uniq
|
|
131
|
+
libs.each do |lib|
|
|
132
|
+
begin
|
|
133
|
+
require lib
|
|
134
|
+
rescue LoadError => e
|
|
135
|
+
e.message << "\nFailed to load #{lib}"
|
|
136
|
+
raise e
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def feature_files
|
|
142
|
+
potential_feature_files = @paths.map do |path|
|
|
143
|
+
path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
|
|
144
|
+
File.directory?(path) ? Dir["#{path}/**/*.feature"] : path
|
|
145
|
+
end.flatten.uniq
|
|
146
|
+
|
|
147
|
+
@options[:excludes].each do |exclude|
|
|
148
|
+
potential_feature_files.reject! do |path|
|
|
149
|
+
path =~ /#{Regexp.escape(exclude)}/
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
potential_feature_files
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def feature_dirs
|
|
157
|
+
feature_files.map{|f| File.directory?(f) ? f : File.dirname(f)}.uniq
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def load_plain_text_features(features)
|
|
161
|
+
parser = TreetopParser::FeatureParser.new
|
|
162
|
+
|
|
163
|
+
feature_files.each do |f|
|
|
164
|
+
features << parser.parse_feature(f)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def formatter(step_mother)
|
|
169
|
+
case @options[:format]
|
|
170
|
+
when 'pretty'
|
|
171
|
+
Formatters::PrettyFormatter.new(@options[:out], step_mother, @options)
|
|
172
|
+
when 'progress'
|
|
173
|
+
Formatters::ProgressFormatter.new(@options[:out])
|
|
174
|
+
when 'profile'
|
|
175
|
+
Formatters::ProfileFormatter.new(@options[:out], step_mother)
|
|
176
|
+
when 'html'
|
|
177
|
+
Formatters::HtmlFormatter.new(@options[:out], step_mother)
|
|
178
|
+
else
|
|
179
|
+
raise "Unknown formatter: #{@options[:format]}"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
extend Cucumber::StepMethods
|
|
187
|
+
Cucumber::CLI.step_mother = step_mother
|
|
188
|
+
Cucumber::CLI.executor = executor
|
|
189
|
+
|
|
190
|
+
extend Cucumber::Tree
|
|
191
|
+
Cucumber::CLI.features = features
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
attr_accessor :name
|
|
10
|
+
|
|
11
|
+
def call_in(obj, *args)
|
|
12
|
+
obj.extend(mod)
|
|
13
|
+
a = arity == -1 ? 0 : arity
|
|
14
|
+
if self != StepMother::PENDING && args.length != a
|
|
15
|
+
# We have to manually raise when the block has arity -1 (no pipes)
|
|
16
|
+
raise ArityMismatchError.new("expected #{arity == -1 ? 0 : arity} block argument(s), got #{args.length}")
|
|
17
|
+
else
|
|
18
|
+
obj.__send__(meth, *args)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def arity2
|
|
23
|
+
arity == -1 ? 0 : arity
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_backtrace_line
|
|
27
|
+
"#{file_colon_line}:in `#{name}'"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_comment_line
|
|
31
|
+
"# #{file_colon_line}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def file_colon_line
|
|
35
|
+
path, line = *to_s.match(/[\d\w]+@(.*):(.*)>/)[1..2]
|
|
36
|
+
path = File.expand_path(path)
|
|
37
|
+
pwd = Dir.pwd
|
|
38
|
+
path = path[pwd.length+1..-1]
|
|
39
|
+
"#{path}:#{line}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def meth
|
|
43
|
+
@meth ||= "__cucumber_#{object_id}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def mod
|
|
47
|
+
p = self
|
|
48
|
+
m = meth
|
|
49
|
+
@mod ||= Module.new do
|
|
50
|
+
define_method(m, &p)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def gzub(regexp, format=nil, &proc)
|
|
3
|
+
md = match(regexp)
|
|
4
|
+
raise "#{self.inspect} doesn't match #{regexp.inspect}" if md.nil?
|
|
5
|
+
|
|
6
|
+
s = dup
|
|
7
|
+
pos = 0
|
|
8
|
+
md.captures.each_with_index do |m, n|
|
|
9
|
+
replacement = if block_given?
|
|
10
|
+
proc.call(m)
|
|
11
|
+
else
|
|
12
|
+
format % m
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
if md.offset(n+1)[0]
|
|
16
|
+
s[md.offset(n+1)[0] + pos, m.length] = replacement
|
|
17
|
+
pos += replacement.length - m.length
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
s
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
require 'cucumber/core_ext/proc'
|
|
2
|
+
|
|
3
|
+
module Cucumber
|
|
4
|
+
class Executor
|
|
5
|
+
attr_reader :failed
|
|
6
|
+
attr_accessor :formatter
|
|
7
|
+
|
|
8
|
+
def line=(line)
|
|
9
|
+
@line = line
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(step_mother)
|
|
13
|
+
@world_proc = lambda do
|
|
14
|
+
Object.new
|
|
15
|
+
end
|
|
16
|
+
@before_scenario_procs = []
|
|
17
|
+
@after_scenario_procs = []
|
|
18
|
+
@after_step_procs = []
|
|
19
|
+
@step_mother = step_mother
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def register_world_proc(&proc)
|
|
23
|
+
@world_proc = proc
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def register_before_scenario_proc(&proc)
|
|
27
|
+
proc.extend(CoreExt::CallIn)
|
|
28
|
+
@before_scenario_procs << proc
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def register_after_scenario_proc(&proc)
|
|
32
|
+
proc.extend(CoreExt::CallIn)
|
|
33
|
+
@after_scenario_procs << proc
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def register_after_step_proc(&proc)
|
|
37
|
+
proc.extend(CoreExt::CallIn)
|
|
38
|
+
@after_step_procs << proc
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def visit_features(features)
|
|
42
|
+
raise "Line number can only be specified when there is 1 feature. There were #{features.length}." if @line && features.length != 1
|
|
43
|
+
formatter.visit_features(features) if formatter.respond_to?(:visit_features)
|
|
44
|
+
features.accept(self)
|
|
45
|
+
formatter.dump
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def visit_feature(feature)
|
|
49
|
+
formatter.visit_feature(feature) if formatter.respond_to?(:visit_feature)
|
|
50
|
+
feature.accept(self)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def visit_header(header)
|
|
54
|
+
formatter.header_executing(header) if formatter.respond_to?(:header_executing)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def visit_row_scenario(scenario)
|
|
58
|
+
visit_scenario(scenario)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def visit_regular_scenario(scenario)
|
|
62
|
+
visit_scenario(scenario)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def visit_scenario(scenario)
|
|
66
|
+
if accept?(scenario)
|
|
67
|
+
@error = nil
|
|
68
|
+
@pending = nil
|
|
69
|
+
|
|
70
|
+
@world = @world_proc.call
|
|
71
|
+
@world.extend(Spec::Matchers) if defined?(Spec::Matchers)
|
|
72
|
+
define_step_call_methods(@world)
|
|
73
|
+
|
|
74
|
+
formatter.scenario_executing(scenario) if formatter.respond_to?(:scenario_executing)
|
|
75
|
+
@before_scenario_procs.each{|p| p.call_in(@world, *[])}
|
|
76
|
+
scenario.accept(self)
|
|
77
|
+
@after_scenario_procs.each{|p| p.call_in(@world, *[])}
|
|
78
|
+
formatter.scenario_executed(scenario) if formatter.respond_to?(:scenario_executed)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def accept?(scenario)
|
|
83
|
+
@line.nil? || scenario.at_line?(@line)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def visit_row_step(step)
|
|
87
|
+
visit_step(step)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def visit_regular_step(step)
|
|
91
|
+
visit_step(step)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def visit_step(step)
|
|
95
|
+
unless @pending || @error
|
|
96
|
+
begin
|
|
97
|
+
regexp, args, proc = step.regexp_args_proc(@step_mother)
|
|
98
|
+
formatter.step_executing(step, regexp, args) if formatter.respond_to?(:step_executing)
|
|
99
|
+
step.execute_in(@world, regexp, args, proc)
|
|
100
|
+
@after_step_procs.each{|p| p.call_in(@world, *[])}
|
|
101
|
+
formatter.step_passed(step, regexp, args)
|
|
102
|
+
rescue Pending
|
|
103
|
+
record_pending_step(step, regexp, args)
|
|
104
|
+
rescue => e
|
|
105
|
+
@failed = true
|
|
106
|
+
@error = step.error = e
|
|
107
|
+
formatter.step_failed(step, regexp, args)
|
|
108
|
+
end
|
|
109
|
+
else
|
|
110
|
+
begin
|
|
111
|
+
regexp, args, proc = step.regexp_args_proc(@step_mother)
|
|
112
|
+
step.execute_in(@world, regexp, args, proc)
|
|
113
|
+
formatter.step_skipped(step, regexp, args)
|
|
114
|
+
rescue Pending
|
|
115
|
+
record_pending_step(step, regexp, args)
|
|
116
|
+
rescue Exception
|
|
117
|
+
formatter.step_skipped(step, regexp, args)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def record_pending_step(step, regexp, args)
|
|
123
|
+
@pending = true
|
|
124
|
+
formatter.step_pending(step, regexp, args)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def define_step_call_methods(world)
|
|
128
|
+
world.instance_variable_set('@__executor', self)
|
|
129
|
+
world.instance_eval do
|
|
130
|
+
class << self
|
|
131
|
+
def run_step(name)
|
|
132
|
+
_, args, proc = @__executor.instance_variable_get(:@step_mother).regexp_args_proc(name)
|
|
133
|
+
proc.call_in(self, *args)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
%w{given when then and but}.each do |keyword|
|
|
137
|
+
alias_method Cucumber.language[keyword], :run_step
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|