kosmas58-cucumber 0.3.9.4 → 0.3.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/History.txt +45 -7
  2. data/Manifest.txt +403 -0
  3. data/cucumber.yml +4 -3
  4. data/examples/dos_line_endings/features/dos_line_endings.feature +9 -9
  5. data/features/drb_server_integration.feature +114 -0
  6. data/features/html_formatter/a.html +129 -1574
  7. data/features/junit_formatter.feature +11 -2
  8. data/features/step_definitions/cucumber_steps.rb +15 -2
  9. data/features/support/env.rb +35 -1
  10. data/gem_tasks/features.rake +7 -2
  11. data/lib/cucumber/ast/table.rb +6 -6
  12. data/lib/cucumber/cli/configuration.rb +32 -8
  13. data/lib/cucumber/cli/drb_client.rb +20 -0
  14. data/lib/cucumber/cli/main.rb +9 -0
  15. data/lib/cucumber/formatter/color_io.rb +2 -2
  16. data/lib/cucumber/formatter/console.rb +6 -1
  17. data/lib/cucumber/formatter/cucumber.css +106 -48
  18. data/lib/cucumber/formatter/cucumber.sass +121 -31
  19. data/lib/cucumber/formatter/html.rb +14 -3
  20. data/lib/cucumber/formatter/junit.rb +1 -2
  21. data/lib/cucumber/rake/task.rb +1 -1
  22. data/lib/cucumber/version.rb +2 -2
  23. data/rails_generators/cucumber/cucumber_generator.rb +15 -5
  24. data/rails_generators/cucumber/templates/cucumber.rake +5 -5
  25. data/rails_generators/cucumber/templates/de/paths.rb +3 -3
  26. data/rails_generators/cucumber/templates/de/webrat_steps.rb +11 -3
  27. data/rails_generators/cucumber/templates/env.rb +10 -3
  28. data/rails_generators/cucumber/templates/spork_env.rb +36 -0
  29. data/spec/cucumber/cli/configuration_spec.rb +56 -1
  30. data/spec/cucumber/cli/drb_client_spec.rb +43 -0
  31. data/spec/cucumber/cli/main_spec.rb +70 -19
  32. data/spec/spec_helper.rb +2 -0
  33. metadata +8 -9
  34. data/spec/cucumber/formatter/html/cucumber.css +0 -37
  35. data/spec/cucumber/formatter/html/cucumber.js +0 -13
  36. data/spec/cucumber/formatter/html/index.html +0 -45
  37. data/spec/cucumber/formatter/html/jquery-1.3.min.js +0 -19
  38. data/spec/cucumber/formatter/html/jquery.uitableedit.js +0 -100
@@ -58,5 +58,14 @@ Feature: JUnit output formatter
58
58
  """
59
59
  And "examples/junit/tmp/TEST-One_passing_scenario__one_failing_scenario.xml" should exist
60
60
  And "examples/junit/tmp/TEST-Pending_step.xml" should exist
61
-
62
-
61
+
62
+ Scenario: show correct error message if no --out is passed
63
+ When I run cucumber --format junit features
64
+ Then STDERR should not match
65
+ """
66
+ can't convert .* into String \(TypeError\)
67
+ """
68
+ And STDERR should match
69
+ """
70
+ You \*must\* specify \-\-out DIR for the junit formatter
71
+ """
@@ -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
@@ -88,9 +97,9 @@ end
88
97
 
89
98
  Then /^"([^\"]*)" should have the same contents as "([^\"]*)"$/ do |actual_file, expected_file|
90
99
  actual = IO.read(actual_file)
91
- # Comment out to replace expected file. Use with care! Remember to update duration afterwards.
92
- # File.open(expected_file, "w"){|io| io.write(actual)}
93
100
  actual = replace_duration(actual, '0m30.005s')
101
+ # Comment out to replace expected file. Use with care! Remember to update duration afterwards.
102
+ # File.open(expected_file, "w") {|io| io.write(actual)}
94
103
  actual.should == IO.read(expected_file)
95
104
  end
96
105
 
@@ -98,6 +107,10 @@ Then /^STDERR should match$/ do |text|
98
107
  last_stderr.should =~ /#{text}/
99
108
  end
100
109
 
110
+ Then /^STDERR should not match$/ do |text|
111
+ last_stderr.should_not =~ /#{text}/
112
+ end
113
+
101
114
  Then /^STDERR should be empty$/ do
102
115
  last_stderr.should == ""
103
116
  end
@@ -3,6 +3,11 @@ require 'tempfile'
3
3
  require 'spec/expectations'
4
4
  require 'fileutils'
5
5
  require 'forwardable'
6
+ begin
7
+ gem "spork", ">= 0.5.1" # Ensure correct spork version number to avoid false-negatives.
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
@@ -3,11 +3,16 @@ require 'cucumber/rake/task'
3
3
 
4
4
  namespace :features do
5
5
  Cucumber::Rake::Task.new(:all) do |t|
6
- t.cucumber_opts = "--format pretty"
6
+ t.cucumber_opts = %w{--format progress}
7
+ end
8
+
9
+ Cucumber::Rake::Task.new(:pretty) do |t|
10
+ t.cucumber_opts = %w{--format pretty}
7
11
  end
8
12
 
9
13
  Cucumber::Rake::Task.new(:cruise) do |t|
10
- t.cucumber_opts = "--format html --out=#{ENV['CC_BUILD_ARTIFACTS']}/CucumberFeatures.html"
14
+ t.cucumber_opts = %w{--format html}
15
+ t.cucumber_opts << %[--out "#{ENV['CC_BUILD_ARTIFACTS']}/CucumberFeatures.html"]
11
16
  t.rcov = true
12
17
  t.rcov_opts = %w{--rails --exclude osx\/objc,gems\/,spec\/}
13
18
  t.rcov_opts << %[-o "#{ENV['CC_BUILD_ARTIFACTS']}/CucumberCoverage"]
@@ -62,7 +62,7 @@ module Cucumber
62
62
  def hashes
63
63
  @hashes ||= cells_rows[1..-1].map do |row|
64
64
  row.to_hash
65
- end
65
+ end.freeze
66
66
  end
67
67
 
68
68
  # Converts this table into a Hash where the first column is
@@ -198,7 +198,7 @@ module Cucumber
198
198
  def cells_rows
199
199
  @rows ||= cell_matrix.map do |cell_row|
200
200
  @cells_class.new(self, cell_row)
201
- end
201
+ end.freeze
202
202
  end
203
203
 
204
204
  def headers
@@ -230,7 +230,7 @@ module Cucumber
230
230
  def columns
231
231
  @columns ||= cell_matrix.transpose.map do |cell_row|
232
232
  @cells_class.new(self, cell_row)
233
- end
233
+ end.freeze
234
234
  end
235
235
 
236
236
  def cell_matrix
@@ -243,7 +243,7 @@ module Cucumber
243
243
  col += 1
244
244
  @cell_class.new(raw_cell, self, row, col, line)
245
245
  end
246
- end
246
+ end.freeze
247
247
  end
248
248
 
249
249
  # Represents a row of cells or columns of cells
@@ -268,7 +268,7 @@ module Cucumber
268
268
  end
269
269
 
270
270
  def to_hash #:nodoc:
271
- @to_hash ||= @table.to_hash(self)
271
+ @to_hash ||= @table.to_hash(self).freeze
272
272
  end
273
273
 
274
274
  def value(n) #:nodoc:
@@ -326,7 +326,7 @@ module Cucumber
326
326
  private
327
327
 
328
328
  def col_width
329
- @col_width ||= @table.__send__(:col_width, @col)
329
+ @col_width ||= @table.__send__(:col_width, @col).freeze
330
330
  end
331
331
  end
332
332
  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,20 @@
1
+ require "drb/drb"
2
+ # This code was taken from the RSpec project and slightly modified.
3
+
4
+ module Cucumber
5
+ module Cli
6
+ class DRbClientError < StandardError
7
+ end
8
+ # Runs features on a DRB server, originally created with Spork compatibility in mind.
9
+ class DRbClient
10
+ def self.run(args, error_stream, out_stream)
11
+ # See http://redmine.ruby-lang.org/issues/show/496 as to why we specify localhost:0
12
+ DRb.start_service("druby://localhost:0")
13
+ feature_server = DRbObject.new_with_uri("druby://127.0.0.1:8990")
14
+ feature_server.run(args, error_stream, out_stream)
15
+ rescue DRb::DRbConnError
16
+ raise DRbClientError, "No DRb server is running."
17
+ end
18
+ end
19
+ end
20
+ 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
@@ -32,6 +33,14 @@ module Cucumber
32
33
  end
33
34
 
34
35
  def execute!(step_mother)
36
+ if configuration.drb?
37
+ begin
38
+ return DRbClient.run(@args, @error_stream, @out_stream)
39
+ rescue DRbClientError => e
40
+ @error_stream.puts "WARNING: #{e.message} 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
 
@@ -6,7 +6,7 @@ module Cucumber
6
6
  class ColorIO
7
7
  extend Forwardable
8
8
  def_delegators :@kernel, :puts, :print # win32console colours only work when sent to Kernel
9
- def_delegators :@stdout, :flush, :tty?
9
+ def_delegators :@stdout, :flush, :tty?, :write
10
10
 
11
11
  def initialize
12
12
  @kernel = Kernel
@@ -20,4 +20,4 @@ module Cucumber
20
20
  end
21
21
  end
22
22
  end
23
- end
23
+ end
@@ -53,6 +53,11 @@ module Cucumber
53
53
  end
54
54
  end
55
55
 
56
+ def print_counts
57
+ STDERR.puts("The #print_counts method is deprecated and will be removed in 0.4. Use #print_stats instead")
58
+ print_stats(nil)
59
+ end
60
+
56
61
  def print_stats(features)
57
62
  @io.print dump_count(step_mother.scenarios.length, "scenario")
58
63
  print_status_counts{|status| step_mother.scenarios(status)}
@@ -60,7 +65,7 @@ module Cucumber
60
65
  @io.print dump_count(step_mother.steps.length, "step")
61
66
  print_status_counts{|status| step_mother.steps(status)}
62
67
 
63
- @io.puts(format_duration(features.duration))
68
+ @io.puts(format_duration(features.duration)) if features
64
69
 
65
70
  @io.flush
66
71
  end
@@ -1,53 +1,38 @@
1
+
2
+
1
3
  .cucumber {
2
- background: black;
3
- color: white;
4
+ font-family: "Lucida Grande", Helvetica, sans-serif;
5
+ font-size: 0.7em;
6
+ background: white;
4
7
  padding: 1em;
5
8
  }
6
- .cucumber .passed {
7
- color: #008800;
8
- }
9
- .cucumber .undefined {
10
- color: #888800;
9
+ .cucumber h1, .cucumber h2, .cucumber h3, .cucumber h4, .cucumber ol, .cucumber li, .cucumber pre, .cucumber p {
10
+ font-size: 1em;
11
+ padding: 0px;
12
+ margin: 0px;
11
13
  }
12
- .cucumber .pending {
13
- color: #888800;
14
+ .cucumber div.feature {
15
+ border: 1px solid;
16
+ padding: 2px;
17
+ margin: 4px;
14
18
  }
15
- .cucumber .failed {
16
- color: #880000;
19
+ .cucumber div.feature div.background, .cucumber div.feature div.scenario, .cucumber div.feature p {
20
+ padding: 0em 0em 0em 1em;
17
21
  }
18
- .cucumber .skipped {
19
- color: #008888;
20
- }
21
- .cucumber .outline {
22
- color: #008888;
23
- }
24
-
25
- .cucumber .passed_param {
26
- font-weight: bold;
27
- color: #00ff00;
28
- }
29
- .cucumber .undefined_param {
30
- font-weight: bold;
31
- color: #ffff00;
32
- }
33
- .cucumber .pending_param {
34
- font-weight: bold;
35
- color: #ffff00;
22
+ .cucumber div.feature div.background div.examples, .cucumber div.feature div.scenario div.examples, .cucumber div.feature p div.examples {
23
+ padding: 0em 0em 0em 1em;
36
24
  }
37
- .cucumber .failed_param {
38
- font-weight: bold;
39
- font-weight: bold;
40
- color: #ff0000;
25
+ .cucumber .stats {
26
+ margin: 2em;
41
27
  }
42
- .cucumber .skipped_param {
43
- font-weight: bold;
44
- color: #00ffff;
28
+ .cucumber .summary ul.features li {
29
+ display: inline;
45
30
  }
46
- .cucumber .outline_param {
47
- font-weight: bold;
48
- color: #00ffff;
31
+ .cucumber .backtrace {
32
+ margin-top: 0;
33
+ margin-bottom: 0;
34
+ margin-left: 1em;
49
35
  }
50
-
51
36
  .cucumber a {
52
37
  text-decoration: none;
53
38
  color: inherit;
@@ -58,17 +43,90 @@
58
43
  .cucumber a:visited {
59
44
  font-weight: normal;
60
45
  }
46
+ .cucumber a div.examples {
47
+ border: 1px solid;
48
+ padding: 2px;
49
+ margin: 4px;
50
+ }
51
+ .cucumber table {
52
+ border-collapse: collapse;
53
+ }
54
+ .cucumber table td, .cucumber table th {
55
+ font-size: 0.7em;
56
+ border: 1px solid #AAAAAA;
57
+ }
58
+ .cucumber table td.failed {
59
+ background: #FFC0CB;
60
+ color: #8B0000;
61
+ }
62
+ .cucumber table td.passed {
63
+ background: #98FB98;
64
+ color: #001111;
65
+ }
66
+ .cucumber table td.skipped {
67
+ background: #e0ffff;
68
+ color: #001111;
69
+ }
70
+ .cucumber table td.pending {
71
+ background: #FFFFE0;
72
+ color: #111100;
73
+ }
74
+ .cucumber table td.undefined {
75
+ background: #FFFFE0;
76
+ color: #111100;
77
+ }
61
78
  .cucumber ol {
62
79
  list-style: none;
63
80
  }
64
- .cucumber .stats {
65
- margin: 2em;
81
+ .cucumber ol li {
82
+ margin: 0em 0em 0em 1em;
83
+ padding: 0em 0em 0em 0.2em;
66
84
  }
67
- .cucumber .summary ul.features li {
68
- display: inline;
85
+ .cucumber ol li span.param {
86
+ font-weight: bold;
69
87
  }
70
- .cucumber .backtrace {
71
- margin-top: 0;
72
- margin-bottom: 0;
73
- margin-left: 1em;
88
+ .cucumber ol li.failed {
89
+ border-left: 5px solid #ff0000;
90
+ border-bottom: 1px solid #ff0000;
91
+ background: #ffc0cb;
92
+ color: #8b0000;
93
+ }
94
+ .cucumber ol li.failed span.param {
95
+ background: !failed_dark;
96
+ }
97
+ .cucumber ol li.passed {
98
+ border-left: 5px solid #00ff00;
99
+ border-bottom: 1px solid #00ff00;
100
+ background: #98fb98;
101
+ color: #001111;
102
+ }
103
+ .cucumber ol li.passed span.param {
104
+ background: #00ff00;
105
+ }
106
+ .cucumber ol li.skipped {
107
+ border-left: 5px solid #00ffff;
108
+ border-bottom: 1px solid #00ffff;
109
+ background: #e0ffff;
110
+ color: #001111;
111
+ }
112
+ .cucumber ol li.skipped span.param {
113
+ background: #00ffff;
114
+ }
115
+ .cucumber ol li.pending {
116
+ border-left: 5px solid #ff8000;
117
+ border-bottom: 1px solid #ff8000;
118
+ background: #ffff00;
119
+ color: #2a1b0a;
120
+ }
121
+ .cucumber ol li.pending span.param {
122
+ background: #ff8000;
123
+ }
124
+ .cucumber ol li.undefined {
125
+ border-left: 5px solid #ff8000;
126
+ border-bottom: 1px solid #ff8000;
127
+ background: #ffff00;
128
+ color: #2a1b0a;
129
+ }
130
+ .cucumber ol li.undefined span.param {
131
+ background: #ff8000;
74
132
  }