aslakhellesoy-cucumber 0.3.9.4 → 0.3.9.5

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.
@@ -31,6 +31,15 @@ Given /^the following profiles? (?:are|is) defined:$/ do |profiles|
31
31
  create_file('cucumber.yml', profiles)
32
32
  end
33
33
 
34
+ Given /^I am running "([^\"]*)" in the background$/ do |command|
35
+ run_in_background command
36
+ end
37
+
38
+ Given /^I am not running (?:.*) in the background$/ do
39
+ # no-op
40
+ end
41
+
42
+
34
43
  When /^I run cucumber (.*)$/ do |cucumber_opts|
35
44
  run "#{Cucumber::RUBY_BINARY} #{Cucumber::BINARY} --no-color #{cucumber_opts}"
36
45
  end
@@ -3,6 +3,11 @@ require 'tempfile'
3
3
  require 'spec/expectations'
4
4
  require 'fileutils'
5
5
  require 'forwardable'
6
+ begin
7
+ require 'spork'
8
+ rescue Gem::LoadError => ex
9
+ warn "WARNING: #{ex.message} You need to have the spork gem installed to run the DRb feature properly!"
10
+ end
6
11
 
7
12
  class CucumberWorld
8
13
  extend Forwardable
@@ -52,6 +57,10 @@ class CucumberWorld
52
57
  end
53
58
  end
54
59
 
60
+ def background_jobs
61
+ @background_jobs ||= []
62
+ end
63
+
55
64
  def in_current_dir(&block)
56
65
  Dir.chdir(@current_dir, &block)
57
66
  end
@@ -66,6 +75,27 @@ class CucumberWorld
66
75
  @last_stderr = IO.read(stderr_file.path)
67
76
  end
68
77
 
78
+ def run_in_background(command)
79
+ pid = fork
80
+ in_current_dir do
81
+ if pid
82
+ background_jobs << pid
83
+ else
84
+ #STDOUT.close
85
+ #STDERR.close
86
+ exec command
87
+ end
88
+ end
89
+ end
90
+
91
+ def terminate_background_jobs
92
+ if @background_jobs
93
+ @background_jobs.each do |pid|
94
+ Process.kill(Signal.list['TERM'], pid)
95
+ end
96
+ end
97
+ end
98
+
69
99
  end
70
100
 
71
101
  World do
@@ -77,7 +107,11 @@ Before do
77
107
  FileUtils.mkdir CucumberWorld.working_dir
78
108
  end
79
109
 
110
+ After do
111
+ terminate_background_jobs
112
+ end
113
+
80
114
  Before('@diffxml') do
81
115
  `diffxml --version`
82
116
  raise "Please install diffxml from http://diffxml.sourceforge.net/" if $? != 0
83
- end
117
+ end
@@ -13,6 +13,9 @@ module Cucumber
13
13
  'junit' => 'Cucumber::Formatter::Junit'
14
14
  }
15
15
  DEFAULT_FORMAT = 'pretty'
16
+ DRB_FLAG = '--drb'
17
+ PROFILE_SHORT_FLAG = '-p'
18
+ PROFILE_LONG_FLAG = '--profile'
16
19
 
17
20
  attr_reader :paths
18
21
  attr_reader :options
@@ -28,8 +31,10 @@ module Cucumber
28
31
  end
29
32
 
30
33
  def parse!(args)
31
- @args = args
32
- return parse_args_from_profile('default') if @args.empty?
34
+ @args = args.empty? ? args_from_profile('default') : args
35
+ expand_profiles_into_args
36
+ return if parse_drb
37
+
33
38
  @args.extend(::OptionParser::Arguable)
34
39
 
35
40
  @args.options do |opts|
@@ -100,8 +105,8 @@ module Cucumber
100
105
  opts.on("-e", "--exclude PATTERN", "Don't run feature files or require ruby files matching PATTERN") do |v|
101
106
  @options[:excludes] << Regexp.new(v)
102
107
  end
103
- opts.on("-p", "--profile PROFILE", "Pull commandline arguments from cucumber.yml.") do |v|
104
- parse_args_from_profile(v)
108
+ opts.on(PROFILE_SHORT_FLAG, "#{PROFILE_LONG_FLAG} PROFILE", "Pull commandline arguments from cucumber.yml.") do |v|
109
+ # Processing of this is done previsouly so that the DRb flag can be detected within profiles.
105
110
  end
106
111
  opts.on("-c", "--[no-]color",
107
112
  "Whether or not to use ANSI color in the output. Cucumber decides",
@@ -158,6 +163,9 @@ module Cucumber
158
163
  opts.on("--no-diff", "Disable diff output on failing expectations.") do
159
164
  @options[:diff_enabled] = false
160
165
  end
166
+ opts.on(DRB_FLAG, "Run features against a DRb server. (i.e. with the spork gem)") do
167
+ # Processing of this is done previsouly in order to short circuit args from being lost.
168
+ end
161
169
  opts.on_tail("--version", "Show version.") do
162
170
  @out_stream.puts VERSION::STRING
163
171
  Kernel.exit
@@ -176,7 +184,7 @@ module Cucumber
176
184
  raise("You can't use both --strict and --wip") if @options[:strict] && @options[:wip]
177
185
 
178
186
  # Whatever is left after option parsing is the FILE arguments
179
- @paths += args
187
+ @paths += @args
180
188
  end
181
189
 
182
190
  def verbose?
@@ -199,6 +207,10 @@ module Cucumber
199
207
  @options[:diff_enabled]
200
208
  end
201
209
 
210
+ def drb?
211
+ @drb
212
+ end
213
+
202
214
  def load_language
203
215
  if Cucumber.language_incomplete?(@options[:lang])
204
216
  list_keywords_and_exit(@options[:lang])
@@ -313,7 +325,15 @@ module Cucumber
313
325
  downcase
314
326
  end
315
327
 
316
- def parse_args_from_profile(profile)
328
+ def expand_profiles_into_args
329
+ while (profile_index = @args.index(PROFILE_SHORT_FLAG) || @args.index(PROFILE_LONG_FLAG)) do
330
+ @args.delete_at(profile_index)
331
+ @args[profile_index] = args_from_profile(@args[profile_index])
332
+ @args.flatten!
333
+ end
334
+ end
335
+
336
+ def args_from_profile(profile)
317
337
  unless cucumber_yml.has_key?(profile)
318
338
  raise(<<-END_OF_ERROR)
319
339
  Could not find profile: '#{profile}'
@@ -334,7 +354,7 @@ Defined profiles in cucumber.yml:
334
354
  else
335
355
  raise "The '#{profile}' profile in cucumber.yml was a #{args_from_yml.class}. It must be a String or Array"
336
356
  end
337
- parse!(args_from_yml)
357
+ args_from_yml
338
358
  end
339
359
 
340
360
  def cucumber_yml
@@ -346,7 +366,7 @@ Defined profiles in cucumber.yml:
346
366
  require 'yaml'
347
367
  begin
348
368
  @cucumber_yml = YAML::load(IO.read('cucumber.yml'))
349
- rescue Exception => e
369
+ rescue StandardError => e
350
370
  raise(YmlLoadError,"cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage.\n")
351
371
  end
352
372
 
@@ -370,6 +390,10 @@ Defined profiles in cucumber.yml:
370
390
  Kernel.exit
371
391
  end
372
392
 
393
+ def parse_drb
394
+ @drb = @args.delete(DRB_FLAG) ? true : false
395
+ end
396
+
373
397
  def default_options
374
398
  {
375
399
  :strict => false,
@@ -0,0 +1,21 @@
1
+ require "drb/drb"
2
+ # This code was taken from the RSpec project and slightly modified.
3
+
4
+ module Cucumber
5
+ module Cli
6
+ # Runs features on a DRB server, originally created with Spork compatibility in mind.
7
+ class DRbClient
8
+ def self.run(args, error_stream, out_stream)
9
+ begin
10
+ # See http://redmine.ruby-lang.org/issues/show/496 as to why we specify localhost:0
11
+ DRb.start_service("druby://localhost:0")
12
+ feature_server = DRbObject.new_with_uri("druby://127.0.0.1:8990")
13
+ feature_server.run(args, error_stream, out_stream)
14
+ true
15
+ rescue DRb::DRbConnError
16
+ false
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -5,6 +5,7 @@ require 'cucumber/parser'
5
5
  require 'cucumber/formatter/color_io'
6
6
  require 'cucumber/cli/language_help_formatter'
7
7
  require 'cucumber/cli/configuration'
8
+ require 'cucumber/cli/drb_client'
8
9
 
9
10
  module Cucumber
10
11
  module Cli
@@ -27,11 +28,19 @@ module Cucumber
27
28
 
28
29
  def initialize(args, out_stream = STDOUT, error_stream = STDERR)
29
30
  @args = args
30
- @out_stream = out_stream == STDOUT ? Formatter::ColorIO.new : out_stream
31
+ @out_stream = out_stream #== STDOUT ? Formatter::ColorIO.new : out_stream
31
32
  @error_stream = error_stream
32
33
  end
33
34
 
34
35
  def execute!(step_mother)
36
+ if configuration.drb?
37
+ if DRbClient.run(@args, @error_stream, @out_stream)
38
+ return false
39
+ else
40
+ @out_stream.puts "No DRb server is running. Running features locally:"
41
+ configuration.parse!(@args)
42
+ end
43
+ end
35
44
  configuration.load_language
36
45
  step_mother.options = configuration.options
37
46
 
@@ -16,7 +16,11 @@ module Cucumber
16
16
  def initialize(step_mother, io, options)
17
17
  super(step_mother)
18
18
  @options = options
19
- @builder = Builder::XmlMarkup.new(:target => io, :indent => 2)
19
+ @builder = create_builder(io)
20
+ end
21
+
22
+ def create_builder(io)
23
+ Builder::XmlMarkup.new(:target => io, :indent => 2)
20
24
  end
21
25
 
22
26
  def visit_features(features)
@@ -89,6 +93,7 @@ module Cucumber
89
93
  @listing_background = true
90
94
  @builder.h3 do |h3|
91
95
  @builder.span(keyword, :class => 'keyword')
96
+ @builder.text!(' ')
92
97
  @builder.span(name, :class => 'val')
93
98
  end
94
99
  end
@@ -108,6 +113,7 @@ module Cucumber
108
113
  @listing_background = false
109
114
  @builder.h3 do
110
115
  @builder.span(keyword, :class => 'keyword')
116
+ @builder.text!(' ')
111
117
  @builder.span(name, :class => 'val')
112
118
  end
113
119
  end
@@ -127,7 +133,11 @@ module Cucumber
127
133
  end
128
134
 
129
135
  def visit_examples_name(keyword, name)
130
- @builder.h4("#{keyword} #{name}")
136
+ @builder.h4 do
137
+ @builder.span(keyword, :class => 'keyword')
138
+ @builder.text!(' ')
139
+ @builder.span(name, :class => 'val')
140
+ end
131
141
  end
132
142
 
133
143
  def visit_steps(steps)
@@ -181,7 +191,7 @@ module Cucumber
181
191
 
182
192
  def visit_py_string(string)
183
193
  @builder.pre(:class => 'val') do |pre|
184
- pre << string
194
+ @builder.text!(string)
185
195
  end
186
196
  end
187
197
 
@@ -221,6 +231,7 @@ module Cucumber
221
231
  step_name = step_match.format_args(lambda{|param| %{<span class="param">#{param}</span>}})
222
232
  @builder.div do |div|
223
233
  @builder.span(keyword, :class => 'keyword')
234
+ @builder.text!(' ')
224
235
  @builder.span(:class => 'step val') do |name|
225
236
  name << h(step_name).gsub(/&lt;span class=&quot;(.*?)&quot;&gt;/, '<span class="\1">').gsub(/&lt;\/span&gt;/, '</span>')
226
237
  end
@@ -90,7 +90,7 @@ module Cucumber
90
90
  class_eval <<-EOF, __FILE__, __LINE__ + 1
91
91
  def #{attribute}=(value)
92
92
  @#{attribute} = value
93
- warn("Cucumber::Rake::Task##{attribute} is deprecated and will be removed in 0.4.0. Please use profiles for complex settings: http://wiki.github.com/aslakhellesoy/cucumber/using-rake#profiles")
93
+ warn("\nWARNING: Cucumber::Rake::Task##{attribute} is deprecated and will be removed in 0.4.0. Please use profiles for complex settings: http://wiki.github.com/aslakhellesoy/cucumber/using-rake#profiles\n")
94
94
  end
95
95
  EOF
96
96
  end
@@ -3,7 +3,7 @@ module Cucumber #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
5
  TINY = 9
6
- PATCH = 4 # Set to nil for official release
6
+ PATCH = 5 # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
9
  end
@@ -19,11 +19,17 @@ class CucumberGenerator < Rails::Generator::Base
19
19
  m.gsub_file 'config/database.yml', /\z/, "\ncucumber:\n <<: *TEST"
20
20
 
21
21
  m.directory 'features/support'
22
- m.template 'env.rb', 'features/support/env.rb'
22
+
23
+ if options[:spork]
24
+ m.template 'spork_env.rb', 'features/support/env.rb'
25
+ else
26
+ m.template 'env.rb', 'features/support/env.rb'
27
+ end
28
+
23
29
  m.file 'paths.rb', 'features/support/paths.rb'
24
30
 
25
31
  m.directory 'lib/tasks'
26
- m.file 'cucumber.rake', 'lib/tasks/cucumber.rake'
32
+ m.template 'cucumber.rake', 'lib/tasks/cucumber.rake'
27
33
 
28
34
  m.file 'cucumber', 'script/cucumber', {
29
35
  :chmod => 0755, :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang]
@@ -51,6 +57,10 @@ protected
51
57
  opt.on('--testunit', 'Setup cucumber for use with test/unit') do |value|
52
58
  options[:framework] = :testunit
53
59
  end
60
+
61
+ opt.on('--spork', 'Setup cucumber for use with Spork') do |value|
62
+ options[:spork] = true
63
+ end
54
64
  end
55
65
 
56
66
  end
@@ -5,7 +5,7 @@ begin
5
5
 
6
6
  Cucumber::Rake::Task.new(:features) do |t|
7
7
  t.fork = true
8
- t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
8
+ t.cucumber_opts = [<%= options[:spork] ? "'--drb', " : "" %>'--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
9
9
  end
10
10
  task :features => 'db:test:prepare'
11
11
  rescue LoadError
@@ -2,10 +2,17 @@
2
2
  ENV["RAILS_ENV"] ||= "cucumber"
3
3
  require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
4
4
  require 'cucumber/rails/world'
5
- require 'cucumber/formatter/unicode' # Comment out this line if you don't want Cucumber Unicode support
5
+
6
+ # Comment out the next line if you don't want Cucumber Unicode support
7
+ require 'cucumber/formatter/unicode'
8
+
9
+ # Comment out the next line if you don't want transactions to
10
+ # open/roll back around each scenario
6
11
  Cucumber::Rails.use_transactional_fixtures
7
- Cucumber::Rails.bypass_rescue # Comment out this line if you want Rails own error handling
8
- # (e.g. rescue_action_in_public / rescue_responses / rescue_from)
12
+
13
+ # Comment out the next line if you want Rails' own error handling
14
+ # (e.g. rescue_action_in_public / rescue_responses / rescue_from)
15
+ Cucumber::Rails.bypass_rescue
9
16
 
10
17
  require 'webrat'
11
18
 
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'spork'
3
+
4
+ Spork.prefork do
5
+ # Sets up the Rails environment for Cucumber
6
+ ENV["RAILS_ENV"] ||= "cucumber"
7
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
8
+
9
+ require 'webrat'
10
+
11
+ Webrat.configure do |config|
12
+ config.mode = :rails
13
+ end
14
+
15
+ require 'webrat/core/matchers'
16
+ require 'cucumber'
17
+
18
+ # Comment out the next line if you don't want Cucumber Unicode support
19
+ require 'cucumber/formatter/unicode'
20
+
21
+ require 'spec/rails'
22
+ require 'cucumber/rails/rspec'
23
+ end
24
+
25
+ Spork.each_run do
26
+ # This code will be run each time you run your specs.
27
+ require 'cucumber/rails/world'
28
+
29
+ # Comment out the next line if you don't want transactions to
30
+ # open/roll back around each scenario
31
+ Cucumber::Rails.use_transactional_fixtures
32
+
33
+ # Comment out the next line if you want Rails' own error handling
34
+ # (e.g. rescue_action_in_public / rescue_responses / rescue_from)
35
+ Cucumber::Rails.bypass_rescue
36
+ end
@@ -83,6 +83,61 @@ module Cli
83
83
  end
84
84
  end
85
85
 
86
+ describe '#drb?' do
87
+ it "indicates whether the --drb flag was passed in or not" do
88
+ config = Configuration.new(StringIO.new)
89
+
90
+ config.parse!(%w{features})
91
+ config.drb?.should == false
92
+
93
+
94
+ config.parse!(%w{features --drb})
95
+ config.drb?.should == true
96
+ end
97
+ end
98
+
99
+ context '--drb' do
100
+ it "removes the --drb flag from the args" do
101
+ config = Configuration.new(StringIO.new)
102
+
103
+ args = %w{features --drb}
104
+ config.parse!(args)
105
+ args.should == %w{features}
106
+ end
107
+
108
+ it "keeps all other flags intact" do
109
+ config = Configuration.new(StringIO.new)
110
+
111
+ args = %w{features --drb --format profile}
112
+ config.parse!(args)
113
+ args.should == %w{features --format profile}
114
+ end
115
+
116
+ end
117
+
118
+ context '--drb in a profile' do
119
+ it "removes the --drb flag from the args" do
120
+ given_cucumber_yml_defined_as({'server' => '--drb features'})
121
+ config = Configuration.new(StringIO.new)
122
+
123
+ args = %w{--profile server}
124
+ config.parse!(args)
125
+ args.should == %w{features}
126
+ end
127
+
128
+ it "keeps all other flags intact from all profiles involved" do
129
+ given_cucumber_yml_defined_as({'server' => '--drb features --profile nested',
130
+ 'nested' => '--verbose'})
131
+
132
+ config = Configuration.new(StringIO.new)
133
+
134
+ args = %w{--profile server --format profile}
135
+ config.parse!(args)
136
+ args.should == %w{features --verbose --format profile}
137
+ end
138
+
139
+ end
140
+
86
141
  it "should expand args from YAML file" do
87
142
  given_cucumber_yml_defined_as({'bongo' => '--require from/yml'})
88
143
 
@@ -156,7 +211,7 @@ END_OF_MESSAGE
156
211
  expected_error_message = /cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage./
157
212
 
158
213
  given_cucumber_yml_defined_as("input that causes an exception in YAML loading")
159
- YAML.should_receive(:load).and_raise Exception
214
+ YAML.should_receive(:load).and_raise ArgumentError
160
215
 
161
216
  config = Configuration.new(StringIO.new, error = StringIO.new)
162
217
  lambda{config.parse!([])}.should raise_error(expected_error_message)