Class: Cucumber::StepMother

Inherits:
Object show all
Includes:
Constantize
Defined in:
lib/cucumber/step_mother.rb

Overview

This is the meaty part of Cucumber that ties everything together.

Defined Under Namespace

Classes: StepArgumentTransform

Constant Summary collapse

@@transforms =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Constantize

#constantize, #underscore

Constructor Details

#initializeStepMother

Returns a new instance of StepMother.



58
59
60
61
62
63
# File 'lib/cucumber/step_mother.rb', line 58

def initialize
  @unsupported_programming_languages = []
  @programming_languages = []
  @language_map = {}
  load_natural_language('en')
end

Instance Attribute Details

#log=(value) ⇒ Object

Sets the attribute log

Parameters:

  • value

    the value to set the attribute log to.



56
57
58
# File 'lib/cucumber/step_mother.rb', line 56

def log=(value)
  @log = value
end

#optionsObject

Returns the options passed on the command line.



152
153
154
# File 'lib/cucumber/step_mother.rb', line 152

def options
  @options ||= {}
end

#visitor=(value) ⇒ Object (writeonly)

Sets the attribute visitor

Parameters:

  • value

    the value to set the attribute visitor to.



56
57
58
# File 'lib/cucumber/step_mother.rb', line 56

def visitor=(value)
  @visitor = value
end

Class Method Details

.register_transform(pattern, &transformer) ⇒ Object



65
66
67
68
# File 'lib/cucumber/step_mother.rb', line 65

def self.register_transform(pattern, &transformer)
  raise Cucumber::ArityMismatchError.new('Transform must be registered with at least a one-argument block') if !block_given? || transformer.arity < 1
  @@transforms.unshift StepArgumentTransform.new(Regexp.new(pattern), transformer.to_proc)
end

.transform_arguments(step_args) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/cucumber/step_mother.rb', line 70

def self.transform_arguments(step_args)
  matched = nil
  step_args.map do |step_arg|
    if transform = @@transforms.detect {|t| matched = t.pattern.match(step_arg) if step_arg.is_a?(String) }          
      if matched.captures.empty?
        unless transform.transformer.arity == 1
          raise Cucumber::ArityMismatchError.new("Transforms without Regexp captures only accept a single argument (the step argument)")
        end
        transform.transformer.call(step_arg)
      else
        if transform.transformer.arity != matched.captures.size
          raise Cucumber::ArityMismatchError.new("Number of arguments in Transform (#{transform.transformer.arity}) does not match number of Regexp captures (#{matched.captures.size})")
        end
        transform.transformer.call(*matched.captures)
      end
    else
      step_arg
    end
  end
end

Instance Method Details

#after(scenario) ⇒ Object

:nodoc:



247
248
249
250
251
252
253
# File 'lib/cucumber/step_mother.rb', line 247

def after(scenario) #:nodoc:
  @current_scenario = nil
  return if options[:dry_run]
  @programming_languages.each do |programming_language|
    programming_language.after(scenario)
  end
end

#after_configuration(configuration) ⇒ Object

:nodoc



262
263
264
265
266
# File 'lib/cucumber/step_mother.rb', line 262

def after_configuration(configuration) #:nodoc
  @programming_languages.each do |programming_language|
    programming_language.after_configuration(configuration)
  end
end

#after_stepObject

:nodoc:



255
256
257
258
259
260
# File 'lib/cucumber/step_mother.rb', line 255

def after_step #:nodoc:
  return if options[:dry_run]
  @programming_languages.each do |programming_language|
    programming_language.execute_after_step(@current_scenario)
  end
end

#announce(msg) ⇒ Object

:nodoc:



169
170
171
# File 'lib/cucumber/step_mother.rb', line 169

def announce(msg) #:nodoc:
  @visitor.announce(msg)
end

#before(scenario) ⇒ Object

:nodoc:



239
240
241
242
243
244
245
# File 'lib/cucumber/step_mother.rb', line 239

def before(scenario) #:nodoc:
  return if options[:dry_run] || @current_scenario
  @current_scenario = scenario
  @programming_languages.each do |programming_language|
    programming_language.before(scenario)
  end
end

#before_and_after(scenario, skip_hooks = false) {|scenario| ... } ⇒ Object

:nodoc:

Yields:

  • (scenario)


223
224
225
226
227
228
# File 'lib/cucumber/step_mother.rb', line 223

def before_and_after(scenario, skip_hooks=false) #:nodoc:
  before(scenario) unless skip_hooks
  yield scenario
  after(scenario) unless skip_hooks
  scenario_visited(scenario)
end

#best_matches(step_name, step_matches) ⇒ Object

:nodoc:



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/cucumber/step_mother.rb', line 190

def best_matches(step_name, step_matches) #:nodoc:
  no_groups      = step_matches.select {|step_match| step_match.args.length == 0}
  max_arg_length = step_matches.map {|step_match| step_match.args.length }.max
  top_groups     = step_matches.select {|step_match| step_match.args.length == max_arg_length }

  if no_groups.any?
    longest_regexp_length = no_groups.map {|step_match| step_match.text_length }.max
    no_groups.select {|step_match| step_match.text_length == longest_regexp_length }
  elsif top_groups.any?
    shortest_capture_length = top_groups.map {|step_match| step_match.args.inject(0) {|sum, c| sum + c.length } }.min
    top_groups.select {|step_match| step_match.args.inject(0) {|sum, c| sum + c.length } == shortest_capture_length }
  else
    top_groups
  end
end

#clear!Object

:nodoc:



206
207
208
209
210
211
# File 'lib/cucumber/step_mother.rb', line 206

def clear! #:nodoc:
  step_definitions.clear
  hooks.clear
  steps.clear
  scenarios.clear
end

#load_code_file(step_def_file) ⇒ Object



115
116
117
118
119
120
121
122
123
# File 'lib/cucumber/step_mother.rb', line 115

def load_code_file(step_def_file)
  if programming_language = programming_language_for(step_def_file)
    log.debug("  * #{step_def_file}\n")
    step_definitions = programming_language.step_definitions_for(step_def_file)
    register_step_definitions(step_definitions)
  else
    log.debug("  * #{step_def_file} [NOT SUPPORTED]\n")
  end
end

#load_code_files(step_def_files) ⇒ Object



107
108
109
110
111
112
113
# File 'lib/cucumber/step_mother.rb', line 107

def load_code_files(step_def_files)
  log.debug("Code:\n")
  step_def_files.each do |step_def_file|
    load_code_file(step_def_file)
  end
  log.debug("\n")
end

#load_natural_language(lang) ⇒ Object

Loads a natural language. This has the effect of aliasing Step Definition keywords for all of the registered programming languages (if they support aliasing). See #load_programming_language



147
148
149
# File 'lib/cucumber/step_mother.rb', line 147

def load_natural_language(lang)
  Parser::NaturalLanguage.get(self, lang)
end

#load_plain_text_features(feature_files) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/cucumber/step_mother.rb', line 91

def load_plain_text_features(feature_files)
  features = Ast::Features.new

  log.debug("Features:\n")
  feature_files.each do |f|
    feature_file = FeatureFile.new(f)
    feature = feature_file.parse(self, options)
    if feature
      features.add_feature(feature)
      log.debug("  * #{f}\n")
    end
  end
  log.debug("\n")
  features
end

#load_programming_language(ext) ⇒ Object

Loads and registers programming language implementation. Instances are cached, so calling with the same argument twice will return the same instance.



133
134
135
136
137
138
139
140
141
# File 'lib/cucumber/step_mother.rb', line 133

def load_programming_language(ext)
  return @language_map[ext] if @language_map[ext]
  programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
  programming_language = programming_language_class.new(self)
  programming_language.alias_adverbs(@adverbs || [])
  @programming_languages << programming_language
  @language_map[ext] = programming_language
  programming_language
end

#register_adverbs(adverbs) ⇒ Object

:nodoc:



230
231
232
233
234
235
236
237
# File 'lib/cucumber/step_mother.rb', line 230

def register_adverbs(adverbs) #:nodoc:
  @adverbs ||= []
  @adverbs += adverbs
  @adverbs.uniq!
  @programming_languages.each do |programming_language|
    programming_language.alias_adverbs(@adverbs)
  end
end

#register_step_definitions(step_definitions) ⇒ Object



125
126
127
# File 'lib/cucumber/step_mother.rb', line 125

def register_step_definitions(step_definitions)
  step_definitions.each{|step_definition| register_step_definition(step_definition)}
end

#scenarios(status = nil) ⇒ Object

:nodoc:



173
174
175
176
177
178
179
180
# File 'lib/cucumber/step_mother.rb', line 173

def scenarios(status = nil) #:nodoc:
  @scenarios ||= []
  if(status)
    @scenarios.select{|scenario| scenario.status == status}
  else
    @scenarios
  end
end

#snippet_text(step_keyword, step_name, multiline_arg_class) ⇒ Object

:nodoc:



217
218
219
220
221
# File 'lib/cucumber/step_mother.rb', line 217

def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
  @programming_languages.map do |programming_language|
    programming_language.snippet_text(step_keyword, step_name, multiline_arg_class)
  end.join("\n")
end

#step_definitionsObject

:nodoc:



213
214
215
# File 'lib/cucumber/step_mother.rb', line 213

def step_definitions #:nodoc:
  @step_definitions ||= []
end

#step_match(step_name, formatted_step_name = nil) ⇒ Object

:nodoc:

Raises:



182
183
184
185
186
187
188
# File 'lib/cucumber/step_mother.rb', line 182

def step_match(step_name, formatted_step_name=nil) #:nodoc:
  matches = step_definitions.map { |d| d.step_match(step_name, formatted_step_name) }.compact
  raise Undefined.new(step_name) if matches.empty?
  matches = best_matches(step_name, matches) if matches.size > 1 && options[:guess]
  raise Ambiguous.new(step_name, matches, options[:guess]) if matches.size > 1
  matches[0]
end

#step_visited(step) ⇒ Object

:nodoc:



156
157
158
# File 'lib/cucumber/step_mother.rb', line 156

def step_visited(step) #:nodoc:
  steps << step unless steps.index(step)
end

#steps(status = nil) ⇒ Object

:nodoc:



160
161
162
163
164
165
166
167
# File 'lib/cucumber/step_mother.rb', line 160

def steps(status = nil) #:nodoc:
  @steps ||= []
  if(status)
    @steps.select{|step| step.status == status}
  else
    @steps
  end
end