Selenium-webdriver系列教程(8)————使用Page Object设计模式

在进行web前端自动化测试的过程中,Page Object设计模式可以称得上是杀人放火,居家旅行的常备武器。

Page Object将测试对象及单个的测试步骤封装在每个Page对象中,以page为单位进行管理。举例来说,在没有使用Page Object模式的情况下,脚本可能是这样写的:

require 'rubygems'
require 'selenium-webdriver'
 
url = 'www.soso.com'
dr = Selenium::WebDriver.for :ie
dr.navigate.to url
 
ua_links = dr.find_element(:id => 'ua').find_elements(:css => 'a')
ua_links[3].click
ua_links[3].send_keys(:enter)
sleep 2
dr.switch_to.frame('login_frame')
user = {:name => 'test', :psd => 'test'}
dr.find_element(:id => 'u').send_keys(user[:name])
dr.find_element(:id => 'p').send_keys(user[:psd])
dr.find_element(:id => 'login_button').click
sleep 2
dr.close

这段脚本的作用是去到soso,然后点击【登陆】link,待登陆的dialog弹出后输入用户名和密码,点击【登陆】按钮进行登陆。

看上去这段脚本是不错的,因为其很好的完成了登陆的任务,但不妨深入思考一下,如果我们需要验证错误的用户名正确的密码的话,那么上面关于登陆的那几行脚本是不是需要重复写一遍?

答案是否定的,因为登陆的功能可以抽象成函数,如下所示:

def login usr, psd
    dr.find_element(:id => 'u').send_keys(usr)
    dr.find_element(:id => 'p').send_keys(psd)
    dr.find_element(:id => 'login_button').click
end

这样就可以通过构造不同的数据,每次测试时只需要调用login函数就可以了。

再深入想一下,假设需要测试不输入用户名和密码直接点击登陆按钮的情况,那该怎么办呢?

首先最容易想到的一点是改造login函数,当然usr和psd没有传入的时候就直接点点击登陆按钮,这是没有问题的。不过如果本着代码增强可读性原则,亦可以定义一个名为login_without_usr_psd的函数,如下所示

def login_without_usr_psd
    dr.find_element(:id => 'login_button').click
end

这样在编写测试用例代码的时候就可以直接凭借函数名来揣测出该函数的作用,起到了self explain的作用。在自动化测试代码中,这一点是被鼓励的。

不过这样多定义1个函数就会带来另外的问题 dr.findelement(:id => 'loginbutton').click这行代码就在loin函数和login_without_usr_psd中重复使用。

为了解决这个有些丑陋的问题,使得代码能够稍微美化一点,可以定义另外一个函数来实现点击登陆按钮的功能。

def click_login_btn
    dr.find_element(:id => 'login_button').click
end
 
# now login_without_usr_psd will like below
def login_without_usr_psd
    click_login_btn
end
 
# login function will like this
def login usr, psd
    dr.find_element(:id => 'u').send_keys(usr)
    dr.find_element(:id => 'p').send_keys(psd)
    click_login_btn
end

好了,那么本着使代码更加灵活,self explain 特性更加明显的原则,我们又可以将输入用户名输入用户密码功能抽象成函数,这时候login函数看起来可能会是这样的:

def login usr, psd
    set_usr usr
    set_psd psd
    click_login_btn
end

如果我们重复上面的步骤,一步一步的提升代码的复用性和可读性的话,我们就会发现除了上面演示的setusr,setpsd这样的【基本动作】外,有些测试对象也是可以复用的。比如在登陆的时候我们会用到密码输入框,也许在修改密码的时候我们也会用到这一对象。

很自然的就会想到,如果将一些测试对象以及操作这些测试对象的动作或步骤封装在1个类中,那么代码的灵活性和适用性将会更强。那么按照什么纬度来划分这些类呢?也是很自然的,就像睡醒了就会睁眼,挖完煤就要洗脸一样,我们会发现按照页面也就是page来组织这些类将是很好的解决方案。

这就是Page Object设计模式,将每一个测试页面抽象为1个Page类,并在该类中封装了本页面的测试对象和基本的测试步骤,以提高代码的可读性复用性通用性和一致性。Page Object设计模式带来的好处是显而易见的。比如使用了page object模式后,测试用例可能会如下面所示

soso_page = Site.new(dr).soso_main_page(url).open
soso_page.login wrong_usr, wrong_psd
soso_page.error_msg.should be_eql('error')

测试用例简单且易读,而且代码的复用性极佳。其他用例需要使用到login功能时候只需要new 包含该功能的Page对象,调用login方法既可。

下面的代码演示了如何使用Page Object设计模式重构本文开头所实现的soso主页用户登陆功能。

base_page.rb
 
class BrowserContainer
    def initialize driver
        @dr = driver
    end
end # BrowserContainer
 
class Site < BrowserContainer
    def soso_main_page url
        @soso_main_page = SosoMainPage.new(@dr, url)
    end
 
    def close
        @dr.close
    end
end #Site
 
class BasePage < BrowserContainer
    attr_reader :url
 
    def initialize dr, url
        super(dr)
        @url = url  
    end
 
    def open
        @dr.navigate.to @url    
        self
    end
end #BasePage
 
class SosoMainPage < BasePage
    require './login_dialog'
    include LoginDialog
 
    def login usr, psd
        open_login_dialog
        to_dialog_frame
        usr_field.send_keys usr 
        psd_field.send_keys psd
        login_btn.click
    end
 
    def open_login_dialog
        login_link.click
        login_link.send_keys(:enter)
        sleep 2
    end
 
    private
 
    def ua_links
        @dr.find_element(:id => 'ua').find_elements(:css => 'a')
    end
 
    def login_link
        ua_links[3]
    end 
end #SosoMainPage
 
login_dialog.rb     
 
module LoginDialog
    def to_dialog_frame
        begin
            @dr.switch_to.frame('login_frame')  
        rescue
            raise 'Can not switch to login dialog, make sure the dialog was open'
            exit
        end
    end
 
    def usr_field
        @dr.find_element(:id => 'u')
    end
 
    def psd_field
        @dr.find_element(:id => 'p')
    end
 
    def login_btn
        @dr.find_element(:id => 'login_button')
    end
end #LoginDialog
 
login.rb
 
require 'rubygems'
require 'selenium-webdriver'
require './base_page'
 
dr = Selenium::WebDriver.for :firefox
url = 'http://www.soso.com'
soso_page = Site.new(dr).soso_main_page(url).open
soso_page.login 'test', 'test'

上面的代码由3个文件组成。

base_page.rb文件中定义了

  • Site类 主要用于管理测试中所需要用到的各种页面,提供生成这些页面对象的快捷方法。比如Site.new(dr).soso_main_page(url)方法就实例化了1个SosoMainPage对象。

  • BasePage类 所有Page对象的基类

  • SosoMainPage类 代表了soso主页的Page Object类,封装了首页的一些测试对象,原子操作及基本步骤,如login

login_dialog.rb文件中定义了代码登陆弹出框的LoginDialog。由于login dialog可能会出现在多个页面,比如qq音乐的登陆页面也有该弹出框,所以将其抽象成module,需要用到的页面直接include该module既可。

login.rb文件调用page object并实现了具体的测试逻辑,这个文件中可以使用你熟悉的测试框架来组织用例,如unit test和rspec等

关于Page Object设计模式的介绍就要告一段落了,从上面的代码中我们可以感觉到,Page Object模式加上测试用例框架就基本上可以等于简单的自动化测试框架了。所以在构建自动化测试框架的过程中,活用Page Object将为我们带来一系列的实惠和惊喜,就像超级的代金券一样,看上去不起眼但用起来却其乐无穷,浑身舒爽。

代码链接如下

page_object_attach
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
课程介绍你是否在寻找机会进入自动化测试领域? 你是否渴望学习selenium webdriver + Java以及最新的框架和技术进行web自动化测试? 你是否感兴趣学习Selenium如何用在你现有的项目里的? 这门课带你从Selenium搭建环境开始讲起,然后学习selenium,TestNG, logback, maven, jenkins。 我们假设学员没有任何自动化经验,来设计的这套课程。每个课题都从最基础的开始讲起。Selenium相关的该覆盖的课题都覆盖了。 例子都是来自于真实的web应用项目,帮助你理解不同的组件怎么用上自动化,这将展示给你一个行业层面的框架,增加自信心。 全网没有其他课程像这门课涵盖到如此之深的细节。 您将会学到什么 学完课程以后,你将拥有完整的Selenium Webdriver知识 你将具备从头开始设计Page ObjectPage Factory、DATADRIVEN等搭建自动化框架的能力 用100多个实例对Selenium现实场景应用进行深入理解 全面了解TestNG, Maven, Jenkins, HTML报告,多浏览器并行测试 了解数据库测试使用Selenium进行性能测试 你将彻底了解testNG框架 你从网上随便选择一个网站,都可以实现自动化,用所有可能的测试用例进行自动化测试 将提高你的编码技能,以编写最优化的自动化测试用例代码 你基本可以搞定任何Selenium面试,并能从设计阶段开始领导整个Selenium自动化项目 你应该能够使用应用程序的GUI来验证数据完整性 你将能够创建漂亮的报告来打动客户或领导 更深入地理解自动化指南和代码质量标准 会附带一个练习网站,可以用上所有可用的WebDriver功能,实现自动化 【适合人群】 软件手动测试人员想转为自动化测试的人员 自动化软件测试人员想加强专业技能的 刚毕业学生想从事软件行业 QA 组长或项目经理 【课程优势】 学完课程以后,你将拥有完整的Selenium Webdriver知识 【讲师介绍】 资质介绍: 12年以上软件测试工作经验,其中7年以上自动化测试开发经验 新书“Python3+Selenium3自动化测试项目实战”作者

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值