Selenium-webdriver—使用Page Object设计模式

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

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

Ruby代码   收藏代码
  1. require 'rubygems'  
  2. require 'selenium-webdriver'  
  3.   
  4. url = 'www.soso.com'  
  5. dr = Selenium::WebDriver.for :ie  
  6. dr.navigate.to url  
  7.   
  8. ua_links = dr.find_element(:id => 'ua').find_elements(:css => 'a')  
  9. ua_links[3].click  
  10. ua_links[3].send_keys(:enter)  
  11. sleep 2  
  12. dr.switch_to.frame('login_frame')  
  13. user = {:name => 'test':psd => 'test'}  
  14. dr.find_element(:id => 'u').send_keys(user[:name])  
  15. dr.find_element(:id => 'p').send_keys(user[:psd])  
  16. dr.find_element(:id => 'login_button').click  
  17. sleep 2  
  18. dr.close  

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

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

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

Ruby代码   收藏代码
  1. def login usr, psd  
  2.     dr.find_element(:id => 'u').send_keys(usr)  
  3.     dr.find_element(:id => 'p').send_keys(psd)  
  4.     dr.find_element(:id => 'login_button').click  
  5. end  

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

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

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

Ruby代码   收藏代码
  1. def login_without_usr_psd  
  2.     dr.find_element(:id => 'login_button').click  
  3. end  

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

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

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

Ruby代码   收藏代码
  1. def click_login_btn  
  2.     dr.find_element(:id => 'login_button').click  
  3. end  
  4.   
  5. # now login_without_usr_psd will like below  
  6. def login_without_usr_psd  
  7.     click_login_btn  
  8. end  
  9.   
  10. # login function will like this  
  11. def login usr, psd  
  12.     dr.find_element(:id => 'u').send_keys(usr)  
  13.     dr.find_element(:id => 'p').send_keys(psd)  
  14.     click_login_btn  
  15. end  

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

Ruby代码   收藏代码
  1. def login usr, psd  
  2.     set_usr usr  
  3.     set_psd psd  
  4.     click_login_btn  
  5. end  

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

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

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

Ruby代码   收藏代码
  1. soso_page = Site.new(dr).soso_main_page(url).open  
  2. soso_page.login wrong_usr, wrong_psd  
  3. soso_page.error_msg.should be_eql('error')  

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

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

Ruby代码   收藏代码
  1. base_page.rb  
  2.   
  3. class BrowserContainer  
  4.     def initialize driver  
  5.         @dr = driver  
  6.     end  
  7. end # BrowserContainer  
  8.   
  9. class Site < BrowserContainer  
  10.     def soso_main_page url  
  11.         @soso_main_page = SosoMainPage.new(@dr, url)  
  12.     end  
  13.   
  14.     def close  
  15.         @dr.close  
  16.     end  
  17. end #Site  
  18.   
  19. class BasePage < BrowserContainer  
  20.     attr_reader :url  
  21.   
  22.     def initialize dr, url  
  23.         super(dr)  
  24.         @url = url  
  25.     end  
  26.   
  27.     def open  
  28.         @dr.navigate.to @url  
  29.         self  
  30.     end  
  31. end #BasePage  
  32.   
  33. class SosoMainPage < BasePage  
  34.     require './login_dialog'  
  35.     include LoginDialog  
  36.   
  37.     def login usr, psd  
  38.         open_login_dialog  
  39.         to_dialog_frame  
  40.         usr_field.send_keys usr  
  41.         psd_field.send_keys psd  
  42.         login_btn.click  
  43.     end  
  44.   
  45.     def open_login_dialog  
  46.         login_link.click  
  47.         login_link.send_keys(:enter)  
  48.         sleep 2  
  49.     end  
  50.   
  51.     private  
  52.   
  53.     def ua_links  
  54.         @dr.find_element(:id => 'ua').find_elements(:css => 'a')  
  55.     end  
  56.   
  57.     def login_link  
  58.         ua_links[3]  
  59.     end  
  60. end #SosoMainPage  
  61.   
  62. login_dialog.rb       
  63.   
  64. module LoginDialog  
  65.     def to_dialog_frame  
  66.         begin  
  67.             @dr.switch_to.frame('login_frame')  
  68.         rescue  
  69.             raise 'Can not switch to login dialog, make sure the dialog was open'  
  70.             exit  
  71.         end  
  72.     end  
  73.   
  74.     def usr_field  
  75.         @dr.find_element(:id => 'u')  
  76.     end  
  77.   
  78.     def psd_field  
  79.         @dr.find_element(:id => 'p')  
  80.     end  
  81.   
  82.     def login_btn  
  83.         @dr.find_element(:id => 'login_button')  
  84.     end  
  85. end #LoginDialog  
  86.   
  87. login.rb  
  88.   
  89. require 'rubygems'  
  90. require 'selenium-webdriver'  
  91. require './base_page'  
  92.   
  93. dr = Selenium::WebDriver.for :firefox  
  94. url = 'http://www.soso.com'  
  95. soso_page = Site.new(dr).soso_main_page(url).open  
  96. 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将为我们带来一系列的实惠和惊喜,就像超级的代金券一样,看上去不起眼但用起来却其乐无穷,浑身舒爽。
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值