spriteCloud / lapis-lazuli

Cucumber helper functions and scaffolding for easier test automation suite development.
Other
7 stars 7 forks source link

Unable to used LL methods outside step definitions #13

Closed sjieg closed 9 years ago

sjieg commented 9 years ago

After

LapisLazuli::WorldModule::Config.config_file = "config/config.yml"
World(LapisLazuli)

In the env.rb file, I want to be able to check the env variable to make certain exceptions. E.G.

if env == 'locale'
    load './www/local-page.rb'
end
osteenbergen commented 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

osteenbergen commented 9 years ago

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?

jfinkhaeuser commented 9 years ago

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.

jfinkhaeuser commented 9 years ago

Sorry Onno, wires crossed. I hope my comment explains.

osteenbergen commented 9 years ago

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
jfinkhaeuser commented 9 years ago

Added https://github.com/spriteCloud/lapis-lazuli/wiki/Setup-Code to turn this into a more general guideline.

jfinkhaeuser commented 9 years ago

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.

jfinkhaeuser commented 9 years ago

Alright. Let's do something like you propose. In the meantime, the Setup Code wiki page is still the definite guideline.

jfinkhaeuser commented 9 years ago

Updated the setup code page, and the page about the Hooks module (where it's implemented).