Composition or inheritance for delegating page methods?

The thing I like to do when creating a page object pattern for automated web testing is delegating any methods that don’t belong to the Page object itself.

For example, a very simple page object model like this GoogleHomePage doesn’t delegate any methods to the Browser object.

require "rubygems"
require "watir-webdriver"

class GoogleHomePage
  def initialize(browser)
    @browser = browser
  end
  def visit
    @browser.goto "www.google.com"
  end
end

b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

So, the p.title and p.close statements both fail with an error: undefined method `goto' for # (NoMethodError).

One approach would be simply to write appropriate methods for what you would do on the Browser object. For example:

require "rubygems"
require "watir-webdriver"

class GoogleHomePage
  def initialize(browser)
    @browser = browser
  end
  def visit
    @browser.goto "www.google.com"
  end
  def title
    @browser.title
  end
  def close
    @browser.close
  end
end

b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

But this isn’t DRY. It means every method of Browser you access to needs to be rewritten. But I often see this happen.

What we should be doing is simply delegating any methods that don’t exist on the Page object to the Browser object which is passed in at initialization. There are two ways I know of to do this: inheritance delegation and composition.

Inheritance Delegation

Inheritance delegation means changing our class so it delegates appropriately using a DelegateClass. This means anything of class Browser is delegated.

For example:

require "rubygems"
require "watir-webdriver"

class GoogleHomePage < DelegateClass(Watir::Browser) 
  def initialize(browser)
    super(browser)
  end
  def visit
    self.goto "www.google.com"
  end
end

b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

From this point forward you don’t need to refer to @browser, instead you just refer to self in your class.

Composition

Composition is about composing the class of different elements, some of which are passed to the browser. This essentially involves creating a method_missing method and passing these methods to the instance variable @browser.

require "rubygems"
require "watir-webdriver"

class GoogleHomePage
  def initialize(browser)
    @browser = browser
  end
  def method_missing(sym, *args, &block)
    @browser.send sym, *args, &block
  end
  def visit
    @browser.goto "www.google.com"
  end
end

b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

This means that any reference to the Browser object still needs to refer to @browser throughout the class.

Inheritance or Composition?

You can see from the examples above, both approaches are very similar, but from researching these, it seems that most people prefer composition to inheritance in ruby, mainly due to maintainability of class chains. In our example, the inheritance chain is small and very simple, so I don’t think this poses a great maintainability issue.

What do you think? What would you prefer?

Author: Alister Scott

Alister is an Excellence Wrangler for Automattic.

15 thoughts on “Composition or inheritance for delegating page methods?”

  1. I don’t really understand this example (perhaps because it’s fairly minimal). Why does your GoogleHomePage object need a browser’s goto method? It doesn’t seem to belong there…

    Like

    1. Yes, my bad, .goto is a poor example.
      I have updated my example so the page has a .visit, and I then use .title, and .close, as these are things you may often want to use from the Browser Object.
      Thanks.

      Like

  2. Well, the general rule is to prefer/favour composition over inheritance as it has a number of advantages, particularly from a testability point of view (I can easily supply a mock or any other alternate implementation rather than the one fixed superclass). It also tends to be less brittle. That being said, for the purpose you describe there seems to be little concrete advantage.

    In your case however, I’d ask myself if it actually makes sense at all asking a GoogleHomePage to goto a link. Isn’t it (the home page) already there? Doesn’t it take a browser and the url and then is already there? Does it make sense that you can ask GoogleHomePage to goto “www.bing.com”? What is the most natural way you’d like the calling code to read?

    The reduction in the caller code of not having to refer to the browser directly doesn’t necessarily make it worthwhile unless you also add semantic value to the calling code. Readability is an important aspect.

    Like

    1. although, a lot of my points about inheritance don’t apply with the Ruby DelegateClass style inheritance. I am not a Ruby expert…

      Like

    2. Thanks for your comment Jed.
      Yes, .goto doesn’t belong so I’ve updated my (poor) example.
      The .title and .close methods are more appropriate to delegate.

      Like

      1. K, but you now have the case where you are only using a limited subset of the encapsulated object’s functionality, furthering the case for composition (and probably explicit composition at that).

        Like

        1. Thanks, I will further investigate explicit composition.
          This is why blogs are so great, you get all sorts of useful feedback.

          Like

  3. Alister –

    I have two frameworks (equivalent to your Page Object Pattern) that I use at work. One uses inheritance (I inherited this one), one uses composition. They are both basically the same and neither of them really got in my way until I needed to write some error handling code to switch out a mis-behaving IE instance for a new one. With inheritance, you have to get a new instance of your framework, with composition, you can make a method to renew the underlying Watir instance and keep going. I’m sure somebody will quibble with me saying that I shouldn’t do that, but it really makes dealing with misbehaving IE browsers easy.

    Like

  4. Hi,

    Sorry I’m a tester and not a developer so the finer concepts of objects and inheritance/composition are a bit lost on me. I get what you stated above though.

    So if I use composition how would I deal with something like a click? How do I compose

    p.button(:value => ‘Search’).click

    ? I tried lots of different ways but must have reached my knowledge limit of ruby/object orientation. Nothing worked (and there is nobody around that knows how either). Maybe you can give me a leg-up.

    Cheers
    Oliver

    Like

Comments are closed.