cucumber 0.8.7 → 0.9.0

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.
Files changed (64) hide show
  1. data/.gitignore +24 -0
  2. data/Gemfile +5 -0
  3. data/History.txt +16 -3
  4. data/Rakefile +4 -50
  5. data/cucumber.gemspec +36 -600
  6. data/features/cucumber_cli.feature +1 -1
  7. data/features/json_formatter.feature +1 -1
  8. data/features/junit_formatter.feature +10 -6
  9. data/features/post_configuration_hook.feature +15 -2
  10. data/features/step_definitions/cucumber_steps.rb +5 -1
  11. data/features/step_definitions/wire_steps.rb +1 -0
  12. data/features/support/env.rb +2 -5
  13. data/features/wire_protocol.feature +1 -1
  14. data/lib/cucumber.rb +8 -0
  15. data/lib/cucumber/ast/outline_table.rb +4 -4
  16. data/lib/cucumber/ast/step_invocation.rb +14 -13
  17. data/lib/cucumber/ast/table.rb +2 -1
  18. data/lib/cucumber/ast/tree_walker.rb +3 -3
  19. data/lib/cucumber/cli/configuration.rb +32 -7
  20. data/lib/cucumber/cli/main.rb +26 -30
  21. data/lib/cucumber/cli/options.rb +1 -3
  22. data/lib/cucumber/cli/profile_loader.rb +2 -0
  23. data/lib/cucumber/configuration.rb +37 -0
  24. data/lib/cucumber/errors.rb +40 -0
  25. data/lib/cucumber/feature_file.rb +5 -12
  26. data/lib/cucumber/formatter/junit.rb +2 -2
  27. data/lib/cucumber/formatter/tag_cloud.rb +1 -1
  28. data/lib/cucumber/js_support/js_dsl.js +4 -4
  29. data/lib/cucumber/js_support/js_language.rb +9 -5
  30. data/lib/cucumber/language_support.rb +2 -2
  31. data/lib/cucumber/parser/gherkin_builder.rb +19 -19
  32. data/lib/cucumber/platform.rb +3 -4
  33. data/lib/cucumber/rake/task.rb +1 -7
  34. data/lib/cucumber/rb_support/rb_dsl.rb +1 -0
  35. data/lib/cucumber/rb_support/rb_language.rb +1 -0
  36. data/lib/cucumber/rspec/doubles.rb +3 -3
  37. data/lib/cucumber/runtime.rb +192 -0
  38. data/lib/cucumber/runtime/features_loader.rb +62 -0
  39. data/lib/cucumber/runtime/results.rb +46 -0
  40. data/lib/cucumber/runtime/support_code.rb +174 -0
  41. data/lib/cucumber/runtime/user_interface.rb +80 -0
  42. data/lib/cucumber/step_mother.rb +6 -427
  43. data/lib/cucumber/wire_support/configuration.rb +2 -0
  44. data/lib/cucumber/wire_support/wire_language.rb +1 -8
  45. data/spec/cucumber/ast/background_spec.rb +3 -3
  46. data/spec/cucumber/ast/feature_spec.rb +2 -2
  47. data/spec/cucumber/ast/scenario_outline_spec.rb +1 -1
  48. data/spec/cucumber/ast/scenario_spec.rb +1 -2
  49. data/spec/cucumber/ast/tree_walker_spec.rb +1 -1
  50. data/spec/cucumber/cli/configuration_spec.rb +31 -5
  51. data/spec/cucumber/cli/drb_client_spec.rb +1 -1
  52. data/spec/cucumber/cli/main_spec.rb +8 -37
  53. data/spec/cucumber/cli/options_spec.rb +20 -0
  54. data/spec/cucumber/formatter/spec_helper.rb +5 -7
  55. data/spec/cucumber/rb_support/rb_language_spec.rb +2 -2
  56. data/spec/cucumber/rb_support/rb_step_definition_spec.rb +1 -1
  57. data/spec/cucumber/runtime_spec.rb +294 -0
  58. data/spec/cucumber/step_match_spec.rb +10 -8
  59. data/spec/cucumber/world/pending_spec.rb +1 -1
  60. data/spec/spec_helper.rb +2 -21
  61. metadata +215 -84
  62. data/Caliper.yml +0 -4
  63. data/VERSION.yml +0 -5
  64. data/spec/cucumber/step_mother_spec.rb +0 -302
@@ -1,3 +1,5 @@
1
+ require 'yaml'
2
+
1
3
  module Cucumber
2
4
  module Cli
3
5
 
@@ -0,0 +1,37 @@
1
+ module Cucumber
2
+ # The base class for configuring settings for a Cucumber run.
3
+ class Configuration
4
+ def self.default
5
+ new
6
+ end
7
+
8
+ def self.parse(argument)
9
+ return new(argument) if argument.is_a?(Hash)
10
+ argument
11
+ end
12
+
13
+ def initialize(options = {})
14
+ @options = options
15
+ end
16
+
17
+ def dry_run?
18
+ @options[:dry_run]
19
+ end
20
+
21
+ def guess?
22
+ @options[:guess]
23
+ end
24
+
25
+ def strict?
26
+ @options[:strict]
27
+ end
28
+
29
+ def expand?
30
+ @options[:expand]
31
+ end
32
+
33
+ def paths
34
+ @options[:paths]
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ module Cucumber
2
+ # Raised when there is no matching StepDefinition for a step.
3
+ class Undefined < StandardError
4
+ attr_reader :step_name
5
+
6
+ def initialize(step_name)
7
+ super %{Undefined step: "#{step_name}"}
8
+ @step_name = step_name
9
+ end
10
+
11
+ def nested!
12
+ @nested = true
13
+ end
14
+
15
+ def nested?
16
+ @nested
17
+ end
18
+ end
19
+
20
+ # Raised when a StepDefinition's block invokes World#pending
21
+ class Pending < StandardError
22
+ end
23
+
24
+ # Raised when a step matches 2 or more StepDefinitions
25
+ class Ambiguous < StandardError
26
+ def initialize(step_name, step_definitions, used_guess)
27
+ message = "Ambiguous match of \"#{step_name}\":\n\n"
28
+ message << step_definitions.map{|sd| sd.backtrace_line}.join("\n")
29
+ message << "\n\n"
30
+ message << "You can run again with --guess to make Cucumber be more smart about it\n" unless used_guess
31
+ super(message)
32
+ end
33
+ end
34
+
35
+ class TagExcess < StandardError
36
+ def initialize(messages)
37
+ super(messages.join("\n"))
38
+ end
39
+ end
40
+ end
@@ -2,14 +2,13 @@ require 'cucumber/parser/gherkin_builder'
2
2
  require 'gherkin/formatter/filter_formatter'
3
3
  require 'gherkin/formatter/tag_count_formatter'
4
4
  require 'gherkin/parser/parser'
5
- require 'gherkin/i18n_lexer'
6
5
 
7
6
  module Cucumber
8
7
  class FeatureFile
9
8
  FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/ #:nodoc:
10
9
  LANGUAGE_PATTERN = /language:\s*(.*)/ #:nodoc:
11
10
 
12
- # The +uri+ argument is the location of the source. It can ba a path
11
+ # The +uri+ argument is the location of the source. It can be a path
13
12
  # or a path:line1:line2 etc. If +source+ is passed, +uri+ is ignored.
14
13
  def initialize(uri, source=nil)
15
14
  @source = source
@@ -22,10 +21,10 @@ module Cucumber
22
21
  end
23
22
 
24
23
  # Parses a file and returns a Cucumber::Ast
25
- # If +options+ contains tags, the result will
24
+ # If +configuration_filters+ contains any filters, the result will
26
25
  # be filtered.
27
- def parse(options, tag_counts)
28
- filters = @lines || options.filters
26
+ def parse(configuration_filters, tag_counts)
27
+ filters = @lines || configuration_filters
29
28
 
30
29
  builder = Cucumber::Parser::GherkinBuilder.new
31
30
  filter_formatter = filters.empty? ? builder : Gherkin::Formatter::FilterFormatter.new(builder, filters)
@@ -39,7 +38,7 @@ module Cucumber
39
38
  ast.language = parser.i18n_language
40
39
  ast.file = @path
41
40
  ast
42
- rescue Gherkin::LexingError, Gherkin::Parser::ParseError => e
41
+ rescue Gherkin::Lexer::LexingError, Gherkin::Parser::ParseError => e
43
42
  e.message.insert(0, "#{@path}: ")
44
43
  raise e
45
44
  end
@@ -59,11 +58,5 @@ module Cucumber
59
58
  end
60
59
  end
61
60
  end
62
-
63
- private
64
-
65
- # Special PML markup that we want to filter out.
66
- CO = %{\\s*<(label|callout)\s+id=".*?"\s*/>\\s*}
67
- C_CALLOUT = %r{/\*#{CO}\*/|//#{CO}}o
68
61
  end
69
62
  end
@@ -122,8 +122,8 @@ module Cucumber
122
122
  @builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
123
123
  if failed
124
124
  @builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
125
- @builder.text! @output
126
- @builder.text!(format_exception(exception)) if exception
125
+ @builder.cdata! @output
126
+ @builder.cdata!(format_exception(exception)) if exception
127
127
  end
128
128
  @failures += 1
129
129
  end
@@ -28,7 +28,7 @@ module Cucumber
28
28
  matrix = @counts.to_a.sort{|paira, pairb| paira[0] <=> pairb[0]}.transpose
29
29
  table = Cucumber::Ast::Table.new(matrix)
30
30
  formatter = Cucumber::Formatter::Pretty.new(@step_mother, @io, {})
31
- Cucumber::Ast::TreeWalker.new(@step_mother, [formatter], {}).visit_multiline_arg(table)
31
+ Cucumber::Ast::TreeWalker.new(@step_mother, [formatter]).visit_multiline_arg(table)
32
32
  end
33
33
  end
34
34
  end
@@ -1,15 +1,15 @@
1
1
  var CucumberJsDsl = {
2
2
  registerStepDefinition: function(regexp, func) {
3
3
  if(func == null) {
4
- jsLanguage.executeStepDefinition(regexp);
4
+ jsLanguage.execute_step_definition(regexp);
5
5
  }
6
6
  else{
7
- jsLanguage.addStepDefinition(regexp, func);
7
+ jsLanguage.add_step_definition(regexp, func);
8
8
  }
9
9
  },
10
10
 
11
11
  registerTransform: function(regexp, func) {
12
- jsLanguage.registerJsTransform(regexp, func);
12
+ jsLanguage.register_js_transform(regexp, func);
13
13
  },
14
14
 
15
15
  beforeHook: function(tag_expressions_or_func, func) {
@@ -40,7 +40,7 @@ var CucumberJsDsl = {
40
40
  var hook_func = tag_expressions_or_func;
41
41
  var tag_expressions = [];
42
42
  }
43
- jsLanguage.registerJsHook(label, tag_expressions, hook_func);
43
+ jsLanguage.register_js_hook(label, tag_expressions, hook_func);
44
44
  }
45
45
  }
46
46
 
@@ -39,6 +39,10 @@ module Cucumber
39
39
  @js_language.current_world.execute(@js_function, args)
40
40
  end
41
41
 
42
+ def regexp_source
43
+ @regexp.inspect
44
+ end
45
+
42
46
  def arguments_from(step_name)
43
47
  matches = eval_js "#{@regexp}.exec('#{step_name}')"
44
48
  if matches
@@ -101,10 +105,10 @@ module Cucumber
101
105
  include LanguageSupport::LanguageMethods
102
106
  include JsSnippets
103
107
 
104
- def initialize(step_mother)
108
+ def initialize(runtime)
105
109
  @step_definitions = []
106
110
  @world = JsWorld.new
107
- @step_mother = step_mother
111
+ @runtime = runtime
108
112
 
109
113
  @world["jsLanguage"] = self
110
114
  @world.load(File.dirname(__FILE__) + '/js_dsl.js')
@@ -146,7 +150,7 @@ module Cucumber
146
150
 
147
151
  #TODO: support multiline arguments when calling steps from within steps
148
152
  def execute_step_definition(name, multiline_argument = nil)
149
- @step_mother.step_match(name).invoke(multiline_argument)
153
+ @runtime.step_match(name).invoke(multiline_argument)
150
154
  end
151
155
 
152
156
  def register_js_hook(phase, tag_expressions, js_function)
@@ -162,12 +166,12 @@ module Cucumber
162
166
  end
163
167
 
164
168
  def steps(steps_text, file_colon_line)
165
- @step_mother.invoke_steps(steps_text, @language, file_colon_line)
169
+ @runtime.invoke_steps(steps_text, @language, file_colon_line)
166
170
  end
167
171
 
168
172
  private
169
173
  def path_to_load_js_from
170
- paths = @step_mother.options[:paths]
174
+ paths = @runtime.features_paths
171
175
  if paths.empty?
172
176
  '' # Using rake
173
177
  else
@@ -1,5 +1,5 @@
1
1
  module Cucumber
2
- # This module defines the API for programming panguage support in Cucumber.
2
+ # This module defines the API for programming language support in Cucumber.
3
3
  # While Cucumber itself is written in Ruby, any programming language can
4
4
  # be supported by implementing this API.
5
5
  #
@@ -27,4 +27,4 @@ module Cucumber
27
27
  #
28
28
  module LanguageSupport
29
29
  end
30
- end
30
+ end
@@ -13,23 +13,23 @@ module Cucumber
13
13
  @feature || @multiline_arg
14
14
  end
15
15
 
16
- def feature(statement, uri)
16
+ def feature(feature)
17
17
  @feature = Ast::Feature.new(
18
18
  nil,
19
- Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")),
20
- Ast::Tags.new(nil, statement.tags.map{|tag| tag.name}),
21
- statement.keyword,
22
- legacy_name_for(statement.name, statement.description),
19
+ Ast::Comment.new(feature.comments.map{|comment| comment.value}.join("\n")),
20
+ Ast::Tags.new(nil, feature.tags.map{|tag| tag.name}),
21
+ feature.keyword,
22
+ legacy_name_for(feature.name, feature.description),
23
23
  []
24
24
  )
25
25
  end
26
26
 
27
- def background(statement)
27
+ def background(background)
28
28
  @background = Ast::Background.new(
29
- Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")),
30
- statement.line,
31
- statement.keyword,
32
- legacy_name_for(statement.name, statement.description),
29
+ Ast::Comment.new(background.comments.map{|comment| comment.value}.join("\n")),
30
+ background.line,
31
+ background.keyword,
32
+ legacy_name_for(background.name, background.description),
33
33
  steps=[]
34
34
  )
35
35
  @feature.background = @background
@@ -71,20 +71,20 @@ module Cucumber
71
71
  @step_container = scenario_outline
72
72
  end
73
73
 
74
- def examples(statement, examples_rows)
74
+ def examples(examples)
75
75
  examples_fields = [
76
- Ast::Comment.new(statement.comments.map{|comment| comment.value}.join("\n")),
77
- statement.line,
78
- statement.keyword,
79
- legacy_name_for(statement.name, statement.description),
80
- matrix(examples_rows)
76
+ Ast::Comment.new(examples.comments.map{|comment| comment.value}.join("\n")),
77
+ examples.line,
78
+ examples.keyword,
79
+ legacy_name_for(examples.name, examples.description),
80
+ matrix(examples.rows)
81
81
  ]
82
82
  @step_container.add_examples(examples_fields)
83
83
  end
84
84
 
85
- def step(statement, multiline_arg, result)
86
- @table_owner = Ast::Step.new(statement.line, statement.keyword, statement.name)
87
- multiline_arg = rubify(multiline_arg)
85
+ def step(step)
86
+ @table_owner = Ast::Step.new(step.line, step.keyword, step.name)
87
+ multiline_arg = rubify(step.multiline_arg)
88
88
  case(multiline_arg)
89
89
  when Gherkin::Formatter::Model::PyString
90
90
  @table_owner.multiline_arg = Ast::PyString.new(multiline_arg.value)
@@ -1,11 +1,9 @@
1
1
  # Detect the platform we're running on so we can tweak behaviour
2
2
  # in various places.
3
- require 'rbconfig'
4
- require 'yaml'
5
3
 
6
4
  module Cucumber
7
- version = YAML.load_file(File.dirname(__FILE__) + '/../../VERSION.yml')
8
- VERSION = [version[:major], version[:minor], version[:patch], version[:build]].compact.join('.')
5
+ unless defined?(Cucumber::VERSION)
6
+ VERSION = '0.9.0'
9
7
  BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
10
8
  LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
11
9
  JRUBY = defined?(JRUBY_VERSION)
@@ -27,3 +25,4 @@ module Cucumber
27
25
  end
28
26
  self.use_full_backtrace = false
29
27
  end
28
+ end
@@ -1,11 +1,5 @@
1
1
  require 'cucumber/platform'
2
2
 
3
- begin
4
- # Support Rake > 0.8.7
5
- require 'rake/dsl_definition'
6
- include Rake::DSL
7
- rescue LoadError
8
- end
9
3
  module Cucumber
10
4
  module Rake
11
5
  # Defines a Rake task for running features.
@@ -71,7 +65,7 @@ module Cucumber
71
65
  end
72
66
 
73
67
  def runner
74
- File.exist?("./Gemfile") ? ["bundle", "exec", RUBY] : [RUBY]
68
+ File.exist?("./Gemfile") && Gem.available?("bundler") ? ["bundle", "exec", RUBY] : [RUBY]
75
69
  end
76
70
 
77
71
  def run
@@ -88,6 +88,7 @@ module Cucumber
88
88
 
89
89
  # Registers a proc that will run after Cucumber is configured. You can register as
90
90
  # as you want (typically from ruby scripts under <tt>support/hooks.rb</tt>).
91
+ # TODO: Deprecate this
91
92
  def AfterConfiguration(&proc)
92
93
  RbDsl.register_rb_hook('after_configuration', [], proc)
93
94
  end
@@ -1,3 +1,4 @@
1
+ require 'cucumber/core_ext/instance_exec'
1
2
  require 'cucumber/rb_support/rb_dsl'
2
3
  require 'cucumber/rb_support/rb_world'
3
4
  require 'cucumber/rb_support/rb_step_definition'
@@ -4,13 +4,13 @@ RSpec.configuration.configure_mock_framework
4
4
  World(RSpec::Core::MockFrameworkAdapter)
5
5
 
6
6
  Before do
7
- _setup_mocks
7
+ RSpec::Mocks::setup(self)
8
8
  end
9
9
 
10
10
  After do
11
11
  begin
12
- _verify_mocks
12
+ RSpec::Mocks::verify
13
13
  ensure
14
- _teardown_mocks
14
+ RSpec::Mocks::teardown
15
15
  end
16
16
  end
@@ -0,0 +1,192 @@
1
+ require 'cucumber/configuration'
2
+ require 'cucumber/language_support/language_methods'
3
+ require 'cucumber/formatter/duration'
4
+ require 'gherkin/rubify'
5
+ require 'cucumber/runtime/user_interface'
6
+ require 'cucumber/runtime/features_loader'
7
+ require 'cucumber/runtime/results'
8
+ require 'cucumber/runtime/support_code'
9
+
10
+ module Cucumber
11
+ # This is the meaty part of Cucumber that ties everything together.
12
+ class Runtime
13
+ attr_reader :results
14
+
15
+ include Formatter::Duration
16
+ include Runtime::UserInterface
17
+
18
+ def initialize(configuration = Configuration.default)
19
+ @current_scenario = nil
20
+ @configuration = Configuration.parse(configuration)
21
+ @support_code = SupportCode.new(self, @configuration.guess?)
22
+ @results = Results.new(@configuration)
23
+ end
24
+
25
+ def run!
26
+ load_step_definitions
27
+ fire_after_configuration_hook
28
+
29
+ tree_walker = @configuration.build_tree_walker(self)
30
+ self.visitor = tree_walker # Ugly circular dependency, but needed to support World#announce
31
+
32
+ tree_walker.visit_features(features)
33
+ end
34
+
35
+ def features_paths
36
+ @configuration.paths
37
+ end
38
+
39
+ def step_visited(step) #:nodoc:
40
+ @results.step_visited(step)
41
+ end
42
+
43
+ def scenarios(status = nil)
44
+ @results.scenarios(status)
45
+ end
46
+
47
+ def steps(status = nil)
48
+ @results.steps(status)
49
+ end
50
+
51
+ # Loads and registers programming language implementation.
52
+ # Instances are cached, so calling with the same argument
53
+ # twice will return the same instance.
54
+ #
55
+ def load_programming_language(ext)
56
+ @support_code.load_programming_language!(ext)
57
+ end
58
+
59
+ def invoke(step_name, multiline_argument)
60
+ @support_code.invoke(step_name, multiline_argument)
61
+ end
62
+
63
+ # Invokes a series of steps +steps_text+. Example:
64
+ #
65
+ # invoke(%Q{
66
+ # Given I have 8 cukes in my belly
67
+ # Then I should not be thirsty
68
+ # })
69
+ def invoke_steps(steps_text, i18n, file_colon_line)
70
+ @support_code.invoke_steps(steps_text, i18n, file_colon_line)
71
+ end
72
+
73
+ # Returns a Cucumber::Ast::Table for +text_or_table+, which can either
74
+ # be a String:
75
+ #
76
+ # table(%{
77
+ # | account | description | amount |
78
+ # | INT-100 | Taxi | 114 |
79
+ # | CUC-101 | Peeler | 22 |
80
+ # })
81
+ #
82
+ # or a 2D Array:
83
+ #
84
+ # table([
85
+ # %w{ account description amount },
86
+ # %w{ INT-100 Taxi 114 },
87
+ # %w{ CUC-101 Peeler 22 }
88
+ # ])
89
+ #
90
+ def table(text_or_table, file=nil, line_offset=0)
91
+ if Array === text_or_table
92
+ Ast::Table.new(text_or_table)
93
+ else
94
+ Ast::Table.parse(text_or_table, file, line_offset)
95
+ end
96
+ end
97
+
98
+ # Returns a regular String for +string_with_triple_quotes+. Example:
99
+ #
100
+ # """
101
+ # hello
102
+ # world
103
+ # """
104
+ #
105
+ # Is retured as: " hello\nworld"
106
+ #
107
+ def py_string(string_with_triple_quotes, file=nil, line_offset=0)
108
+ Ast::PyString.parse(string_with_triple_quotes)
109
+ end
110
+
111
+ def step_match(step_name, name_to_report=nil) #:nodoc:
112
+ @support_code.step_match(step_name, name_to_report)
113
+ end
114
+
115
+ def unmatched_step_definitions
116
+ @support_code.unmatched_step_definitions
117
+ end
118
+
119
+ def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
120
+ @support_code.snippet_text(step_keyword, step_name, multiline_arg_class)
121
+ end
122
+
123
+ def with_hooks(scenario, skip_hooks=false)
124
+ around(scenario, skip_hooks) do
125
+ before_and_after(scenario, skip_hooks) do
126
+ yield scenario
127
+ end
128
+ end
129
+ end
130
+
131
+ def around(scenario, skip_hooks=false, &block) #:nodoc:
132
+ if skip_hooks
133
+ yield
134
+ return
135
+ end
136
+
137
+ @support_code.around(scenario, block)
138
+ end
139
+
140
+ def before_and_after(scenario, skip_hooks=false) #:nodoc:
141
+ before(scenario) unless skip_hooks
142
+ yield scenario
143
+ after(scenario) unless skip_hooks
144
+ @results.scenario_visited(scenario)
145
+ end
146
+
147
+ def before(scenario) #:nodoc:
148
+ return if @configuration.dry_run? || @current_scenario
149
+ @current_scenario = scenario
150
+ @support_code.fire_hook(:before, scenario)
151
+ end
152
+
153
+ def after(scenario) #:nodoc:
154
+ @current_scenario = nil
155
+ return if @configuration.dry_run?
156
+ @support_code.fire_hook(:after, scenario)
157
+ end
158
+
159
+ def after_step #:nodoc:
160
+ return if @configuration.dry_run?
161
+ @support_code.fire_hook(:execute_after_step, @current_scenario)
162
+ end
163
+
164
+ def unknown_programming_language?
165
+ @support_code.unknown_programming_language?
166
+ end
167
+
168
+ private
169
+
170
+ def fire_after_configuration_hook #:nodoc
171
+ @support_code.fire_hook(:after_configuration, @configuration)
172
+ end
173
+
174
+ def features
175
+ loader = Runtime::FeaturesLoader.new(
176
+ @configuration.feature_files,
177
+ @configuration.filters,
178
+ @configuration.tag_expression)
179
+ loader.features
180
+ end
181
+
182
+ def load_step_definitions
183
+ files = @configuration.support_to_load + @configuration.step_defs_to_load
184
+ @support_code.load_files!(files)
185
+ end
186
+
187
+ def log
188
+ Cucumber.logger
189
+ end
190
+ end
191
+
192
+ end