Class: Cucumber::StepMother
- Includes:
- Constantize, Formatter::Duration
- Defined in:
- lib/cucumber/step_mother.rb
Overview
This is the meaty part of Cucumber that ties everything together.
Instance Attribute Summary collapse
-
#log ⇒ Object
writeonly
Sets the attribute log.
-
#options ⇒ Object
Returns the options passed on the command line.
-
#visitor ⇒ Object
writeonly
Sets the attribute visitor.
Instance Method Summary collapse
-
#after(scenario) ⇒ Object
:nodoc:.
-
#after_configuration(configuration) ⇒ Object
:nodoc.
-
#after_step ⇒ Object
:nodoc:.
-
#announce(msg) ⇒ Object
Output
announcement
alongside the formatted output. -
#before(scenario) ⇒ Object
:nodoc:.
-
#before_and_after(scenario, skip_hooks = false) {|scenario| ... } ⇒ Object
:nodoc:.
-
#best_matches(step_name, step_matches) ⇒ Object
:nodoc:.
-
#embed(file, mime_type) ⇒ Object
Embed
file
of MIME typemime_type
into the output. -
#initialize ⇒ StepMother
constructor
A new instance of StepMother.
- #invoke(step_name, multiline_argument = nil) ⇒ Object
-
#invoke_steps(steps_text, natural_language) ⇒ Object
Invokes a series of steps
steps_text
. - #load_code_file(step_def_file) ⇒ Object
- #load_code_files(step_def_files) ⇒ Object
-
#load_natural_language(lang) ⇒ Object
Loads a natural language.
- #load_plain_text_features(feature_files) ⇒ Object
-
#load_programming_language(ext) ⇒ Object
Loads and registers programming language implementation.
-
#py_string(string_with_triple_quotes, file = nil, line_offset = 0) ⇒ Object
Returns a regular String for
string_with_triple_quotes
. -
#register_adverbs(adverbs) ⇒ Object
:nodoc:.
-
#scenarios(status = nil) ⇒ Object
:nodoc:.
-
#snippet_text(step_keyword, step_name, multiline_arg_class) ⇒ Object
:nodoc:.
-
#step_match(step_name, name_to_report = nil) ⇒ Object
:nodoc:.
-
#step_visited(step) ⇒ Object
:nodoc:.
-
#steps(status = nil) ⇒ Object
:nodoc:.
-
#table(text_or_table, file = nil, line_offset = 0) ⇒ Object
Returns a Cucumber::Ast::Table for
text_or_table
, which can either be a String:. - #unknown_programming_language? ⇒ Boolean
- #unmatched_step_definitions ⇒ Object
Methods included from Formatter::Duration
Methods included from Constantize
Constructor Details
#initialize ⇒ StepMother
Returns a new instance of StepMother.
47 48 49 50 51 52 53 |
# File 'lib/cucumber/step_mother.rb', line 47 def initialize @unsupported_programming_languages = [] @programming_languages = [] @language_map = {} load_natural_language('en') @current_scenario = nil end |
Instance Attribute Details
#log=(value) ⇒ Object
Sets the attribute log
45 46 47 |
# File 'lib/cucumber/step_mother.rb', line 45 def log=(value) @log = value end |
#options ⇒ Object
Returns the options passed on the command line.
113 114 115 |
# File 'lib/cucumber/step_mother.rb', line 113 def @options ||= {} end |
#visitor=(value) ⇒ Object (writeonly)
Sets the attribute visitor
45 46 47 |
# File 'lib/cucumber/step_mother.rb', line 45 def visitor=(value) @visitor = value end |
Instance Method Details
#after(scenario) ⇒ Object
:nodoc:
300 301 302 303 304 305 306 |
# File 'lib/cucumber/step_mother.rb', line 300 def after(scenario) #:nodoc: @current_scenario = nil return if [:dry_run] @programming_languages.each do |programming_language| programming_language.after(scenario) end end |
#after_configuration(configuration) ⇒ Object
:nodoc
315 316 317 318 319 |
# File 'lib/cucumber/step_mother.rb', line 315 def after_configuration(configuration) #:nodoc @programming_languages.each do |programming_language| programming_language.after_configuration(configuration) end end |
#after_step ⇒ Object
:nodoc:
308 309 310 311 312 313 |
# File 'lib/cucumber/step_mother.rb', line 308 def after_step #:nodoc: return if [:dry_run] @programming_languages.each do |programming_language| programming_language.execute_after_step(@current_scenario) end end |
#announce(msg) ⇒ Object
Output announcement
alongside the formatted output. This is an alternative to using Kernel#puts - it will display nicer, and in all outputs (in case you use several formatters)
Beware that the output will be printed before the corresponding step. This is because the step itself will not be printed until after it has run, so it can be coloured according to its status.
138 139 140 |
# File 'lib/cucumber/step_mother.rb', line 138 def announce(msg) @visitor.announce(msg) end |
#before(scenario) ⇒ Object
:nodoc:
292 293 294 295 296 297 298 |
# File 'lib/cucumber/step_mother.rb', line 292 def before(scenario) #:nodoc: return if [: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:
276 277 278 279 280 281 |
# File 'lib/cucumber/step_mother.rb', line 276 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:
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/cucumber/step_mother.rb', line 243 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 |
#embed(file, mime_type) ⇒ Object
Embed file
of MIME type mime_type
into the output. This may or may not be ignored, depending on what kind of formatter(s) are active.
145 146 147 |
# File 'lib/cucumber/step_mother.rb', line 145 def (file, mime_type) @visitor.(file, mime_type) end |
#invoke(step_name, multiline_argument = nil) ⇒ Object
158 159 160 161 162 163 164 165 |
# File 'lib/cucumber/step_mother.rb', line 158 def invoke(step_name, multiline_argument=nil) begin step_match(step_name).invoke(multiline_argument) rescue Exception => e e.nested! if Undefined === e raise e end end |
#invoke_steps(steps_text, natural_language) ⇒ Object
Invokes a series of steps steps_text
. Example:
invoke(%Q{
Given I have 8 cukes in my belly
Then I should not be thirsty
})
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/cucumber/step_mother.rb', line 173 def invoke_steps(steps_text, natural_language) ored_keywords = natural_language.step_keywords.map{|kw| Regexp.escape(kw)}.join("|") # TODO Gherkin: # This a bit hacky and fragile. When we move to Gherkin we should replace this entire method body # with a call to the parser - parsing the body of a scenario. We may need to put the parser/policy in the # appropriate state (the same state it's in after parsing a Scenario: line). steps_text.strip.split(/(?=^\s*(?:#{ored_keywords}))/).map { |step| step.strip }.each do |step| output = step.match(/^\s*(#{ored_keywords})([^\n]+)(\n.*)?$/m) action, step_name, table_or_string = output[1], output[2], output[3] if table_or_string.to_s.strip =~ /^\|/ table_or_string = table(table_or_string) elsif table_or_string.to_s.strip =~ /^"""/ table_or_string = py_string(table_or_string.gsub(/^\n/, "")) end args = [step_name, table_or_string].compact invoke(*args) end end |
#load_code_file(step_def_file) ⇒ Object
81 82 83 84 85 86 87 88 |
# File 'lib/cucumber/step_mother.rb', line 81 def load_code_file(step_def_file) if programming_language = programming_language_for(step_def_file) log.debug(" * #{step_def_file}\n") programming_language.load_code_file(step_def_file) else log.debug(" * #{step_def_file} [NOT SUPPORTED]\n") end end |
#load_code_files(step_def_files) ⇒ Object
73 74 75 76 77 78 79 |
# File 'lib/cucumber/step_mother.rb', line 73 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
108 109 110 |
# File 'lib/cucumber/step_mother.rb', line 108 def load_natural_language(lang) Parser::NaturalLanguage.get(self, lang) end |
#load_plain_text_features(feature_files) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/cucumber/step_mother.rb', line 55 def load_plain_text_features(feature_files) features = Ast::Features.new start = Time.new log.debug("Features:\n") feature_files.each do |f| feature_file = FeatureFile.new(f) feature = feature_file.parse(self, ) if feature features.add_feature(feature) log.debug(" * #{f}\n") end end duration = Time.now - start log.debug("Parsing feature files took #{format_duration(duration)}\n\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.
94 95 96 97 98 99 100 101 102 |
# File 'lib/cucumber/step_mother.rb', line 94 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 |
#py_string(string_with_triple_quotes, file = nil, line_offset = 0) ⇒ Object
Returns a regular String for string_with_triple_quotes
. Example:
"""
hello
world
"""
Is retured as: “ hellonworld”
228 229 230 231 |
# File 'lib/cucumber/step_mother.rb', line 228 def py_string(string_with_triple_quotes, file=nil, line_offset=0) @py_string_parser ||= Parser::PyStringParser.new @py_string_parser.parse_or_fail(string_with_triple_quotes, file, line_offset).to_s end |
#register_adverbs(adverbs) ⇒ Object
:nodoc:
283 284 285 286 287 288 289 290 |
# File 'lib/cucumber/step_mother.rb', line 283 def register_adverbs(adverbs) #:nodoc: @adverbs ||= [] @adverbs += adverbs @adverbs.uniq! @programming_languages.each do |programming_language| programming_language.alias_adverbs(@adverbs) end end |
#scenarios(status = nil) ⇒ Object
:nodoc:
149 150 151 152 153 154 155 156 |
# File 'lib/cucumber/step_mother.rb', line 149 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:
265 266 267 268 269 270 |
# File 'lib/cucumber/step_mother.rb', line 265 def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc: load_programming_language('rb') if unknown_programming_language? @programming_languages.map do |programming_language| programming_language.snippet_text(step_keyword, step_name, multiline_arg_class) end.join("\n") end |
#step_match(step_name, name_to_report = nil) ⇒ Object
:nodoc:
233 234 235 236 237 238 239 240 241 |
# File 'lib/cucumber/step_mother.rb', line 233 def step_match(step_name, name_to_report=nil) #:nodoc: matches = @programming_languages.map do |programming_language| programming_language.step_matches(step_name, name_to_report) end.flatten raise Undefined.new(step_name) if matches.empty? matches = best_matches(step_name, matches) if matches.size > 1 && [:guess] raise Ambiguous.new(step_name, matches, [:guess]) if matches.size > 1 matches[0] end |
#step_visited(step) ⇒ Object
:nodoc:
117 118 119 |
# File 'lib/cucumber/step_mother.rb', line 117 def step_visited(step) #:nodoc: steps << step unless steps.index(step) end |
#steps(status = nil) ⇒ Object
:nodoc:
121 122 123 124 125 126 127 128 |
# File 'lib/cucumber/step_mother.rb', line 121 def steps(status = nil) #:nodoc: @steps ||= [] if(status) @steps.select{|step| step.status == status} else @steps end end |
#table(text_or_table, file = nil, line_offset = 0) ⇒ Object
Returns a Cucumber::Ast::Table for text_or_table
, which can either be a String:
table(%{
| account | description | amount |
| INT-100 | Taxi | 114 |
| CUC-101 | Peeler | 22 |
})
or a 2D Array:
table([
%w{ account description amount },
%w{ INT-100 Taxi 114 },
%w{ CUC-101 Peeler 22 }
])
210 211 212 213 214 215 216 217 |
# File 'lib/cucumber/step_mother.rb', line 210 def table(text_or_table, file=nil, line_offset=0) if Array === text_or_table Ast::Table.new(text_or_table) else @table_parser ||= Parser::TableParser.new @table_parser.parse_or_fail(text_or_table.strip, file, line_offset) end end |
#unknown_programming_language? ⇒ Boolean
272 273 274 |
# File 'lib/cucumber/step_mother.rb', line 272 def unknown_programming_language? @programming_languages.empty? end |
#unmatched_step_definitions ⇒ Object
259 260 261 262 263 |
# File 'lib/cucumber/step_mother.rb', line 259 def unmatched_step_definitions @programming_languages.map do |programming_language| programming_language.unmatched_step_definitions end.flatten end |