Composition or inheritance for delegating page methods?
引用链接: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?的更多相关文章
- 组合优于继承 Composition over inheritance
https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance 解答1 Prefer composition ...
- Effective Java 16 Favor composition over inheritance
Inheritance disadvantage Unlike method invocation, inheritance violates encapsulation. Since you don ...
- React之Composition Vs inheritance 组合Vs继承
React的组合 composition: props有个特殊属性,children,组件可以通过props.children拿到所有包含在内的子元素, 当组件内有子元素时,组件属性上的child ...
- 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 ...
- selenium page object model
Page Object Model (POM) & Page Factory in Selenium: Ultimate Guide 来源:http://www.guru99.com/page ...
- <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>
<Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...
- inheritance in kentico
Visual inheritance http://devnet.kentico.com/docs/7_0/devguide/index.html?visual_inheritance.htm The ...
- Thinking in Java——笔记(17)
Containers in Depth Full container taxonomy You can usually ignore any class that begins with " ...
- 静态工厂方法VS构造器
我之前已经介绍过关于构建者模式(Builder Pattern)的一些内容,它是一种很有用的模式用于实例化包含几个属性(可选的)的类,带来的好处是更容易读.写及维护客户端代码.今天,我将继续介绍对象创 ...
随机推荐
- shell入门-awk-2
awk的条件操作符 ///显示第一段有root的行 [root@wangshaojun ~]# awk -F ':' '$1=="root"' 1.txtroot:x:0:0:ro ...
- web安全之XSS和CSRF
XSS 跨站脚本攻击(cross site script),本来缩写CSS单位了和层叠样式(Cascading Style Sheet,CSS)有所区别,所以在安全领域叫做“XSS”. XSS攻击,通 ...
- mysql nginx redis 配置文件
https://github.com/superhj1987/awesome-config
- cocos2dx之lua绑定简析
一.总原则:c++对象的生命期不依赖lua gc管理,手动创建的对象要手动销毁 二.引擎层在设计上就是支持脚本概念的(也就是说脚本的使用是“侵入式”的),与lua打交道的代码都封在CCLuaEngin ...
- p2279&bzoj1217 消防局的设立
传送门(洛谷) 传送门(bzoj) 题目 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来 连接这些基地,并且每两个基地都能够通过道路到达, ...
- .NET中的泛型委托
.Net中有一个内置的委托 Func 它总共有以下5种形式 1. Func<TResult> 2. Func<T,TResult> 3. Func<T1,T2,TR ...
- [转载]Java程序员掌握的10大项知识体系--精通太难说出口
1.语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语法错误并且知道任何修正. 2.命令:必须熟悉JDK带的一些常用命令及其常用选项,命令至少需要熟悉:a ...
- git 仓库拆分方案对比
此文已由作者张磊授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 前言 git 拆分仓库在网上已有的案例上来看,分为 submodule 和 subtree. 还有基于这两个方 ...
- 安全测试 + 渗透测试 Xmind 要点梳理
从事测试工作多年,一直对安全测试充满神秘感.买了本书,闲来无事时翻看了解.发现书的开头提供的Xmind脑图挺有参考价值,所以做了次“搬运工”,提供给想接触了解安全测试/渗透测试的小伙伴. 安全测试要点 ...
- SCUT - 337 - 岩殿居蟹 - 线段树 - 树状数组
https://scut.online/p/337 这个东西是个阶梯状的.那么可以考虑存两棵树,一棵树是阶梯的,另一棵树的平的,随便一减就是需要的阶梯. 优化之后貌似速度比树状数组还惊人. #incl ...