引用链接:http://watirmelon.com/2011/01/24/composition-or-inheritance-for-delegating-page-methods/

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.

Composition or inheritance for delegating page methods?的更多相关文章

  1. 组合优于继承 Composition over inheritance

    https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance 解答1 Prefer composition ...

  2. Effective Java 16 Favor composition over inheritance

    Inheritance disadvantage Unlike method invocation, inheritance violates encapsulation. Since you don ...

  3. React之Composition Vs inheritance 组合Vs继承

    React的组合   composition: props有个特殊属性,children,组件可以通过props.children拿到所有包含在内的子元素, 当组件内有子元素时,组件属性上的child ...

  4. Inheritance setUp() and tearDown() methods from Classsetup() and Classteardown

      I have a general test class in my nosetests suit and some sub-classes, inheriting from it. The con ...

  5. selenium page object model

    Page Object Model (POM) & Page Factory in Selenium: Ultimate Guide 来源:http://www.guru99.com/page ...

  6. <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>

    <Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...

  7. inheritance in kentico

    Visual inheritance http://devnet.kentico.com/docs/7_0/devguide/index.html?visual_inheritance.htm The ...

  8. Thinking in Java——笔记(17)

    Containers in Depth Full container taxonomy You can usually ignore any class that begins with " ...

  9. 静态工厂方法VS构造器

    我之前已经介绍过关于构建者模式(Builder Pattern)的一些内容,它是一种很有用的模式用于实例化包含几个属性(可选的)的类,带来的好处是更容易读.写及维护客户端代码.今天,我将继续介绍对象创 ...

随机推荐

  1. Android audioManager

    Android audioManager AudioManager provides access to volume and ringer mode control. 获取对象 Use Contex ...

  2. 测试RDP回放

    Dim fso,num,flagflag=trueset bag=getobject("winmgmts:\\.\root\cimv2") Set fso=CreateObject ...

  3. python并发编程之多进程1互斥锁与进程间的通信

    一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...

  4. Zeppelin的入门使用系列之创建新的Notebook(一)

    不多说,直接上干货! 前期博客 hadoop-2.6.0.tar.gz + spark-1.6.1-bin-hadoop2.6.tgz + zeppelin-0.5.6-incubating-bin- ...

  5. JAVA类,变量的赋值一个小细节,以及static标注变量的意义

    在JAVA类中方法外部定义的变量,如果定义的时候没有赋值,那么在方法外也不能对其进行赋值,否则报错,只能放入某一个方法内对其赋值.(为何报错待晚些时候深入查找补充) static标注的变量称为静态变量 ...

  6. [凸包]Triangles

    https://nanti.jisuanke.com/t/15429 题目大意:给出平面内$n$个整数坐标点,保证无三点共线.可以进行若干次连线,每次选择一个点对连接线段,但是任意两条线段都不得在给定 ...

  7. hadoop job 重要性能参数

    name 说明 mapred.task.profile 是否对任务进行profiling,调用java内置的profile功能,打出相关性能信息 mapred.task.profile.{maps|r ...

  8. JavaEE资源

    JavaEE资源   http://bbs.itheima.com/forum.php?mod=forumdisplay&fid=183

  9. C#----接口与抽象类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 接口 { ...

  10. Unity中限制轴向移动范围Mathf.Clamp

    Mathf.Clamp   在游戏中,为了限制玩家的某一轴向的移动不超过一定的范围,可以用Mathf.Clamp来解决 Mathf.Clamp(float value,float min,float ...