cucumber 0.6.4 → 0.7.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. data/History.txt +11 -0
  2. data/Rakefile +3 -5
  3. data/VERSION.yml +3 -3
  4. data/cucumber.gemspec +35 -55
  5. data/cucumber.yml +3 -2
  6. data/examples/i18n/Rakefile +1 -0
  7. data/examples/i18n/en-lol/features/step_definitions/cucumbrz_steps.rb +1 -1
  8. data/examples/i18n/eo/.gitignore +1 -0
  9. data/examples/i18n/eo/Rakefile +6 -0
  10. data/examples/i18n/eo/features/adicio.feature +17 -0
  11. data/examples/i18n/eo/features/divido.feature +10 -0
  12. data/examples/i18n/eo/features/step_definitons/calculator_steps.rb +24 -0
  13. data/examples/i18n/eo/lib/calculator.rb +14 -0
  14. data/examples/i18n/fr/features/step_definitions/calculatrice_steps.rb +1 -1
  15. data/examples/i18n/ru/features/division.feature +1 -1
  16. data/examples/i18n/uk/Rakefile +6 -0
  17. data/examples/i18n/uk/features/addition.feature +11 -0
  18. data/examples/i18n/uk/features/consecutive_calculations.feature +17 -0
  19. data/examples/i18n/uk/features/division.feature +16 -0
  20. data/examples/i18n/uk/features/step_definitons/calculator_steps.rb +19 -0
  21. data/examples/i18n/uk/features/support/env.rb +5 -0
  22. data/examples/i18n/uk/features/support/world.rb +8 -0
  23. data/examples/i18n/uk/lib/calculator.rb +24 -0
  24. data/examples/i18n/uz/features/step_definitons/calculator_steps.rb +1 -1
  25. data/examples/sinatra/features/add.feature +1 -1
  26. data/examples/sinatra/features/step_definitions/add_steps.rb +1 -1
  27. data/examples/sinatra/features/support/env.rb +2 -19
  28. data/examples/sinatra/views/add.erb +7 -5
  29. data/features/announce.feature +46 -39
  30. data/features/background.feature +3 -0
  31. data/features/call_many_steps.feature +1 -1
  32. data/features/cucumber_cli_outlines.feature +12 -0
  33. data/features/drb_server_integration.feature +1 -1
  34. data/features/exception_in_after_block.feature +3 -0
  35. data/features/exception_in_after_step_block.feature +3 -0
  36. data/features/html_formatter/a.html +29 -29
  37. data/features/language_help.feature +57 -52
  38. data/features/multiline_names.feature +1 -0
  39. data/features/step_definitions/cucumber_steps.rb +2 -1
  40. data/features/usage_and_stepdefs_formatter.feature +30 -30
  41. data/features/wire_protocol.feature +12 -9
  42. data/features/wire_protocol_table_diffing.feature +8 -6
  43. data/features/wire_protocol_timeouts.feature +5 -4
  44. data/gem_tasks/treetop.rake +13 -0
  45. data/lib/autotest/cucumber_mixin.rb +1 -1
  46. data/lib/cucumber/ast.rb +1 -0
  47. data/lib/cucumber/ast/background.rb +14 -4
  48. data/lib/cucumber/ast/examples.rb +2 -0
  49. data/lib/cucumber/ast/feature.rb +26 -5
  50. data/lib/cucumber/ast/feature_element.rb +18 -9
  51. data/lib/cucumber/ast/outline_table.rb +13 -1
  52. data/lib/cucumber/ast/py_string.rb +26 -9
  53. data/lib/cucumber/ast/scenario.rb +13 -7
  54. data/lib/cucumber/ast/scenario_outline.rb +18 -6
  55. data/lib/cucumber/ast/step.rb +4 -4
  56. data/lib/cucumber/ast/step_invocation.rb +5 -2
  57. data/lib/cucumber/ast/table.rb +26 -1
  58. data/lib/cucumber/ast/tags.rb +3 -1
  59. data/lib/cucumber/ast/tree_walker.rb +2 -18
  60. data/lib/cucumber/cli/configuration.rb +2 -2
  61. data/lib/cucumber/cli/options.rb +16 -21
  62. data/lib/cucumber/feature_file.rb +25 -7
  63. data/lib/cucumber/formatter/ansicolor.rb +6 -1
  64. data/lib/cucumber/formatter/console.rb +4 -3
  65. data/lib/cucumber/formatter/html.rb +8 -5
  66. data/lib/cucumber/formatter/junit.rb +5 -4
  67. data/lib/cucumber/formatter/pdf.rb +2 -3
  68. data/lib/cucumber/formatter/pretty.rb +5 -5
  69. data/lib/cucumber/formatter/usage.rb +2 -2
  70. data/lib/cucumber/parser.rb +0 -6
  71. data/lib/cucumber/parser/gherkin_builder.rb +142 -0
  72. data/lib/cucumber/platform.rb +0 -2
  73. data/lib/cucumber/rb_support/rb_language.rb +7 -12
  74. data/lib/cucumber/step_mother.rb +4 -26
  75. data/spec/cucumber/ast/background_spec.rb +0 -1
  76. data/spec/cucumber/ast/feature_factory.rb +2 -4
  77. data/spec/cucumber/ast/feature_spec.rb +0 -2
  78. data/spec/cucumber/ast/py_string_spec.rb +2 -13
  79. data/spec/cucumber/ast/scenario_outline_spec.rb +0 -1
  80. data/spec/cucumber/ast/scenario_spec.rb +0 -1
  81. data/spec/cucumber/ast/step_spec.rb +1 -1
  82. data/spec/cucumber/ast/table_spec.rb +2 -2
  83. data/spec/cucumber/cli/main_spec.rb +1 -1
  84. data/spec/cucumber/cli/options_spec.rb +2 -2
  85. data/spec/cucumber/formatter/html_spec.rb +20 -1
  86. data/spec/cucumber/formatter/junit_spec.rb +1 -0
  87. data/spec/cucumber/formatter/spec_helper.rb +7 -5
  88. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +0 -1
  89. data/spec/cucumber/step_mother_spec.rb +2 -2
  90. data/spec/spec_helper.rb +0 -1
  91. metadata +67 -93
  92. data/lib/cucumber/cli/language_help_formatter.rb +0 -72
  93. data/lib/cucumber/filter.rb +0 -43
  94. data/lib/cucumber/languages.yml +0 -536
  95. data/lib/cucumber/parser/common.rb +0 -182
  96. data/lib/cucumber/parser/common.tt +0 -21
  97. data/lib/cucumber/parser/feature.rb +0 -1591
  98. data/lib/cucumber/parser/feature.tt +0 -287
  99. data/lib/cucumber/parser/i18n.tt +0 -35
  100. data/lib/cucumber/parser/natural_language.rb +0 -118
  101. data/lib/cucumber/parser/py_string.rb +0 -285
  102. data/lib/cucumber/parser/py_string.tt +0 -45
  103. data/lib/cucumber/parser/table.rb +0 -314
  104. data/lib/cucumber/parser/table.tt +0 -60
  105. data/lib/cucumber/parser/treetop_ext.rb +0 -54
  106. data/lib/cucumber/tag_expression.rb +0 -41
  107. data/spec/cucumber/ast/feature_element_spec.rb +0 -41
  108. data/spec/cucumber/ast/step_collection_spec.rb +0 -17
  109. data/spec/cucumber/parser/feature_parser_spec.rb +0 -400
  110. data/spec/cucumber/parser/table_parser_spec.rb +0 -52
  111. data/spec/cucumber/tag_expression_spec.rb +0 -125
  112. data/spec/cucumber/treetop_parser/empty_feature.feature +0 -4
  113. data/spec/cucumber/treetop_parser/empty_scenario.feature +0 -9
  114. data/spec/cucumber/treetop_parser/empty_scenario_outline.feature +0 -3
  115. data/spec/cucumber/treetop_parser/fit_scenario.feature +0 -8
  116. data/spec/cucumber/treetop_parser/given_scenario.feature +0 -9
  117. data/spec/cucumber/treetop_parser/invalid_scenario_outlines.feature +0 -7
  118. data/spec/cucumber/treetop_parser/multiline_steps.feature +0 -17
  119. data/spec/cucumber/treetop_parser/multiple_tables.feature +0 -27
  120. data/spec/cucumber/treetop_parser/scenario_outline.feature +0 -16
  121. data/spec/cucumber/treetop_parser/spaces.feature +0 -12
  122. data/spec/cucumber/treetop_parser/test_dos.feature +0 -25
  123. data/spec/cucumber/treetop_parser/with_comments.feature +0 -23
  124. data/spec/cucumber/treetop_parser/with_tags.feature +0 -18
@@ -1,6 +1,8 @@
1
1
  module Cucumber
2
2
  module Ast
3
3
  class Examples #:nodoc:
4
+ attr_writer :outline_table
5
+
4
6
  def initialize(comment, line, keyword, name, outline_table)
5
7
  @comment, @keyword, @name, @outline_table = comment, keyword, name, outline_table
6
8
  end
@@ -3,30 +3,48 @@ module Cucumber
3
3
  # Represents the root node of a parsed feature.
4
4
  class Feature #:nodoc:
5
5
  attr_accessor :language
6
- attr_writer :features
6
+ attr_writer :features, :background
7
7
  attr_reader :file
8
8
  attr_reader :name
9
9
 
10
- def initialize(background, comment, tags, name, feature_elements)
11
- @background, @comment, @tags, @name, @feature_elements = background, comment, tags, name.strip, feature_elements
10
+ def initialize(background, comment, tags, keyword, name, feature_elements)
11
+ @background, @comment, @tags, @keyword, @name, @feature_elements = background, comment, tags, keyword, name.strip, feature_elements
12
+ end
12
13
 
13
- background.feature = self if background
14
+ def init
15
+ @background.feature = self if @background
16
+ @background.init if @background
14
17
  @feature_elements.each do |feature_element|
18
+ feature_element.init
15
19
  feature_element.feature = self
16
20
  end
17
21
  end
18
22
 
23
+ def add_feature_element(feature_element)
24
+ @feature_elements << feature_element
25
+ end
26
+
19
27
  def accept(visitor)
20
28
  return if Cucumber.wants_to_quit
29
+ init
21
30
  visitor.visit_comment(@comment) unless @comment.empty?
22
31
  visitor.visit_tags(@tags)
23
- visitor.visit_feature_name(@name)
32
+ visitor.visit_feature_name(@keyword, indented_name)
24
33
  visitor.visit_background(@background) if @background
25
34
  @feature_elements.each do |feature_element|
26
35
  visitor.visit_feature_element(feature_element)
27
36
  end
28
37
  end
29
38
 
39
+ def indented_name
40
+ indent = ""
41
+ @name.split("\n").map do |l|
42
+ s = "#{indent}#{l}"
43
+ indent = " "
44
+ s
45
+ end.join("\n")
46
+ end
47
+
30
48
  def source_tag_names
31
49
  @tags.tag_names
32
50
  end
@@ -36,6 +54,7 @@ module Cucumber
36
54
  end
37
55
 
38
56
  def next_feature_element(feature_element, &proc)
57
+ init
39
58
  index = @feature_elements.index(feature_element)
40
59
  next_one = @feature_elements[index+1]
41
60
  proc.call(next_one) if next_one
@@ -55,6 +74,7 @@ module Cucumber
55
74
  end
56
75
 
57
76
  def tag_locations(tag)
77
+ init
58
78
  @feature_elements.select{|feature_element| feature_element.tagged_with?(tag)}
59
79
  end
60
80
 
@@ -68,6 +88,7 @@ module Cucumber
68
88
  end
69
89
 
70
90
  def to_sexp
91
+ init
71
92
  sexp = [:feature, @file, @name]
72
93
  comment = @comment.to_sexp
73
94
  sexp += [comment] if comment
@@ -1,11 +1,15 @@
1
1
  require 'enumerator'
2
- require 'cucumber/tag_expression'
2
+ require 'gherkin/parser/tag_expression'
3
3
 
4
4
  module Cucumber
5
5
  module Ast
6
6
  module FeatureElement #:nodoc:
7
7
  attr_accessor :feature
8
8
 
9
+ def add_step(step)
10
+ @raw_steps << step
11
+ end
12
+
9
13
  def attach_steps(steps)
10
14
  steps.each {|step| step.feature_element = self}
11
15
  end
@@ -14,20 +18,24 @@ module Cucumber
14
18
  @feature.file_colon_line(line) if @feature
15
19
  end
16
20
 
17
- def text_length
18
- name_line_lengths.max
19
- end
20
-
21
21
  def first_line_length
22
22
  name_line_lengths[0]
23
23
  end
24
24
 
25
+ def text_length
26
+ name_line_lengths.max
27
+ end
28
+
25
29
  def name_line_lengths
26
30
  if @name.strip.empty?
27
- [@keyword.jlength]
31
+ [Ast::Step::INDENT + @keyword.jlength + ': '.jlength]
28
32
  else
29
33
  @name.split("\n").enum_for(:each_with_index).map do |line, line_number|
30
- line_number == 0 ? @keyword.jlength + line.jlength : line.jlength + Ast::Step::INDENT - 1 # We -1 as names which are not keyword lines are missing a space between keyword and name
34
+ if line_number == 0
35
+ Ast::Step::INDENT + @keyword.jlength + ': '.jlength + line.jlength
36
+ else
37
+ Ast::Step::INDENT + Ast::Step::INDENT + line.jlength
38
+ end
31
39
  end
32
40
  end
33
41
  end
@@ -36,7 +44,7 @@ module Cucumber
36
44
  scenario_name_regexps.detect{|name| name =~ @name}
37
45
  end
38
46
 
39
- def backtrace_line(name = "#{@keyword} #{@name}", line = @line)
47
+ def backtrace_line(name = "#{@keyword}: #{@name}", line = @line)
40
48
  @feature.backtrace_line(name, line) if @feature
41
49
  end
42
50
 
@@ -45,11 +53,12 @@ module Cucumber
45
53
  end
46
54
 
47
55
  def max_line_length
56
+ init
48
57
  @steps.max_line_length(self)
49
58
  end
50
59
 
51
60
  def accept_hook?(hook)
52
- TagExpression.parse(hook.tag_expressions).eval(source_tag_names)
61
+ Gherkin::Parser::TagExpression.new(hook.tag_expressions).eval(source_tag_names)
53
62
  end
54
63
 
55
64
  def source_tag_names
@@ -5,11 +5,20 @@ module Cucumber
5
5
  super(raw)
6
6
  @scenario_outline = scenario_outline
7
7
  @cells_class = ExampleRow
8
- create_step_invocations_for_example_rows!(scenario_outline)
8
+ end
9
+
10
+ def init
11
+ create_step_invocations_for_example_rows!(@scenario_outline)
12
+ end
13
+
14
+ def to_sexp
15
+ init
16
+ super
9
17
  end
10
18
 
11
19
  def accept(visitor)
12
20
  return if Cucumber.wants_to_quit
21
+ init
13
22
  cells_rows.each_with_index do |row, n|
14
23
  if(visitor.options[:expand])
15
24
  row.accept(visitor)
@@ -29,12 +38,15 @@ module Cucumber
29
38
  end
30
39
 
31
40
  def skip_invoke!
41
+ init
32
42
  example_rows.each do |cells|
33
43
  cells.skip_invoke!
34
44
  end
35
45
  end
36
46
 
37
47
  def create_step_invocations_for_example_rows!(scenario_outline)
48
+ return if @dunit
49
+ @dunit = true
38
50
  example_rows.each do |cells|
39
51
  cells.create_step_invocations!(scenario_outline)
40
52
  end
@@ -17,23 +17,40 @@ module Cucumber
17
17
  # Note how the indentation from the source is stripped away.
18
18
  #
19
19
  class PyString #:nodoc:
20
+ class Builder
21
+ attr_reader :string
22
+
23
+ def initialize
24
+ @string = ''
25
+ end
26
+
27
+ def py_string(string, line_number)
28
+ @string = string
29
+ end
30
+
31
+ def eof
32
+ end
33
+ end
34
+
20
35
  attr_accessor :file
21
36
 
22
37
  def self.default_arg_name
23
38
  "string"
24
39
  end
25
40
 
26
- def initialize(start_line, end_line, string, quotes_indent)
27
- @start_line, @end_line = start_line, end_line
28
- @string, @quotes_indent = string.gsub(/\\"/, '"'), quotes_indent
41
+ def self.parse(text)
42
+ builder = Builder.new
43
+ lexer = Gherkin::I18nLexer.new(builder)
44
+ lexer.scan(text)
45
+ new(builder.string)
46
+ end
47
+
48
+ def initialize(string)
49
+ @string = string
29
50
  end
30
51
 
31
52
  def to_s
32
- # Assume all whitespace before the first triple quote is the same.
33
- # Also assume the contents of the pystring is indented with the same prefix.
34
- # This allows indentation with both " " and "\t" characters.
35
- return @string if @quotes_indent == ""
36
- @string.gsub(/^#{@quotes_indent[0..0]}{0,#{@quotes_indent.length}}/, "")
53
+ @string
37
54
  end
38
55
 
39
56
  def accept(visitor)
@@ -47,7 +64,7 @@ module Cucumber
47
64
  value ||= ''
48
65
  string = string.gsub(name, value)
49
66
  end
50
- PyString.new(@start_line, @end_line, string, @quotes_indent)
67
+ PyString.new(string)
51
68
  end
52
69
 
53
70
  def has_text?(text)
@@ -19,18 +19,24 @@ module Cucumber
19
19
  def step_collection(step_invocations)
20
20
  StepCollection.new(step_invocations)
21
21
  end
22
+
23
+ def init
24
+ end
22
25
  end
23
26
 
24
- def initialize(background, comment, tags, line, keyword, name, steps)
27
+ def initialize(background, comment, tags, line, keyword, name, raw_steps)
25
28
  @background = background || EmptyBackground.new
26
- @comment, @tags, @line, @keyword, @name = comment, tags, line, keyword, name
27
- attach_steps(steps)
29
+ @comment, @tags, @line, @keyword, @name, @raw_steps = comment, tags, line, keyword, name, raw_steps
30
+ @exception = @executed = nil
31
+ end
28
32
 
29
- step_invocations = steps.map{|step| step.step_invocation}
30
- @steps = @background.step_collection(step_invocations)
33
+ def init
34
+ return if @steps
35
+ @background.init
31
36
  @background.feature_elements << self
32
-
33
- @exception = @executed = nil
37
+ attach_steps(@raw_steps)
38
+ step_invocations = @raw_steps.map{|step| step.step_invocation}
39
+ @steps = @background.step_collection(step_invocations)
34
40
  end
35
41
 
36
42
  def accept(visitor)
@@ -2,6 +2,8 @@ module Cucumber
2
2
  module Ast
3
3
  class ScenarioOutline #:nodoc:
4
4
  include FeatureElement
5
+
6
+ attr_reader :name
5
7
 
6
8
  module ExamplesArray #:nodoc:
7
9
  def accept(visitor)
@@ -18,12 +20,20 @@ module Cucumber
18
20
  # * Examples keyword
19
21
  # * Examples section name
20
22
  # * Raw matrix
21
- def initialize(background, comment, tags, line, keyword, name, steps, example_sections)
22
- @background, @comment, @tags, @line, @keyword, @name = background, comment, tags, line, keyword, name
23
- attach_steps(steps)
24
- @steps = StepCollection.new(steps)
23
+ def initialize(background, comment, tags, line, keyword, name, raw_steps, example_sections)
24
+ @background, @comment, @tags, @line, @keyword, @name, @raw_steps, @example_sections = background, comment, tags, line, keyword, name, raw_steps, example_sections
25
+ end
26
+
27
+ def add_examples(example_section)
28
+ @example_sections << example_section
29
+ end
25
30
 
26
- @examples_array = example_sections.map do |example_section|
31
+ def init
32
+ return if @steps
33
+ attach_steps(@raw_steps)
34
+ @steps = StepCollection.new(@raw_steps)
35
+
36
+ @examples_array = @example_sections.map do |example_section|
27
37
  examples_comment = example_section[0]
28
38
  examples_line = example_section[1]
29
39
  examples_keyword = example_section[2]
@@ -33,6 +43,7 @@ module Cucumber
33
43
  examples_table = OutlineTable.new(examples_matrix, self)
34
44
  Examples.new(examples_comment, examples_line, examples_keyword, examples_name, examples_table)
35
45
  end
46
+
36
47
  @examples_array.extend(ExamplesArray)
37
48
 
38
49
  @background.feature_elements << self if @background
@@ -73,7 +84,7 @@ module Cucumber
73
84
 
74
85
  def visit_scenario_name(visitor, row)
75
86
  visitor.visit_scenario_name(
76
- @feature.language.scenario_keywords[0] + ":",
87
+ @feature.language.keywords('scenario')[0],
77
88
  row.name,
78
89
  file_colon_line(row.line),
79
90
  source_indent(first_line_length)
@@ -85,6 +96,7 @@ module Cucumber
85
96
  end
86
97
 
87
98
  def to_sexp
99
+ init
88
100
  sexp = [:scenario_outline, @keyword, @name]
89
101
  comment = @comment.to_sexp
90
102
  sexp += [comment] if comment
@@ -4,9 +4,9 @@ require 'cucumber/step_match'
4
4
  module Cucumber
5
5
  module Ast
6
6
  class Step #:nodoc:
7
- attr_reader :line, :keyword, :name, :multiline_arg
7
+ attr_reader :line, :keyword, :name
8
8
  attr_writer :step_collection, :options
9
- attr_accessor :feature_element, :exception
9
+ attr_accessor :feature_element, :exception, :multiline_arg
10
10
 
11
11
  INDENT = 2
12
12
 
@@ -69,11 +69,11 @@ module Cucumber
69
69
  end
70
70
 
71
71
  def text_length(name=@name)
72
- @keyword.jlength + name.jlength + INDENT # Add indent as steps get indented more than scenarios
72
+ INDENT + INDENT + @keyword.jlength + name.jlength
73
73
  end
74
74
 
75
75
  def backtrace_line
76
- @backtrace_line ||= @feature_element.backtrace_line("#{@keyword} #{@name}", @line) unless @feature_element.nil?
76
+ @backtrace_line ||= @feature_element.backtrace_line("#{@keyword}#{@name}", @line) unless @feature_element.nil?
77
77
  end
78
78
 
79
79
  def file_colon_line
@@ -1,9 +1,12 @@
1
1
  require 'cucumber/step_match'
2
2
  require 'cucumber/ast/table'
3
+ require 'gherkin/rubify'
3
4
 
4
5
  module Cucumber
5
6
  module Ast
6
7
  class StepInvocation #:nodoc:
8
+ include Gherkin::Rubify
9
+
7
10
  BACKTRACE_FILTER_PATTERNS = [
8
11
  /vendor\/rails|lib\/cucumber|bin\/cucumber:|lib\/rspec|gems\//
9
12
  ]
@@ -142,11 +145,11 @@ module Cucumber
142
145
  end
143
146
 
144
147
  def actual_keyword
145
- repeat_keywords = [language.but_keywords(false), language.and_keywords(false)].flatten.uniq.reject{|kw| kw == '*'}
148
+ repeat_keywords = rubify([language.keywords('but'), language.keywords('and')]).flatten.uniq.reject{|kw| kw == '* '}
146
149
  if repeat_keywords.index(@step.keyword) && previous
147
150
  previous.actual_keyword
148
151
  else
149
- keyword == '*' ? language.given_keyword : keyword
152
+ keyword == '* ' ? language.code_keywords.first : keyword
150
153
  end
151
154
  end
152
155
 
@@ -1,3 +1,5 @@
1
+ require 'gherkin/rubify'
2
+
1
3
  module Cucumber
2
4
  module Ast
3
5
  # Step Definitions that match a plain text Step with a multiline argument table
@@ -29,7 +31,23 @@ module Cucumber
29
31
  end
30
32
  end
31
33
 
34
+ class Builder
35
+ attr_reader :rows
36
+
37
+ def initialize
38
+ @rows = []
39
+ end
40
+
41
+ def row(row, line_number)
42
+ @rows << row
43
+ end
44
+
45
+ def eof
46
+ end
47
+ end
48
+
32
49
  include Enumerable
50
+ include Gherkin::Rubify
33
51
 
34
52
  NULL_CONVERSIONS = Hash.new(lambda{ |cell_value| cell_value }).freeze
35
53
 
@@ -39,6 +57,13 @@ module Cucumber
39
57
  "table"
40
58
  end
41
59
 
60
+ def self.parse(text)
61
+ builder = Builder.new
62
+ lexer = Gherkin::I18nLexer.new(builder)
63
+ lexer.scan(text)
64
+ new(builder.rows)
65
+ end
66
+
42
67
  # Creates a new instance. +raw+ should be an Array of Array of String
43
68
  # or an Array of Hash (similar to what #hashes returns).
44
69
  # You don't typically create your own Table objects - Cucumber will do
@@ -48,7 +73,7 @@ module Cucumber
48
73
  @cells_class = Cells
49
74
  @cell_class = Cell
50
75
 
51
- raw = ensure_array_of_array(raw)
76
+ raw = ensure_array_of_array(rubify(raw))
52
77
  # Verify that it's square
53
78
  transposed = raw.transpose
54
79
  create_cell_matrix(raw)