Class: EolScenario
- Inherits:
-
Object
- Object
- EolScenario
- Includes:
- IndifferentVariableHash
- Defined in:
- lib/eol_scenarios/eol_scenario.rb,
lib/eol_scenarios/spec.rb
Overview
a Scenario is some set of data/logic that can be loaded up easily to run an application against.
if you need to enter abunchof data manually into the a website to test something you’re working on, this is a good candidate for a scenario.
we can also use scenarios for loading up the base foundation of data that’s required to load the web application
TODO define what is public/private and document public API in README and
actually give private methods a private visibility
Defined Under Namespace
Modules: Spec
Class Attribute Summary collapse
-
.before_blocks ⇒ Object
an array of the paths where scenarios can be found.
-
.load_paths ⇒ Object
an array of the paths where scenarios can be found.
-
.verbose ⇒ Object
an array of the paths where scenarios can be found.
Instance Attribute Summary collapse
-
#file_path ⇒ Object
Returns the value of attribute file_path.
Class Method Summary collapse
-
.[](*names) ⇒ Object
returns a scenario by name, eg.
-
.all ⇒ Object
returns all Scenarios found using Scenario#load_paths.
-
.before(&block) ⇒ Object
run some block of code before any scenarios run.
-
.load(*scenarios) ⇒ Object
loads a Scenario, evaluating its code.
Instance Method Summary collapse
- #description ⇒ Object
- #description_without_summary ⇒ Object
- #first_line ⇒ Object
-
#header ⇒ Object
Comment header, any comments at the top of the source code.
-
#info ⇒ Object
returns a formatted string, showing information about this current scenario.
-
#initialize(file_path) ⇒ EolScenario
constructor
A new instance of EolScenario.
-
#load ⇒ Object
evaluates the code of the scenario.
- #name ⇒ Object (also: #to_s)
- #source_code ⇒ Object
-
#summary ⇒ Object
if the first line of the scenario’s source code is a comment, we use it as the scenario’s summary.
Constructor Details
#initialize(file_path) ⇒ EolScenario
Returns a new instance of EolScenario.
19 20 21 22 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 19 def initialize file_path @file_path = file_path source_code # does some parsing ... eager load this! otherwise Scenario[:first].some_var won't work end |
Class Attribute Details
.before_blocks ⇒ Object
an array of the paths where scenarios can be found
any .rb file found in these directories is assumed to be a scenario
103 104 105 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 103 def before_blocks @before_blocks end |
.load_paths ⇒ Object
an array of the paths where scenarios can be found
any .rb file found in these directories is assumed to be a scenario
103 104 105 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 103 def load_paths @load_paths end |
.verbose ⇒ Object
an array of the paths where scenarios can be found
any .rb file found in these directories is assumed to be a scenario
103 104 105 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 103 def verbose @verbose end |
Instance Attribute Details
#file_path ⇒ Object
Returns the value of attribute file_path.
17 18 19 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 17 def file_path @file_path end |
Class Method Details
.[](*names) ⇒ Object
returns a scenario by name, eg. Scenario
if 1 name is passed in, we’ll return that scenario or nil
if more than 1 name is passed in, we’ll return an array of scenarios (or an empty array)
140 141 142 143 144 145 146 147 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 140 def [] *names # puts "Scenario#{ names.inspect }" if Scenario.verbose if names.length == 1 all.find {|scenario| scenario.name.downcase == names.first.to_s.downcase } else names.map {|name| self[ name ] }.compact end end |
.all ⇒ Object
returns all Scenarios found using Scenario#load_paths
106 107 108 109 110 111 112 113 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 106 def all load_paths.inject([]) do |all_scenarios, load_path| Dir[ File.join(load_path, '**', '*.rb') ].each do |found_scenario_file| all_scenarios << EolScenario.new(found_scenario_file) end all_scenarios end end |
.before(&block) ⇒ Object
run some block of code before any scenarios run
good for last-minute require statements and whatnot
128 129 130 131 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 128 def before &block @before_blocks ||= [] @before_blocks << block if block end |
.load(*scenarios) ⇒ Object
loads a Scenario, evaluating its code
we do this here so we can easily eval in a certain context, if we want to add a context later
Scenario.load @scenario1, @scenario2
Scenario.load :names, 'work', :too
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 157 def load *scenarios puts "EolScenario.load(#{ scenarios.map {|s| s.to_s }.join(', ') })" if EolScenario.verbose @before_blocks.each { |b| b.call } if @before_blocks and not @before_blocks.empty? # TODO should be able to define some block that scenarios get evaluated in! # or some things that scenarios might want to require or ... = ( scenarios.last.is_a?(Hash) ) ? scenarios.pop : { } [:unique] ||= true # whether each scenario passed has to be unique ... will likely change this to be true by default [:whiny] = true if [:whiny].nil? # make sure everything is actually a Scenario object # # after this, we can safely assume that everything is a scenario! # scenarios.map! do |scenario| scenario.is_a?(EolScenario) ? scenario : self[scenario] end scenarios.compact! scenarios = scenarios.inject([]) do |all, scenario| all += EolScenario[ nil, *scenario.dependencies ] if scenario.dependencies all << scenario all end scenarios.compact! puts "[ after dependencies, scenarios => #{ scenarios.map {|s| s.to_s }.join(', ') } ]" if EolScenario.verbose scenarios = scenarios.inject([]) do |all, scenario| existing_scenario = all.find {|s| s.name == scenario.name } if existing_scenario # the last scenario with the given name "wins" (but we need to persist order) index_of_existing_scenario = all.index existing_scenario all.delete_at index_of_existing_scenario all.insert index_of_existing_scenario, scenario else all << scenario end all end if [:unique] puts "scenarios to load: #{ scenarios.map {|s| s.to_s }.join(', ') }" if EolScenario.verbose scenarios.each do |scenario| scenario = self[scenario] unless scenario.is_a?EolScenario # try getting using self[] if not a scenario puts "... loading #{ scenario.name } (#{ scenario.summary })" if EolScenario.verbose begin if scenario.is_a? EolScenario puts "loading scenario: #{ scenario.file_path }" if EolScenario.verbose # TODO update to eval ... should load in a custom context ... # the eval should also catch exceptions and print the # line number that threw the exception, etc etc Kernel::load scenario.file_path else puts "Unsure how to load scenario: #{ scenario.inspect }" if [:whiny] end rescue => ex puts "An Exception was thrown by scenario: #{ scenario.name }" if [:whiny] raise ex end end end |
Instance Method Details
#description ⇒ Object
76 77 78 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 76 def description header.gsub(/^#* ?/, '').gsub(/^---.*/m, '').strip # gets rid of comment hashes and yaml end |
#description_without_summary ⇒ Object
80 81 82 83 84 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 80 def description_without_summary parts = description.split("\n") parts.shift parts.join("\n") end |
#first_line ⇒ Object
56 57 58 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 56 def first_line header.split("\n").first #.gsub(/^#* ?/, '') end |
#header ⇒ Object
Comment header, any comments at the top of the source code
92 93 94 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 92 def header source_code.gsub /\n^[^#].*/m, '' end |
#info ⇒ Object
returns a formatted string, showing information about this current scenario
31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 31 def info str = <<INFO Scenario: #{ name } Summary: #{ summary } Description: #{ description_without_summary } INFO variables.each do |key, value| str << "#{ key }: #{ value.inspect }\n" end str end |
#load ⇒ Object
evaluates the code of the scenario
87 88 89 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 87 def load self.class.load self # pass the loading off to the class end |
#name ⇒ Object Also known as: to_s
24 25 26 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 24 def name File.basename(file_path).sub(/\.rb$/, '') end |
#source_code ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 60 def source_code unless @source_code # the first time we read in the source code, # see if there are any variables in the header # and, if so, set them via IndifferentVariableHash @source_code = File.read file_path yaml_frontmatter = header.gsub(/^#* ?/, '')[/^---.*/m] if yaml_frontmatter require 'yaml' header_variables = YAML::load(yaml_frontmatter) variables.merge!(header_variables) if header_variables end end @source_code end |
#summary ⇒ Object
if the first line of the scenario’s source code is a comment, we use it as the scenario’s summary
ideally, all scenarios should have a short simple summary
48 49 50 51 52 53 54 |
# File 'lib/eol_scenarios/eol_scenario.rb', line 48 def summary if first_line =~ /^#/ first_line.sub(/^#*/, '').strip else '' end end |