Richlewis
Richlewis

Reputation: 15374

Extending Modules in Cucumber

I know that in Cucumber that I can create a module and then include that module into the World object and all the methods that I have created within the newly created module are available globally

module MyModule
  def my_method

 end
end
World(MyModule)

Now anywhere in my cucumber tests I can call my_method and it will work

The issue I see here and an issue I have come across is duplication of method names, as the application gets bigger or other testers/developers work on the application.

So if I was to wrap everything up in its own module and create module methods like so

module MyModule
  def self.my_method
    page.find('#element')
 end
end
World(MyModule)

MyModule.my_method
# This will return undefined variable or method 'page' for MyModule module

So being new to using modules I have read that you can extend other modules so that you can use those methods within another module

So to access the page method I would need to access Capybara::DSL

 module MyModule
 extend Capybara::DSL
  def self.my_method
    page.find('#element')
 end
end
World(MyModule)

MyModule.my_method now works, but my question is rather than extend individual namespaces for every module that I need access to is there a way to extend/include everything or is this a bad practice?

Another example of where things fail are when I try to access instances of a class

module SiteCss
 def login_page
   Login.new
 end
end

class Login < SitePrism::Page
 element :username, "#username"
end

module MyModule
 extend Capybara::DSL
  def self.my_method
    page.find('#element')
   login_page.username.set('username')
 end
end
World(MyModule)

So with this example if I was it try and call login_page.username I would get

undefined method `login_page`

I'm really looking for the correct way to be doing this.

In conclusion I am trying to understand how to use custom modules and classes in cucumber without having to load everything into the World object.

Upvotes: 0

Views: 712

Answers (1)

Pippo
Pippo

Reputation: 925

Yes, it's not pretty to extend a module multiple times, if that's really what you want to do, I can suggest a way you can improve it a bit:

base class which will inherit your page object framework and extend(include is probably the correct option here):

module Pages
  class BasePage < SitePrism::Page
    extend Capybara::DSL
  end
end

Now your login class:

module Pages
  class Login < BasePage
    element :username, "#username"

    def yourmethod
      page.find('#element')
      username.set('username')
    end
  end
end

Now the bits you are probably interested in, expose yourmethod to cucumber world:

module SiteCss
  def page_object
    @page_object ||= Pages::Login.new
  end
end

World(SiteCss)

Now you should have access to yourmethod in a cleaner way...

Usage:

@page_object.yourmethod

Although the most important suggestion I could give you is run from SitePrism... Create your own page object framework... don't fall into SitePrism trap...

Upvotes: 0

Related Questions