Closed sjieg closed 9 years ago
Did some testing and the only way to have the LL functionality available is via
LapisLazuli::WorldModule::Config.config_file = "config/config.yml"
World(LapisLazuli)
include LapisLazuli
World is just an Object used to run scenarios, however the env.rb (or any support code) is not a scenario and has no access to the methods provided by World.
So the support code should also include the same modules as World to be able to use them.
See for more information about world: https://github.com/cucumber/cucumber/wiki/A-Whole-New-World
Any comment on why? Do you want to improve the codebase by allowing:
LapisLazuli::WorldModule::Config.env("locale")
or does my suggestion have unwanted side effects?
Eh, I didn't mean to re-open the issue.
The main thing I wanted to add is that such a global 'include LapisLazuli' is not considered good practice, as Onno's link goes on to say.
It's mostly due to how Ruby handles this kind of include; what really happens is that Object - that is, the class that every object ultimately derives from - is extended with the functions from the module.
This is best illustrated with this example:
class X
def foo
puts "X::foo"
end
end
x = X.new
x.foo # as expected, prints "X::foo"
module Y
def foo
puts "Y::foo"
end
end
class Z
end
z = Z.new
z.foo # as expected, yields NoMethodError
include Y
z.foo # wait, what? prints Y::foo"
The point is that include
at global scope is not really a good idea, as it can have side-effects.
So how to get out of this cleanly?
Well, most support code has the following properties:
In most cases, the simple thing to do is to place it in a cucumber hook, probably the before scenario hook.
If you need it to be run once and only once, that page has an example on how to do it using global variables. But a more complete example for more complex test suites might involve singleton functions:
# env.rb
module MyFunctions
@@loaded = nil
def load_conditional_stuff
if not @@loaded.nil?
return
end
@@loaded = true
if env == 'locale'
load './www/local-page.rb'
end
end
end
LapisLazuli::WorldModule::Config.config_file = "config/config.yml"
World(LapisLazuli, MyFunctions) # Make MyFunctions part of the World object
Before do
load_conditional_stuff
end
It's more complex, but avoids namespace pollution.
Sorry Onno, wires crossed. I hope my comment explains.
Yes include does pollute the global scope, which can have bad side effects.
I like the solution you are proposing and I hope this can be integrated into LL
LapisLazuli::WorldModule::Config.config_file = "config/config.yml"
World(LapisLazuli, MyFunctions) # Make MyFunctions part of the World object
LapisLazuli.Before do
# all LL functions are available here
if current_env == "local"
p "Local testing"
end
end
Added https://github.com/spriteCloud/lapis-lazuli/wiki/Setup-Code to turn this into a more general guideline.
When I was writing the Setup Code page, I figured we can actually provide a mechanism for running code once.
Cucumber's AfterConfiguration
hook doesn't work so well, as it unfortunately doesn't have the World object set up.
Alright. Let's do something like you propose. In the meantime, the Setup Code wiki page is still the definite guideline.
Updated the setup code page, and the page about the Hooks module (where it's implemented).
After
In the env.rb file, I want to be able to check the
env
variable to make certain exceptions. E.G.