cucumber 0.3.97 → 0.3.98

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,12 @@
1
+ == 0.3.98 2009-08-25
2
+
3
+ Just a small release to help Cuke4Duke, which will be presented at Agile2009
4
+ in 2 days.
5
+
6
+ === New Features
7
+ * Backtrace filtering now happens in StepInvocation class, meaning other languages (Cuke4Duke) can get backtraces stripped. (Aslak Hellesøy)
8
+ * Cucumber::Ast::Table#map_headers now allows for a block that will convert all the headers. See docs for details. (Ben Mabey)
9
+
1
10
  == 0.3.97 2009-08-23
2
11
 
3
12
  The AA-FTT release. Creating a release for the AA-FTT meeting in Chicago so that we can play
@@ -324,7 +324,6 @@ lib/cucumber/cli/main.rb
324
324
  lib/cucumber/cli/options.rb
325
325
  lib/cucumber/cli/profile_loader.rb
326
326
  lib/cucumber/constantize.rb
327
- lib/cucumber/core_ext/exception.rb
328
327
  lib/cucumber/core_ext/instance_exec.rb
329
328
  lib/cucumber/core_ext/proc.rb
330
329
  lib/cucumber/core_ext/string.rb
@@ -42,4 +42,4 @@ if require_spec
42
42
  t.rcov_opts = %w{--exclude osx\/objc,gems\/,spec\/}
43
43
  t.verbose = true
44
44
  end
45
- end
45
+ end
@@ -8,4 +8,3 @@ require 'cucumber/version'
8
8
  require 'cucumber/step_mother'
9
9
  require 'cucumber/cli/main'
10
10
  require 'cucumber/broadcaster'
11
- require 'cucumber/core_ext/exception'
@@ -3,6 +3,10 @@ require 'cucumber/step_match'
3
3
  module Cucumber
4
4
  module Ast
5
5
  class StepInvocation #:nodoc:
6
+ BACKTRACE_FILTER_PATTERNS = [
7
+ /vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\//
8
+ ]
9
+
6
10
  attr_writer :step_collection, :background
7
11
  attr_reader :name, :matched_cells, :status, :reported_exception
8
12
  attr_accessor :exception
@@ -68,6 +72,7 @@ module Cucumber
68
72
  end
69
73
 
70
74
  def failed(options, e, clear_backtrace)
75
+ e = filter_backtrace(e)
71
76
  e.set_backtrace([]) if clear_backtrace
72
77
  e.backtrace << @step.backtrace_line unless @step.backtrace_line.nil?
73
78
  @exception = e
@@ -78,6 +83,23 @@ module Cucumber
78
83
  end
79
84
  end
80
85
 
86
+ def filter_backtrace(e)
87
+ return e if Cucumber.use_full_backtrace
88
+ filtered = (e.backtrace || []).reject do |line|
89
+ BACKTRACE_FILTER_PATTERNS.detect { |p| line =~ p }
90
+ end
91
+
92
+ if Cucumber::JRUBY
93
+ # In order to filter backtraces properly on JRuby, we need to
94
+ # create a new Exception - otherwise the backtrace is *not*
95
+ # filtered. The rescue is for org.jruby.NativeException, which
96
+ # cannot be new'ed.
97
+ e = e.class.new(e.message) rescue Exception.new(e.message)
98
+ end
99
+ e.set_backtrace(filtered)
100
+ e
101
+ end
102
+
81
103
  def status!(status)
82
104
  @status = status
83
105
  @matched_cells.each do |cell|
@@ -164,8 +164,26 @@ module Cucumber
164
164
  # table.hashes
165
165
  # # => [{:phone => '123456', :address => 'xyz'}, {:phone => '345678', :address => 'abc'}]
166
166
  #
167
- def map_headers!(mappings)
167
+ # You may also pass in a block if you wish to convert all of the headers:
168
+ #
169
+ # table.map_headers! { |header| header.downcase }
170
+ # table.hashes.keys
171
+ # # => ['phone number', 'address']
172
+ #
173
+ # When a block is passed in along with a hash then the mappings in the hash take precendence:
174
+ #
175
+ # table.map_headers!('Address' => 'ADDRESS') { |header| header.downcase }
176
+ # table.hashes.keys
177
+ # # => ['phone number', 'ADDRESS']
178
+ #
179
+ def map_headers!(mappings={}, &block)
168
180
  header_cells = cell_matrix[0]
181
+
182
+ if block_given?
183
+ header_values = header_cells.map { |cell| cell.value } - mappings.keys
184
+ mappings = mappings.merge(Hash[*header_values.zip(header_values.map(&block)).flatten])
185
+ end
186
+
169
187
  mappings.each_pair do |pre, post|
170
188
  mapped_cells = header_cells.select{|cell| pre === cell.value}
171
189
  raise "No headers matched #{pre.inspect}" if mapped_cells.empty?
@@ -178,7 +196,7 @@ module Cucumber
178
196
  end
179
197
 
180
198
  # Returns a new Table where the headers are redefined. See #map_headers!
181
- def map_headers(mappings)
199
+ def map_headers(mappings={})
182
200
  table = self.dup
183
201
  table.map_headers!(mappings)
184
202
  table
@@ -195,7 +195,7 @@ module Cucumber
195
195
  @quiet = true
196
196
  end
197
197
  opts.on("-b", "--backtrace", "Show full backtrace for all errors.") do
198
- Exception.cucumber_full_backtrace = true
198
+ Cucumber.use_full_backtrace = true
199
199
  end
200
200
  opts.on("-S", "--strict", "Fail if there are any undefined steps.") do
201
201
  @options[:strict] = true
@@ -45,11 +45,29 @@ class Object #:nodoc:
45
45
  yield
46
46
  rescue Exception => e
47
47
  instance_exec_invocation_line = "#{__FILE__}:#{__LINE__ - 2}:in `cucumber_run_with_backtrace_filtering'"
48
- Exception.cucumber_strip_backtrace!((e.backtrace || []), instance_exec_invocation_line, pseudo_method)
48
+ replace_instance_exec_invocation_line!((e.backtrace || []), instance_exec_invocation_line, pseudo_method)
49
49
  raise e
50
50
  end
51
51
  end
52
-
52
+
53
+ INSTANCE_EXEC_OFFSET = (Cucumber::RUBY_1_9 || Cucumber::JRUBY) ? -3 : -4
54
+
55
+ def replace_instance_exec_invocation_line!(backtrace, instance_exec_invocation_line, pseudo_method)
56
+ return if Cucumber.use_full_backtrace
57
+
58
+ instance_exec_pos = backtrace.index(instance_exec_invocation_line)
59
+ if instance_exec_pos
60
+ replacement_line = instance_exec_pos + INSTANCE_EXEC_OFFSET
61
+ backtrace[replacement_line].gsub!(/`.*'/, "`#{pseudo_method}'") if pseudo_method
62
+ backtrace[replacement_line+1..-1] = nil
63
+
64
+ backtrace.compact!
65
+ else
66
+ # This happens with rails, because they screw up the backtrace
67
+ # before we get here (injecting erb stacktrace and such)
68
+ end
69
+ end
70
+
53
71
  unless defined? instance_exec # 1.9
54
72
  # http://eigenclass.org/hiki/bounded+space+instance_exec
55
73
  module InstanceExecHelper #:nodoc:
@@ -15,8 +15,13 @@ module Cucumber
15
15
  RAILS = defined?(Rails)
16
16
  RUBY_BINARY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
17
17
  RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
18
-
19
- def self.file_mode(m) #:nodoc:
20
- RUBY_1_9 ? "#{m}:UTF-8" : m
18
+
19
+ class << self
20
+ attr_accessor :use_full_backtrace
21
+
22
+ def file_mode(m) #:nodoc:
23
+ RUBY_1_9 ? "#{m}:UTF-8" : m
24
+ end
21
25
  end
26
+ self.use_full_backtrace = false
22
27
  end
@@ -46,7 +46,7 @@ module Cucumber
46
46
  load_code_file(code_file)
47
47
  step_definitions
48
48
  rescue LoadError => e
49
- e.message << "\nFailed to load #{code_filr}"
49
+ e.message << "\nFailed to load #{code_file}"
50
50
  raise e
51
51
  ensure
52
52
  @step_definitions = nil
@@ -2,7 +2,7 @@ module Cucumber #:nodoc:
2
2
  class VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- TINY = 97
5
+ TINY = 98
6
6
  PATCH = nil # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
@@ -84,7 +84,7 @@ module Cucumber
84
84
  ])
85
85
  table.rows_hash.should == {'one' => '1111', 'two' => '22222'}
86
86
  end
87
-
87
+
88
88
  it "should fail if the table doesn't have two columns" do
89
89
  faulty_table = Table.new([
90
90
  %w{one 1111 abc},
@@ -95,21 +95,50 @@ module Cucumber
95
95
  }.should raise_error('The table must have exactly 2 columns')
96
96
  end
97
97
  end
98
-
99
- it "should allow renaming columns" do
100
- table2 = @table.map_headers('one' => :three)
101
- table2.hashes.first[:three].should == '4444'
102
- end
103
98
 
104
- it "should allow renaming columns using regexp" do
105
- table2 = @table.map_headers(/one|uno/ => :three)
106
- table2.hashes.first[:three].should == '4444'
107
- end
99
+ describe '#map_headers' do
100
+ it "renames the columns to the specified values in the provided hash" do
101
+ table2 = @table.map_headers('one' => :three)
102
+ table2.hashes.first[:three].should == '4444'
103
+ end
104
+
105
+ it "allows renaming columns using regexp" do
106
+ table2 = @table.map_headers(/one|uno/ => :three)
107
+ table2.hashes.first[:three].should == '4444'
108
+ end
109
+
110
+ it "copies column mappings" do
111
+ @table.map_column!('one') { |v| v.to_i }
112
+ table2 = @table.map_headers('one' => 'three')
113
+ table2.hashes.first['three'].should == 4444
114
+ end
115
+
116
+ it "takes a block and operates on all the headers with it" do
117
+ table = Table.new([
118
+ ['HELLO', 'WORLD'],
119
+ %w{4444 55555}
120
+ ])
121
+
122
+ table.map_headers! do |header|
123
+ header.downcase
124
+ end
125
+
126
+ table.hashes.first.keys.should =~ %w[hello world]
127
+ end
128
+
129
+ it "treats the mappings in the provided hash as overrides when used with a block" do
130
+ table = Table.new([
131
+ ['HELLO', 'WORLD'],
132
+ %w{4444 55555}
133
+ ])
134
+
135
+ table.map_headers!('WORLD' => 'foo') do |header|
136
+ header.downcase
137
+ end
138
+
139
+ table.hashes.first.keys.should =~ %w[hello foo]
140
+ end
108
141
 
109
- it "should copy column mappings when mapping headers" do
110
- @table.map_column!('one') { |v| v.to_i }
111
- table2 = @table.map_headers('one' => 'three')
112
- table2.hashes.first['three'].should == 4444
113
142
  end
114
143
 
115
144
  describe "replacing arguments" do
@@ -312,7 +312,7 @@ END_OF_MESSAGE
312
312
 
313
313
  describe "--backtrace" do
314
314
  before do
315
- Exception.cucumber_full_backtrace = false
315
+ Cucumber.use_full_backtrace = false
316
316
  end
317
317
 
318
318
  it "should show full backtrace when --backtrace is present" do
@@ -325,7 +325,7 @@ END_OF_MESSAGE
325
325
  end
326
326
 
327
327
  after do
328
- Exception.cucumber_full_backtrace = false
328
+ Cucumber.use_full_backtrace = false
329
329
  end
330
330
  end
331
331
 
@@ -244,7 +244,7 @@ module Cli
244
244
  context '-b or --backtrace' do
245
245
  it "turns on cucumber's full backtrace" do
246
246
  when_parsing("-b") do
247
- Exception.should_receive(:cucumber_full_backtrace=).with(true)
247
+ Cucumber.should_receive(:use_full_backtrace=).with(true)
248
248
  end
249
249
  end
250
250
  end
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/../../spec_helper'
2
- require 'cucumber/core_ext/instance_exec'
2
+ require 'cucumber/core_ext/proc'
3
3
 
4
4
  describe Proc do
5
5
  it "should remove extraneous path info for file" do
@@ -1,3 +1,4 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
1
2
  require File.dirname(__FILE__) + '/../../../lib/cucumber/core_ext/string'
2
3
 
3
4
  describe String, "#gzub" do
@@ -6,10 +6,6 @@ module Cucumber
6
6
  describe ANSIColor do
7
7
  include ANSIColor
8
8
 
9
- after do
10
- ::Term::ANSIColor.coloring = true
11
- end
12
-
13
9
  it "should wrap passed_param with bold green and reset to green" do
14
10
  passed_param("foo").should == "\e[32m\e[1mfoo\e[0m\e[0m\e[32m"
15
11
  end
@@ -5,15 +5,12 @@ module Cucumber
5
5
  module Formatter
6
6
  describe Progress do
7
7
 
8
- before(:all) do
9
- Term::ANSIColor.coloring = false
10
- end
11
-
12
8
  before(:each) do
9
+ Term::ANSIColor.coloring = false
13
10
  @out = StringIO.new
14
11
  @progress = Progress.new(mock("step mother"), @out, {})
15
12
  end
16
-
13
+
17
14
  describe "visiting a table cell value without a status" do
18
15
  it "should take the status from the last run step" do
19
16
  @progress.visit_step_result('', '', nil, :failed, nil, 10, nil)
@@ -9,6 +9,10 @@ module Cucumber
9
9
  @parser = NaturalLanguage.get(@step_mother, 'en').parser
10
10
  end
11
11
 
12
+ after do
13
+ NaturalLanguage.instance_variable_set(:@languages, nil) # So that new StepMothers can be created and have adverbs registered
14
+ end
15
+
12
16
  def parse(text)
13
17
  feature = @parser.parse_or_fail(text)
14
18
  end
@@ -9,6 +9,10 @@ module Cucumber
9
9
  @parser = NaturalLanguage.get(StepMother.new, 'en').parser
10
10
  end
11
11
 
12
+ after do
13
+ NaturalLanguage.instance_variable_set(:@languages, nil)
14
+ end
15
+
12
16
  def parse(text)
13
17
  @parser.__send__(:prepare_to_parse, text)
14
18
  @parser.root = :table
@@ -5,6 +5,11 @@ describe "Rails world" do
5
5
 
6
6
  it "should run without Test::Unit.run defined" do
7
7
  require "mini_rails"
8
+
9
+ step_mother = Cucumber::StepMother.new
10
+ step_mother.load_natural_language('en')
11
+ rb = step_mother.load_programming_language('rb')
12
+
8
13
  require "cucumber/rails/world"
9
14
  end
10
15
 
@@ -8,6 +8,11 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
8
8
  require 'cucumber'
9
9
  $:.unshift(File.dirname(__FILE__))
10
10
 
11
- ::Term::ANSIColor.coloring = true
11
+ Spec::Runner.configure do |config|
12
+ config.before(:each) do
13
+ ::Term::ANSIColor.coloring = true
14
+ Cucumber::Parser::NaturalLanguage.instance_variable_set(:@languages, nil)
15
+ end
16
+ end
12
17
 
13
18
  alias running lambda
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.97
4
+ version: 0.3.98
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Aslak Helles\xC3\xB8y"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-23 00:00:00 -05:00
12
+ date: 2009-08-25 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -401,7 +401,6 @@ files:
401
401
  - lib/cucumber/cli/options.rb
402
402
  - lib/cucumber/cli/profile_loader.rb
403
403
  - lib/cucumber/constantize.rb
404
- - lib/cucumber/core_ext/exception.rb
405
404
  - lib/cucumber/core_ext/instance_exec.rb
406
405
  - lib/cucumber/core_ext/proc.rb
407
406
  - lib/cucumber/core_ext/string.rb
@@ -1,53 +0,0 @@
1
- # Exception extension that tweaks Exception backtraces:
2
- #
3
- # * The line of the failing .feature line is appended to the backtrace
4
- # * The line that calls #cucumber_instance_exec is replaced with the StepDefinition's regexp
5
- # * Non intersting lines are stripped out
6
- #
7
- # The result is that backtraces look like this:
8
- #
9
- # features/step_definitions/the_step_definition.rb:in `/some step/'
10
- # features/the_feature_file.feature:41:in `Given some step'
11
- #
12
- # or if the exception is raised in the tested code:
13
- #
14
- # lib/myapp/some_file.rb:in `/some_method/'
15
- # lib/myapp/some_other_file.rb:in `/some_other_method/'
16
- # features/step_definitions/the_step_definition.rb:in `/some step/'
17
- # features/the_feature_file.feature:41:in `Given some step'
18
- #
19
- # All backtrace munging can be turned off with the <tt>--backtrace</tt> switch
20
- #
21
- class Exception #:nodoc:
22
- CUCUMBER_FILTER_PATTERNS = [
23
- /vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\//
24
- ]
25
-
26
- INSTANCE_EXEC_OFFSET = (Cucumber::RUBY_1_9 || Cucumber::JRUBY) ? -3 : -4
27
-
28
- def self.cucumber_full_backtrace=(v)
29
- @@cucumber_full_backtrace = v
30
- end
31
- self.cucumber_full_backtrace = false
32
-
33
- # Strips the backtrace from +line+ and down
34
- def self.cucumber_strip_backtrace!(backtrace, instance_exec_invocation_line, pseudo_method)
35
- return if @@cucumber_full_backtrace
36
-
37
- instance_exec_pos = backtrace.index(instance_exec_invocation_line)
38
- if instance_exec_pos
39
- replacement_line = instance_exec_pos + INSTANCE_EXEC_OFFSET
40
- backtrace[replacement_line].gsub!(/`.*'/, "`#{pseudo_method}'") if pseudo_method
41
- backtrace[replacement_line+1..-1] = nil
42
-
43
- backtrace.compact!
44
- else
45
- # This happens with rails, because they screw up the backtrace
46
- # before we get here (injecting erb stacktrace and such)
47
- end
48
-
49
- backtrace.reject! do |line|
50
- CUCUMBER_FILTER_PATTERNS.detect{|p| line =~ p}
51
- end
52
- end
53
- end