Reputation: 11
currently I am loading all YAML files inside Cucumber Hooks like this before- the intention is to ensure we dont code individually for loading YAML files.
@all_Yaml_Files = Dir.entries(@projectData_Path).select {|f| !File.directory? f};
@all_Yaml_Files.each do |file_Name|
file_Full_Path = @projectData_Path + '/' + file_Name
instance_variable_set("@" + file_Name.split('.')[0], YAML.load_file(file_Full_Path))
end
However this code is inside a Before Cucumber Hook. So When the instance variables are loaded they are not available for next scenario. How can I make them run only once and then be available for all scenarios and all features - ie globally. Currently its loading everytime for a scenario.
Before do
....
end
Note: By doing above , we can directly access a YAML_FileName by @YAML_FileName variable without writing code. Thats my intention. Same happens with all excel files, json files etc etc. They are all called from inside Hooks.
Upvotes: 1
Views: 3477
Reputation: 8345
EDIT: added the "quick" solution
You are using class variables (@var
) now; these are subject to some Cucumber magic so they are cleaned out after each scenario, as you noticed. This makes them rather useful as well, giving you a "clean slate" while allowing you to transfer some state from one step to the next.
This is all just Ruby, so you can of course use global ruby variables ($var
) instead. This still requires you to change your existing code.
If you want to keep your class variables @var
and still have them to stick around, you could do hooks to save and restore them in globals, i.e.:
Around do |scenario, block|
@var = $var
begin
block.call
ensure
$var = @var
end
end
You'll want to make sure this hook is encountered early enough so it fires before any other hooks you might have.
I don't like to use globals in any language, so I try not to use either @var
or $var
in Cucumber. Instead, I prefer to do it the OOP way... hence:
I use a singleton module for such things:
# support/000_cucu_globals.rb
class CucuGlobals
include Singleton
def initialize
@somevalue = 'hello world'
...
end
attr_reader :somevalue
end
Elsewhere:
puts CucuGlobals.instance.somevalue + "!"
Adjust/extend/get creative, as necessary. If you want to avoid typing so much, feel free to use a shorter class name (like G
for global). You can also make your accessors class methods instead to even skip the instance
in between. This is all just Ruby (not Cucumber) at this point, so there is not Cucumber magic involved anymore.
Hint: you want to load this module pretty early. I'm sure there is a good way to do that "cleanly", but I opted to just name it in such a way that is found first, by Cucumber (000_...
).
Upvotes: 1