Page Object Model (Selenium, Python)
时间 2015-06-15 00:11:56 Qxf2 blog
We have come a long way since our post on implementing the Page Object Model
- Implementing the Page Object Model (Selenium + Python)
While the above post is useful and we rank high on Google, we routinely hear two criticisms of it:
a) the post is too high level
b) the application being tested is not very repeatable
So we thought we would rework the above piece to address the drawbacks. In this post we shall give you a more detailed architecture, provide many more code snippets and write an automated test for Gmail.
Overview of Page Object Model
A page object represents an area in the web application user interface that your test is interacting with. Page objects reduces the amount of duplicated code and if the user interface changes, the fix needs changes in one place only.[ 1 ]
WHAT vs HOW
Usually the testers write the test cases describing ‘what’ is to be tested, this depends on the product functionality. But the implementation of this functionality by the developers keeps changing till the final code freeze is done, hence testers should know ‘how’ to implement the test cases so that the changes to the test scripts are minimal in case of code changes by the the developers. Page Objects encapsulates the finer details(locators and methods) of the pages from the test script and make the test script more readable and robust.
Sample Test Case – (WHAT)
We are going to explain about page objects with a very simple test case for Gmail.
-Goto http://gmail.com
-Enter the username, click Next
-Enter the password, click Sign in
-Perform search on the inbox ‘subject:POM’
-Click on the search result
-Click on inbox
A simple approach would be to write a test script with all the xpaths and the methods required for the execution of the above listed steps in one single file. The test would run fine and achieve the purpose but one major drawback is the test script is brittle. For any minor UI change on any page, the test script would have to be updated.To overcome this problem we use the page object pattern. As its name suggests,each page of the application to be tested is treated like an object which has the variables (xpaths) and methods (actions that can be performed on that particular page). This in turn makes the test script much cleaner.
Implementing the test case using POM templates (HOW)
Given below is the pictorial description of the various page objects used for the implementation of the test case.

Lets start with the main hero – Page.py
All page models can inherit from the Page class. This has useful wrappers for common Selenium operations
class Page(unittest.TestCase):
"Page class that all page models can inherit from"
def __init__(self,selenium_driver,base_url='https://mail.google.com/'):
"Constructor"
#We assume relative URLs start without a / in the beginning
if base_url[-1] != '/':
base_url += '/'
self.base_url = base_url
self.driver = selenium_driver
#Visit and initialize xpaths for the appropriate page
self.start()
#Initialize the logger object
self.log_obj = Base_Logging(level=logging.DEBUG)
def open(self,url):
"Visit the page base_url + url"
url = self.base_url + url
self.driver.get(url)
def get_xpath(self,xpath):
"Return the DOM element of the xpath OR the 'None' object if the element is not found"
def click_element(self,xpath):
"Click the button supplied"
.
.
def write(self,msg,level='info'):
self.log_obj.write(msg,level)
def wait(self,wait_seconds=5):
" Performs wait for time provided"
time.sleep(wait_seconds)
Next is the Login_Page.py which handles the common functionality of user login. This will be the most re-used class.
from Page import Page
class Login_Page(Page):
"Page object for the Login page"
def start(self):
self.url = ""
self.open(self.url)
# Assert Title of the Login Page and Login
self.assertIn("Gmail", self.driver.title)
"Xpath of all the field"
#Login
self.login_email = "//input[@name='Email']"
self.login_next_button = "//input[@id='next']"
self.login_password = "//input[@placeholder='Password']"
self.login_signin_button = "//input[@id='signIn']"
def login(self,username,password):
"Login using credentials provided"
self.set_login_email(username)
self.submit_next()
self.set_login_password(password)
self.submit_login()
if 'Qxf2 Mail' in self.driver.title :
self.write("Login Success")
return True
else:
self.write("FAIL: Login error")
return False
def set_login_email(self,username):
"Set the username on the login screen"
def submit_next(self):
self.click_element(self.login_next_button)
self.wait(3)
def set_login_password(self,password):
"Set the password on the login screen"
def submit_login(self):
"Submit the login form"
Once we login, the main page is displayed which consists of the header (which contains the search box, user profile options),the navigation menu on the left side of the page and the main body. As the header and the navigation menu are common to all pages we created page objects for each of them. Here is a snippet of each of the classes.
Nav_Menu.py
from Page import Page
class Nav_Menu(Page):
"Page object for the side menu"
def start(self):
"Xpath of all the field"
#Navigation Menu
self.inbox = "//a[contains(@href, '#inbox')]"
self.sent_mail = "//a[contains(@href, '#sent')]"
self.drafts= "//a[contains(@href, '#drafts')]"
def select_menu_item(self,menu_item):
"select menu item"
Header_Section.py
from Page import Page
class Header_Section(Page):
"Page object for the page header"
def start(self):
"Xpath of all the fields"
#Search and profile
self.search_textbox = "//input[@id='gbqfq']"
self.search_button = "//button[@id='gbqfb']"
self.signout_button = "//a[text()='Sign out']"
self.search_result = "//span[contains(text(),'%s')]"
def search_by_subject(self,searchtext):
self.set_text(self.search_textbox,'subject:'+searchtext)
.
.
Now, the Main_Page.py will contain the objects of the above two classes.
class Main_Page(Page):
"Page object for the Main page"
def start(self):
self.url = ""
self.open(self.url)
#Create a Header Section object
self.header_obj = Header_Section(self.driver)
#Create a Menu object
self.menu_obj = Nav_Menu(self.driver)
This completes the page objects needed for this particular test case.**Please note – as an alternate way, we can also have a ‘Template_Page'(which inherits from the Page class and has the common objects) and have all pages(except Login page) derive from it.
In addition to these we have the following files
PageFactory.py
PageFactory uses the factory design pattern. get_page_object() returns the appropriate page object.
def get_page_object(page_name,driver,base_url='https://gmail.com/'):
"Return the appropriate page object based on page_name"
test_obj = None
page_name = page_name.lower()
if page_name == "login":
test_obj = Login_Page(driver,base_url=base_url)
elif page_name == "main":
test_obj = Main_Page(driver,base_url=base_url) return test_obj
DriverFactory.pywhich returns the appropriate driver for firefox or chrome or IE browser.
login.credentialsfile contains the username , password required for authentication.
Finally , we have our test script which puts it all together and executes the test case.
Search_Inbox_Test.py
def run_search_inbox_test(browser,conf,base_url,sauce_flag,browser_version,platform,testrail_run_id):
"Login to Gmail using the page object model"
# get the test account credentials from the .credentials file
credentials_file = os.path.join(os.path.dirname(__file__),'login.credentials')
username = Conf_Reader.get_value(credentials_file,'LOGIN_USER')
password = Conf_Reader.get_value(credentials_file,'LOGIN_PASSWORD')
#Result flag used by TestRail
result_flag = False
#Setup a driver
#create object of driver factory
driver_obj = DriverFactory()
driver = driver_obj.get_web_driver(browser,sauce_flag,browser_version,platform)
driver.maximize_window()
#Create a login page object
login_obj = PageFactory.get_page_object("login",driver)
if (login_obj.login(username,password)):
msg = "Login was successful"
result_flag = True
login_obj.write(msg)
else:
msg = "Login failed"
login_obj.write(msg)
#Create an object for main page with header and menu
main_obj = PageFactory.get_page_object("main",driver)
main_obj.wait(3)
#Search the inbox for message by subject 'POM' and open the message
if main_obj.header_obj.search_by_subject('POM'):
main_obj.write("Search successful")
result_flag = True
else:
main_obj.write("Search text was not found")
result_flag = False
#Go to inbox
main_obj.menu_obj.select_menu_item('inbox')
As you must have noticed the final test is very easy to read and need not be modified in case of any underlying changes to individual pages.
Running the test
Let us execute the test,

and here is the log file for the test run.

So now, we all agree that the page objects make it really easy for the tester to convert the documented test case to an automated test case. Not only that, maintaining these tests is also very easy.
References:
1. http://selenium-python.readthedocs.org/en/latest/page-objects.html

My journey as a tester started at Sun Microsystems (now Oracle). I was part of the testing and sustaining team for the Portal Server and Identity Management products. My first assignment was to test the Rewriter module. I enjoyed understanding the big picture, writing test cases, finding bugs and sometimes suggesting the fix too! I was hooked onto testing. Testing felt natural and intuitive to me. I am technically inclined and can write automation in Java, C++, Perl and Python. I am well versed with SilkTest, Selenium, Appium and Selendroid. I am a Computer Science graduate from BITS-Pilani. I love travelling and listening to music.
© 2015,Qxf2 Services. All rights reserved.
Page Object Model (Selenium, Python)的更多相关文章
- Selenium的PO模式(Page Object Model)[python版]
Page Object Model 简称POM 普通的测试用例代码: .... #测试用例 def test_login_mail(self): driver = self.driver driv ...
- Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)
研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...
- Python+Selenium框架设计--- Page Object Model
POM(Page Object Model):页面对象模型,POM是一种最近几年非常流行的自动化测试模型,或者思想,POM不是一个框架,就是一个解决问题的思想.采用POM的目的,是为了解决前端中UI变 ...
- selenium page object model
Page Object Model (POM) & Page Factory in Selenium: Ultimate Guide 来源:http://www.guru99.com/page ...
- Appium+Python之PO模型(Page object Model)
思考:我们进行自动化测试时,如果把代码都写在一个脚本中,代码的可读性会变差,且后期代码维护也麻烦,最好的想法就是测试对象和测试用例可以分离,可以很快定位问题,代码可读性高,也比较容易理解.这里推荐大家 ...
- Java&Selenium自动化测试之Page Object Model
PO是什么: 1.页面对象模型(PO)是一种设计模式,用来管理维护一组web元素的对象库 2.在PO下,应用程序的每一个页面都有一个对应的page class 3.每一个page class维护着该w ...
- python+selenium自动化软件测试(第7章):Page Object模式
什么是Page ObjectModel模式Page Objects是selenium的一种测试设计模式,主要将每个页面看作是一个class.class的内容主要包括属性和方法,属性不难理解,就是这个页 ...
- Python+selenium之Page Object设计模式
Page Object是selenium自动化测试项目开发实践的最佳设计模式之一,他主要提现在对界面交互细节的封装,这样可以使测试案例隔你给加关注于业务而非界面细节,从而提高测试案例的可读性. Pag ...
- selenium 的页面对象模型Page Object
页面对象模型page object model是selenium中的一种脚本设计模式,它能将页面元素封装起来,与业务操作分隔开, 在页面变化改变时,无需去修改业务逻辑代码,提高脚本维护的效率. 1.p ...
随机推荐
- 淘宝(阿里百川)手机客户端开发日记第十四篇 jsp提交含有上传控件表单乱码问题
今天我来总结昨天开发的一个简单的jsp web 应用程序时,在做一个调教表单,从servlet端获取数据,这个表单里含有上传文件控件.如果我们在测试的时候,获取数据的是乱码,这时,大家可以先去掉上传控 ...
- Svn + tomcat + Hudson持续集成部署
1.首先下载hudson 2. 我这里使用hudson-3.0.1版本 3. 下载后hudson是一个 war 包 4. 操作部署: (1). 直接将hudson的war包复制到tomcat的weba ...
- Win7 x64bit安装Oracle10g
解决方案: 步骤一:在解压出的oracle文件夹中搜索refhost.xml文件,搜索结果出现2条符合条件文件,这两个文件均需要修改. 打开文件发现内容中有包含...5.0 6.0等系统说明, ...
- iOS 不规则的ImageView
http://blog.csdn.net/kevinpake/article/details/41205715 我们在做iOS开发的时候,往往需要实现不规则形状的头像,如: 那如何去实现? 通常图片都 ...
- Android学习笔记(十三)——广播机制
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! Android 中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容 ...
- WIN7 IIS7 安装方法
一.首先是安装IIS.打开控制面板,找到"程序与功能",点进去. 二.点击左侧"打开或关闭Windows功能". 三 看下图打相应的钩.
- VMware12中CentOS7网络设置
VMware提供了三种将虚拟网卡和物理网卡捆绑起来的方式,即桥接(Bridge)模式,网络地址转换(Network Address Transformation, NAT)模式和主机(Host Onl ...
- 深入浅出Java回调机制
本文转载自http://hellosure.iteye.com/blog/1130176 在网上看到了一个比喻,觉得很形象,这里借用一下: 你有一个复杂的问题解决不了,打电话给你的同学,你的同学说可以 ...
- Print Common Nodes in Two Binary Search Trees
Given two Binary Search Trees, find common nodes in them. In other words, find intersection of two B ...
- wxPython中文教程入门实例
这篇文章主要为大家分享下python编程中有关wxPython的中文教程,分享一些wxPython入门实例,有需要的朋友参考下 wxPython中文教程入门实例 wx.Window 是一个基类 ...