aslakhellesoy-cucumber 0.1.5 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +228 -0
- data/License.txt +20 -0
- data/Manifest.txt +226 -0
- data/README.txt +41 -0
- data/Rakefile +9 -0
- data/TODO.txt +26 -0
- data/bin/cucumber +5 -0
- data/config/hoe.rb +69 -0
- data/config/requirements.rb +15 -0
- data/cucumber.yml +1 -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/step_definitons/calculator_steps.rb +43 -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/step_definitons/hello_steps.rb +25 -0
- data/examples/cs/features/step_definitons/tree_steps.rb +14 -0
- data/examples/cs/features/tree.feature +9 -0
- data/examples/cs/src/Hello.cs +18 -0
- data/examples/dos_line_endings/Rakefile +6 -0
- data/examples/dos_line_endings/features/dos_line_endings.feature +9 -0
- data/examples/i18n/README.textile +18 -0
- data/examples/i18n/Rakefile +16 -0
- data/examples/i18n/ar/Rakefile +6 -0
- data/examples/i18n/ar/features/addition.feature +17 -0
- data/examples/i18n/ar/features/step_definitons/calculator_steps.rb +31 -0
- data/examples/i18n/ar/lib/calculator.rb +10 -0
- data/examples/i18n/da/Rakefile +6 -0
- data/examples/i18n/da/features/step_definitons/kalkulator_steps.rb +22 -0
- data/examples/i18n/da/features/summering.feature +17 -0
- data/examples/i18n/da/lib/kalkulator.rb +11 -0
- data/examples/i18n/en/Rakefile +5 -0
- data/examples/i18n/en/features/addition.feature +17 -0
- data/examples/i18n/en/features/division.feature +10 -0
- data/examples/i18n/en/features/step_definitons/calculator_steps.rb +31 -0
- data/examples/i18n/en/lib/calculator.rb +14 -0
- data/examples/i18n/es/Rakefile +6 -0
- data/examples/i18n/es/features/adicion.feature +17 -0
- data/examples/i18n/es/features/step_definitons/calculador_steps.rb +22 -0
- data/examples/i18n/es/lib/calculador.rb +11 -0
- data/examples/i18n/et/Rakefile +6 -0
- data/examples/i18n/et/features/liitmine.feature +17 -0
- data/examples/i18n/et/features/step_definitions/kalkulaator_steps.rb +26 -0
- data/examples/i18n/et/lib/kalkulaator.rb +10 -0
- data/examples/i18n/fr/Rakefile +6 -0
- data/examples/i18n/fr/features/addition.feature +13 -0
- data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +22 -0
- data/examples/i18n/fr/lib/calculatrice.rb +10 -0
- data/examples/i18n/id/Rakefile +6 -0
- data/examples/i18n/id/features/addition.feature +17 -0
- data/examples/i18n/id/features/division.feature +10 -0
- data/examples/i18n/id/features/step_definitons/calculator_steps.rb +31 -0
- data/examples/i18n/id/lib/calculator.rb +14 -0
- data/examples/i18n/it/Rakefile +6 -0
- data/examples/i18n/it/features/somma.feature +10 -0
- data/examples/i18n/it/features/step_definitons/calcolatrice_steps.rb +22 -0
- data/examples/i18n/it/lib/calcolatrice.rb +11 -0
- data/examples/i18n/ja/README.txt +5 -0
- data/examples/i18n/ja/Rakefile +6 -0
- data/examples/i18n/ja/features/addition.feature +17 -0
- data/examples/i18n/ja/features/division.feature +10 -0
- data/examples/i18n/ja/features/step_definitons/calculator_steps.rb +30 -0
- data/examples/i18n/ja/lib/calculator.rb +14 -0
- data/examples/i18n/no/Rakefile +6 -0
- data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +22 -0
- data/examples/i18n/no/features/summering.feature +17 -0
- data/examples/i18n/no/lib/kalkulator.rb +11 -0
- data/examples/i18n/pt/Rakefile +6 -0
- data/examples/i18n/pt/features/adicao.feature +10 -0
- data/examples/i18n/pt/features/step_definitions/calculadora_steps.rb +22 -0
- data/examples/i18n/pt/lib/calculadora.rb +10 -0
- data/examples/i18n/ro/Rakefile +6 -0
- data/examples/i18n/ro/features/step_definitons/calculator_steps.rb +22 -0
- data/examples/i18n/ro/features/suma.feature +10 -0
- data/examples/i18n/ro/lib/calculator.rb +11 -0
- data/examples/i18n/se/Rakefile +6 -0
- data/examples/i18n/se/features/step_definitons/kalkulator_steps.rb +22 -0
- data/examples/i18n/se/features/summering.feature +17 -0
- data/examples/i18n/se/lib/kalkulator.rb +11 -0
- data/examples/i18n/zh-CN/Rakefile +6 -0
- data/examples/i18n/zh-CN/features/addition.feature +17 -0
- data/examples/i18n/zh-CN/features/step_definitons/calculator_steps.rb +24 -0
- data/examples/i18n/zh-CN/lib/calculator.rb +10 -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/step_definitons/hello_steps.rb +25 -0
- data/examples/java/features/step_definitons/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/selenium/Rakefile +6 -0
- data/examples/selenium/features/search.feature +9 -0
- data/examples/selenium/features/step_definitons/stories_steps.rb +41 -0
- data/examples/tickets/Rakefile +11 -0
- data/examples/tickets/cucumber.yml +2 -0
- data/examples/tickets/features/step_definitons/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/step_definitons/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 +41 -0
- data/lib/autotest/cucumber.rb +6 -0
- data/lib/autotest/cucumber_mixin.rb +109 -0
- data/lib/autotest/cucumber_rails.rb +6 -0
- data/lib/autotest/cucumber_rails_rspec.rb +6 -0
- data/lib/autotest/cucumber_rspec.rb +6 -0
- data/lib/autotest/discover.rb +9 -0
- data/lib/cucumber.rb +39 -0
- data/lib/cucumber/broadcaster.rb +20 -0
- data/lib/cucumber/cli.rb +269 -0
- data/lib/cucumber/core_ext/proc.rb +54 -0
- data/lib/cucumber/core_ext/string.rb +22 -0
- data/lib/cucumber/executor.rb +170 -0
- data/lib/cucumber/formatters.rb +1 -0
- data/lib/cucumber/formatters/ansicolor.rb +111 -0
- data/lib/cucumber/formatters/autotest_formatter.rb +23 -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 +234 -0
- data/lib/cucumber/formatters/profile_formatter.rb +92 -0
- data/lib/cucumber/formatters/progress_formatter.rb +58 -0
- data/lib/cucumber/languages.yml +235 -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 +101 -0
- data/lib/cucumber/step_methods.rb +49 -0
- data/lib/cucumber/step_mother.rb +89 -0
- data/lib/cucumber/tree.rb +18 -0
- data/lib/cucumber/tree/feature.rb +61 -0
- data/lib/cucumber/tree/features.rb +21 -0
- data/lib/cucumber/tree/given_scenario.rb +13 -0
- data/lib/cucumber/tree/scenario.rb +158 -0
- data/lib/cucumber/tree/step.rb +134 -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 +206 -0
- data/lib/cucumber/treetop_parser/feature_ar.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_cy.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_da.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_de.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_en-tx.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_en.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_es.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_et.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_fr.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_id.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_it.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_ja.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_nl.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_no.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_parser.rb +34 -0
- data/lib/cucumber/treetop_parser/feature_pl.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_pt.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_ro.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_ro2.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_ru.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_se.rb +1591 -0
- data/lib/cucumber/treetop_parser/feature_zh-CN.rb +1591 -0
- data/lib/cucumber/version.rb +9 -0
- data/rails_generators/cucumber/USAGE +11 -0
- data/rails_generators/cucumber/cucumber_generator.rb +30 -0
- data/rails_generators/cucumber/templates/cucumber +7 -0
- data/rails_generators/cucumber/templates/cucumber.rake +7 -0
- data/rails_generators/cucumber/templates/env.rb +8 -0
- data/rails_generators/cucumber/templates/webrat_steps.rb +46 -0
- data/rails_generators/feature/USAGE +12 -0
- data/rails_generators/feature/feature_generator.rb +16 -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/broadcaster_spec.rb +27 -0
- data/spec/cucumber/cli_spec.rb +242 -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 +222 -0
- data/spec/cucumber/formatters/ansicolor_spec.rb +35 -0
- data/spec/cucumber/formatters/autotest_formatter_spec.rb +26 -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 +204 -0
- data/spec/cucumber/formatters/profile_formatter_spec.rb +192 -0
- data/spec/cucumber/formatters/progress_formatter_spec.rb +65 -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 +19 -0
- data/spec/cucumber/step_mother_spec.rb +74 -0
- data/spec/cucumber/tree/feature_spec.rb +12 -0
- data/spec/cucumber/tree/row_scenario_spec.rb +25 -0
- data/spec/cucumber/tree/scenario_spec.rb +76 -0
- data/spec/cucumber/tree/step_spec.rb +50 -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 +98 -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 +17 -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 +151 -35
@@ -0,0 +1,41 @@
|
|
1
|
+
class FeatureCompiler
|
2
|
+
def initialize
|
3
|
+
require 'yaml'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
@tt = PLATFORM =~ /mswin|mingw/ ? 'tt.bat' : 'tt'
|
7
|
+
|
8
|
+
@template = ERB.new(IO.read(File.dirname(__FILE__) + '/../lib/cucumber/treetop_parser/feature.treetop.erb'))
|
9
|
+
@langs = YAML.load_file(File.dirname(__FILE__) + '/../lib/cucumber/languages.yml')
|
10
|
+
end
|
11
|
+
|
12
|
+
def compile_all
|
13
|
+
@langs.keys.each do |lang|
|
14
|
+
compile(lang)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def compile(lang)
|
19
|
+
words = @langs['en'].merge(@langs[lang]) # Use English words if languages.yml is missing a word
|
20
|
+
grammar_file = File.dirname(__FILE__) + "/../lib/cucumber/treetop_parser/feature_#{lang}.treetop"
|
21
|
+
ruby_file = File.dirname(__FILE__) + "/../lib/cucumber/treetop_parser/feature_#{lang}.rb"
|
22
|
+
grammar = @template.result(binding)
|
23
|
+
File.open(grammar_file, "wb") do |io|
|
24
|
+
io.write(grammar)
|
25
|
+
end
|
26
|
+
sh "#{@tt} #{grammar_file}"
|
27
|
+
FileUtils.rm(grammar_file)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
namespace :treetop do
|
32
|
+
desc 'Compile the grammar for all languages in languages.yml'
|
33
|
+
task :compile do
|
34
|
+
FeatureCompiler.new.compile_all
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Compile the English grammar'
|
38
|
+
task :compile_en do
|
39
|
+
FeatureCompiler.new.compile('en')
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'autotest'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Autotest::CucumberMixin
|
5
|
+
def self.included(receiver)
|
6
|
+
receiver::ALL_HOOKS << [:run_features, :ran_features]
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :scenarios_to_run
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super
|
13
|
+
reset_features
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
hook :initialize
|
18
|
+
reset
|
19
|
+
reset_features
|
20
|
+
add_sigint_handler
|
21
|
+
|
22
|
+
self.last_mtime = Time.now if $f
|
23
|
+
|
24
|
+
loop do # ^c handler
|
25
|
+
begin
|
26
|
+
get_to_green
|
27
|
+
if self.tainted then
|
28
|
+
rerun_all_tests
|
29
|
+
rerun_all_features if all_good
|
30
|
+
else
|
31
|
+
hook :all_good
|
32
|
+
end
|
33
|
+
wait_for_changes
|
34
|
+
# Once tests and features are green, reset features every
|
35
|
+
# time a file is changed to see if anything breaks.
|
36
|
+
reset_features
|
37
|
+
rescue Interrupt
|
38
|
+
break if self.wants_to_quit
|
39
|
+
reset
|
40
|
+
reset_features
|
41
|
+
end
|
42
|
+
end
|
43
|
+
hook :quit
|
44
|
+
end
|
45
|
+
|
46
|
+
def all_features_good
|
47
|
+
scenarios_to_run == []
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_to_green
|
51
|
+
begin
|
52
|
+
super
|
53
|
+
run_features
|
54
|
+
wait_for_changes unless all_features_good
|
55
|
+
end until all_features_good
|
56
|
+
end
|
57
|
+
|
58
|
+
def rerun_all_features
|
59
|
+
reset_features
|
60
|
+
run_features
|
61
|
+
end
|
62
|
+
|
63
|
+
def reset_features
|
64
|
+
self.scenarios_to_run = :all
|
65
|
+
end
|
66
|
+
|
67
|
+
def run_features
|
68
|
+
hook :run_features
|
69
|
+
Tempfile.open('autotest-cucumber') do |dirty_scenarios_file|
|
70
|
+
cmd = self.make_cucumber_cmd self.scenarios_to_run, dirty_scenarios_file.path
|
71
|
+
return if cmd.empty?
|
72
|
+
puts cmd unless $q
|
73
|
+
system cmd
|
74
|
+
self.scenarios_to_run = dirty_scenarios_file.readlines.map { |l| l.chomp }
|
75
|
+
self.tainted = true unless self.scenarios_to_run == []
|
76
|
+
end
|
77
|
+
hook :ran_features
|
78
|
+
end
|
79
|
+
|
80
|
+
def make_cucumber_cmd(scenarios_to_run, dirty_scenarios_filename)
|
81
|
+
return '' if scenarios_to_run == []
|
82
|
+
|
83
|
+
profiles = YAML.load_file("cucumber.yml").keys rescue []
|
84
|
+
|
85
|
+
profile ||= "autotest-all" if profiles.include?("autotest-all") and scenarios_to_run == :all
|
86
|
+
profile ||= "autotest" if profiles.include?("autotest")
|
87
|
+
profile ||= nil
|
88
|
+
|
89
|
+
if profile
|
90
|
+
args = ["--profile", profile]
|
91
|
+
else
|
92
|
+
args = %w{features --format} << (scenarios_to_run == :all ? "progress" : "pretty")
|
93
|
+
end
|
94
|
+
args += %w{--format autotest --out} << dirty_scenarios_filename
|
95
|
+
args = args.join(' ')
|
96
|
+
|
97
|
+
if scenarios_to_run == :all
|
98
|
+
scenario_args = nil
|
99
|
+
else
|
100
|
+
scenario_args = scenarios_to_run.map { |s| "-s '#{s}'" }.join(' ')
|
101
|
+
end
|
102
|
+
|
103
|
+
return "#{cucumber} #{args} #{scenario_args}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def cucumber
|
107
|
+
File.exist?("script/cucumber") ? "script/cucumber" : "cucumber"
|
108
|
+
end
|
109
|
+
end
|
data/lib/cucumber.rb
ADDED
@@ -0,0 +1,39 @@
|
|
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
|
+
require 'cucumber/broadcaster'
|
16
|
+
|
17
|
+
$KCODE='u'
|
18
|
+
require 'jcode'
|
19
|
+
|
20
|
+
module Cucumber
|
21
|
+
LANGUAGE_FILE = File.expand_path(File.dirname(__FILE__) + '/cucumber/languages.yml')
|
22
|
+
|
23
|
+
class << self
|
24
|
+
attr_reader :language
|
25
|
+
|
26
|
+
def load_language(lang)
|
27
|
+
@language = config[lang]
|
28
|
+
end
|
29
|
+
|
30
|
+
def languages
|
31
|
+
config.keys.sort
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
require 'yaml'
|
36
|
+
@config ||= YAML.load_file(LANGUAGE_FILE)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Cucumber
|
2
|
+
class Broadcaster
|
3
|
+
|
4
|
+
def initialize(receivers = [])
|
5
|
+
@receivers = receivers
|
6
|
+
end
|
7
|
+
|
8
|
+
def register(receiver)
|
9
|
+
@receivers << receiver
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(method_name, *args)
|
13
|
+
@receivers.each do |receiver|
|
14
|
+
r = (receiver == STDOUT) ? Kernel: receiver # Needed to make colors work on Windows
|
15
|
+
r.__send__(method_name, *args) if receiver.respond_to?(method_name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/lib/cucumber/cli.rb
ADDED
@@ -0,0 +1,269 @@
|
|
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 autotest}
|
27
|
+
DEFAULT_FORMAT = 'pretty'
|
28
|
+
|
29
|
+
def initialize(out_stream = STDOUT, error_stream = STDERR)
|
30
|
+
@out_stream = out_stream
|
31
|
+
@error_stream = error_stream
|
32
|
+
@paths = []
|
33
|
+
@options = {
|
34
|
+
:require => nil,
|
35
|
+
:lang => 'en',
|
36
|
+
:dry_run => false,
|
37
|
+
:source => true,
|
38
|
+
:snippets => true,
|
39
|
+
:formats => {},
|
40
|
+
:excludes => [],
|
41
|
+
:scenario_names => nil
|
42
|
+
}
|
43
|
+
@active_format = DEFAULT_FORMAT
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_options!(args)
|
47
|
+
return parse_args_from_profile('default') if args.empty?
|
48
|
+
args.extend(OptionParser::Arguable)
|
49
|
+
|
50
|
+
args.options do |opts|
|
51
|
+
opts.banner = "Usage: cucumber [options] FILES|DIRS"
|
52
|
+
opts.on("-r LIBRARY|DIR", "--require LIBRARY|DIR", "Require files before executing the features.",
|
53
|
+
"If this option is not specified, all *.rb files that",
|
54
|
+
"are siblings or below the features will be autorequired",
|
55
|
+
"This option can be specified multiple times.") do |v|
|
56
|
+
@options[:require] ||= []
|
57
|
+
@options[:require] << v
|
58
|
+
end
|
59
|
+
opts.on("-l LINE", "--line LINE", "Only execute the scenario at the given line") do |v|
|
60
|
+
@options[:line] = v
|
61
|
+
end
|
62
|
+
opts.on("-s SCENARIO", "--scenario SCENARIO", "Only execute the scenario with the given name.",
|
63
|
+
"If this option is given more than once, run all",
|
64
|
+
"the specified scenarios.") do |v|
|
65
|
+
@options[:scenario_names] ||= []
|
66
|
+
@options[:scenario_names] << v
|
67
|
+
end
|
68
|
+
opts.on("-a LANG", "--language LANG", "Specify language for features (Default: #{@options[:lang]})",
|
69
|
+
"Available languages: #{Cucumber.languages.join(", ")}",
|
70
|
+
"Look at #{Cucumber::LANGUAGE_FILE} for keywords") do |v|
|
71
|
+
@options[:lang] = v
|
72
|
+
end
|
73
|
+
opts.on("-f FORMAT", "--format FORMAT", "How to format features (Default: #{DEFAULT_FORMAT})",
|
74
|
+
"Available formats: #{FORMATS.join(", ")}",
|
75
|
+
"This option can be specified multiple times.") do |v|
|
76
|
+
unless FORMATS.index(v)
|
77
|
+
@error_stream.puts "Invalid format: #{v}\n"
|
78
|
+
@error_stream.puts opts.help
|
79
|
+
exit 1
|
80
|
+
end
|
81
|
+
@options[:formats][v] ||= []
|
82
|
+
@options[:formats][v] << @out_stream
|
83
|
+
@active_format = v
|
84
|
+
end
|
85
|
+
opts.on("-o", "--out FILE", "Write output to a file instead of @out_stream.",
|
86
|
+
"This option can be specified multiple times, and applies to the previously",
|
87
|
+
"specified --format.") do |v|
|
88
|
+
@options[:formats][@active_format] ||= []
|
89
|
+
if @options[:formats][@active_format].last == @out_stream
|
90
|
+
@options[:formats][@active_format][-1] = File.open(v, 'w')
|
91
|
+
else
|
92
|
+
@options[:formats][@active_format] << File.open(v, 'w')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
opts.on("-c", "--[no-]color", "Use ANSI color in the output, if formatters use it. If",
|
96
|
+
"these options are given multiple times, the last one is",
|
97
|
+
"used. If neither --color or --no-color is given cucumber",
|
98
|
+
"decides based on your platform and the output destination") do |v|
|
99
|
+
@options[:color] = v
|
100
|
+
end
|
101
|
+
opts.on("-e", "--exclude PATTERN", "Don't run features matching a pattern") do |v|
|
102
|
+
@options[:excludes] << v
|
103
|
+
end
|
104
|
+
opts.on("-p", "--profile PROFILE", "Pull commandline arguments from cucumber.yml.") do |v|
|
105
|
+
parse_args_from_profile(v)
|
106
|
+
end
|
107
|
+
opts.on("-d", "--dry-run", "Invokes formatters without executing the steps.") do
|
108
|
+
@options[:dry_run] = true
|
109
|
+
end
|
110
|
+
opts.on("-n", "--no-source", "Don't show the file and line of the step definition with the steps.") do
|
111
|
+
@options[:source] = false
|
112
|
+
end
|
113
|
+
opts.on("-i", "--no-snippets", "Don't show the snippets for pending steps") do
|
114
|
+
@options[:snippets] = false
|
115
|
+
end
|
116
|
+
opts.on("-q", "--quiet", "Don't show any development aid information") do
|
117
|
+
@options[:snippets] = false
|
118
|
+
@options[:source] = false
|
119
|
+
end
|
120
|
+
opts.on_tail("--version", "Show version") do
|
121
|
+
puts VERSION::STRING
|
122
|
+
exit
|
123
|
+
end
|
124
|
+
opts.on_tail("--help", "You're looking at it") do
|
125
|
+
puts opts.help
|
126
|
+
exit
|
127
|
+
end
|
128
|
+
end.parse!
|
129
|
+
|
130
|
+
if @options[:formats].empty?
|
131
|
+
@options[:formats][DEFAULT_FORMAT] = [@out_stream]
|
132
|
+
end
|
133
|
+
|
134
|
+
# Whatever is left after option parsing is the FILE arguments
|
135
|
+
@paths += args
|
136
|
+
end
|
137
|
+
|
138
|
+
def parse_args_from_profile(profile)
|
139
|
+
unless File.exist?('cucumber.yml')
|
140
|
+
return exit_with_error("cucumber.yml was not found. Please define your '#{profile}' and other profiles in cucumber.yml.\n"+
|
141
|
+
"Type 'cucumber --help' for usage.\n")
|
142
|
+
end
|
143
|
+
|
144
|
+
require 'yaml'
|
145
|
+
cucumber_yml = YAML::load(IO.read('cucumber.yml'))
|
146
|
+
args_from_yml = cucumber_yml[profile]
|
147
|
+
if args_from_yml.nil?
|
148
|
+
exit_with_error <<-END_OF_ERROR
|
149
|
+
Could not find profile: '#{profile}'
|
150
|
+
|
151
|
+
Defined profiles in cucumber.yml:
|
152
|
+
* #{cucumber_yml.keys.join("\n * ")}
|
153
|
+
END_OF_ERROR
|
154
|
+
elsif !args_from_yml.is_a?(String)
|
155
|
+
exit_with_error "Profiles must be defined as a String. The '#{profile}' profile was #{args_from_yml.inspect} (#{args_from_yml.class}).\n"
|
156
|
+
else
|
157
|
+
parse_options!(args_from_yml.split(' '))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def execute!(step_mother, executor, features)
|
162
|
+
Term::ANSIColor.coloring = @options[:color] unless @options[:color].nil?
|
163
|
+
Cucumber.load_language(@options[:lang])
|
164
|
+
executor.formatters = build_formatter_broadcaster(step_mother)
|
165
|
+
require_files
|
166
|
+
load_plain_text_features(features)
|
167
|
+
executor.line = @options[:line].to_i if @options[:line]
|
168
|
+
executor.scenario_names = @options[:scenario_names] if @options[:scenario_names]
|
169
|
+
executor.visit_features(features)
|
170
|
+
exit 1 if executor.failed
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
# Requires files - typically step files and ruby feature files.
|
176
|
+
def require_files
|
177
|
+
ARGV.clear # Shut up RSpec
|
178
|
+
require "cucumber/treetop_parser/feature_#{@options[:lang]}"
|
179
|
+
require "cucumber/treetop_parser/feature_parser"
|
180
|
+
|
181
|
+
requires = @options[:require] || feature_dirs
|
182
|
+
libs = requires.map do |path|
|
183
|
+
path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
|
184
|
+
File.directory?(path) ? Dir["#{path}/**/*.rb"] : path
|
185
|
+
end.flatten.uniq
|
186
|
+
libs.each do |lib|
|
187
|
+
begin
|
188
|
+
require lib
|
189
|
+
rescue LoadError => e
|
190
|
+
e.message << "\nFailed to load #{lib}"
|
191
|
+
raise e
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def feature_files
|
197
|
+
potential_feature_files = @paths.map do |path|
|
198
|
+
path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
|
199
|
+
path = path.chomp('/')
|
200
|
+
File.directory?(path) ? Dir["#{path}/**/*.feature"] : path
|
201
|
+
end.flatten.uniq
|
202
|
+
|
203
|
+
@options[:excludes].each do |exclude|
|
204
|
+
potential_feature_files.reject! do |path|
|
205
|
+
path =~ /#{Regexp.escape(exclude)}/
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
potential_feature_files
|
210
|
+
end
|
211
|
+
|
212
|
+
def feature_dirs
|
213
|
+
feature_files.map{|f| File.directory?(f) ? f : File.dirname(f)}.uniq
|
214
|
+
end
|
215
|
+
|
216
|
+
def load_plain_text_features(features)
|
217
|
+
parser = TreetopParser::FeatureParser.new
|
218
|
+
|
219
|
+
feature_files.each do |f|
|
220
|
+
features << parser.parse_feature(f)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def build_formatter_broadcaster(step_mother)
|
225
|
+
formatter_broadcaster = Broadcaster.new
|
226
|
+
@options[:formats].each do |format, output_list|
|
227
|
+
output_broadcaster = build_output_broadcaster(output_list)
|
228
|
+
case format
|
229
|
+
when 'pretty'
|
230
|
+
formatter_broadcaster.register(Formatters::PrettyFormatter.new(output_broadcaster, step_mother, @options))
|
231
|
+
when 'progress'
|
232
|
+
formatter_broadcaster.register(Formatters::ProgressFormatter.new(output_broadcaster))
|
233
|
+
when 'profile'
|
234
|
+
formatter_broadcaster.register(Formatters::ProfileFormatter.new(output_broadcaster, step_mother))
|
235
|
+
when 'html'
|
236
|
+
formatter_broadcaster.register(Formatters::HtmlFormatter.new(output_broadcaster, step_mother))
|
237
|
+
when 'autotest'
|
238
|
+
formatter_broadcaster.register(Formatters::AutotestFormatter.new(output_broadcaster))
|
239
|
+
else
|
240
|
+
raise "Unknown formatter: #{@options[:format]}"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
formatter_broadcaster
|
244
|
+
end
|
245
|
+
|
246
|
+
def build_output_broadcaster(output_list)
|
247
|
+
output_broadcaster = Broadcaster.new
|
248
|
+
output_list.each do |output|
|
249
|
+
output_broadcaster.register(output)
|
250
|
+
end
|
251
|
+
output_broadcaster
|
252
|
+
end
|
253
|
+
|
254
|
+
private
|
255
|
+
|
256
|
+
def exit_with_error(error_message)
|
257
|
+
@error_stream << error_message
|
258
|
+
Kernel.exit 1
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
extend Cucumber::StepMethods
|
265
|
+
Cucumber::CLI.step_mother = step_mother
|
266
|
+
Cucumber::CLI.executor = executor
|
267
|
+
|
268
|
+
extend Cucumber::Tree
|
269
|
+
Cucumber::CLI.features = features
|