cucumber 0.3.97 → 0.3.98

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.
@@ -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