博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Selenium-webdriver系列教程(8)———使用Page Object设计模式
阅读量:4051 次
发布时间:2019-05-25

本文共 5012 字,大约阅读时间需要 16 分钟。

有时间再看, 有的地方代码是有问题的。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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弹出后输入用户名和密码,点击【登陆】按钮进行登陆。

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

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

1
2
3
4
5
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的函数,如下所示

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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函数看起来可能会是这样的:

1
2
3
4
5
def
login usr, psd
    
set_usr usr
    
set_psd psd
    
click_login_btn
end

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

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

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

1
2
3
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主页用户登陆功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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 =
''
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将为我们带来一系列的实惠和惊喜,就像超级的代金券一样,看上去不起眼但用起来却其乐无穷,浑身舒爽。

代码链接如下

转载地址:http://zzjci.baihongyu.com/

你可能感兴趣的文章
python_configparser(解析ini)
查看>>
selenium学习资料
查看>>
<转>文档视图指针互获
查看>>
从mysql中 导出/导入表及数据
查看>>
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
swiper插件的的使用
查看>>
layui插件的使用
查看>>
JS牛客网编译环境的使用
查看>>
9、VUE面经
查看>>
关于进制转换的具体实现代码
查看>>
Golang 数据可视化利器 go-echarts ,实际使用
查看>>
mysql 跨机器查询,使用dblink
查看>>
mysql5.6.34 升级到mysql5.7.32
查看>>
dba 常用查询
查看>>
Oracle 异机恢复
查看>>
Oracle 12C DG 搭建(RAC-RAC/RAC-单机)
查看>>
Truncate 表之恢复
查看>>
Oracle DG failover 后恢复
查看>>