(一) 前言

简单的说就是分为2层,页面class 和测试class。

页面class:分为父类和子类(子类指具体的页面,每一个页面都创建一个类),父类中定义公有的属性和方法(操作)。

#对面向对象有了解的,应该很容易理解抽象出公有属性和方法的意思

#父类和子类我是按自己的理解进行描述的,或者可以说basepage对象(父对象,提供公有的属性、方法) 和 page对象(具体哪一个页面)

测试class:按照业务流程,对各个页面的属性、操作进行组合,形成一个测试用例。

使用page object模式,抽象出各个页面的元素、方法,然后再按照测试用例的要求进行组合。这样做的好处是

1、页面修改了,只要对页面类进行修改就好了,对测试类(测试用例)没太大影响

2、可以在多个测试复用部分代码。

3、测试代码(测试类、测试用例)部分变得更易读、灵活、可维护。

我把上一篇的代码按照page object模式修改了下,代码如下。

(二) 父类(BasePage对象,base.py)

 from abc import abstractclassmethod
class BasePage(object):
def __init__(self,driver):
self.driver = driver '''验证页面是否是指定的页面。
@abstractclassmethod修饰符指该方法是抽象的'''
@abstractclassmethod
def validate_page(self,driver):
return

(三) 首页(page对象(子类),homepage.py)

 from base import BasePage
class HomePage(BasePage):
#用来定位页面元素的ID、NAME、XPTH、CSS表达式等
_login_area = '#login_area'
_register = '注册' def validate_page(self,driver):
return driver.title == '博客园 - 开发者的网上家园'
#定位并点击 注册
def register_click(self):
self.login_area = self.driver.find_element_by_css_selector(self._login_area)
self.login_area.find_element_by_link_text(self._register).click()

(四) 注册页面(page对象(子类),registerpage.py)

 from base import BasePage
class RegisterPage(BasePage):
# 用来定位页面元素的ID、NAME、XPTH、CSS表达式等
_user_email = 'Email'
_user_phone_country = 'CountryCode'
_user_phone = 'PhoneNum'
_user_login_name = 'LoginName'
_user_nickname = 'DisplayName'
_user_password = 'Password'
_user_confirm_password = 'ConfirmPassword'
_phone_error = 'PhoneNum-error'
_loginName_error = 'LoginName-error' def validate_page(self,driver):
return driver.title == '用户注册 - 博客园' #输入注册信息
def send_keys(self,email,phone,login_name,nickname,password,confirm_password):
self.driver.find_element_by_id(self._user_email).clear()
self.driver.find_element_by_id(self._user_phone).clear()
self.driver.find_element_by_id(self._user_login_name).clear()
self.driver.find_element_by_id(self._user_nickname).clear()
self.driver.find_element_by_id(self._user_password).clear()
self.driver.find_element_by_id(self._user_confirm_password).clear()
self.driver.find_element_by_id(self._user_email).send_keys(email)
self.driver.find_element_by_id(self._user_phone).send_keys(phone)
self.driver.find_element_by_id(self._user_login_name).send_keys(login_name)
self.driver.find_element_by_id(self._user_nickname).send_keys(nickname)
self.driver.find_element_by_id(self._user_password).send_keys(password)
self.driver.find_element_by_id(self._user_confirm_password).send_keys(confirm_password) #手机号码有误时的提示信息
def phone_err(self):
phone_error = self.driver.find_element_by_id(self._phone_error)
return phone_error.text #登录名不合法时的提示信息
def loginName_error(self):
loginName_error = self.driver.find_element_by_id(self._loginName_error)
return loginName_error.text

(五)   测试类(测试用例,testRegisterNewUser.py)

 from selenium import webdriver
from ddt import ddt,data,unpack
import xlrd
from homepage import HomePage
from registerpage import RegisterPage
from basetestcase import BaseTestCase
#读取Excel数据的函数
def get_data(file_name):
rows = []
book = xlrd.open_workbook(file_name)
sheet = book.sheet_by_index(0)
for r_idx in range(1, sheet.nrows):
rows.append(list(sheet.row_values(r_idx,0)))
pthone = rows[r_idx - 1].pop(1)
rows[r_idx - 1].insert(1, str(int(pthone)))
return rows
@ddt
class RegisterNewUserDDT(BaseTestCase):
#重写setUpClass()
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.driver.implicitly_wait(30)
cls.driver.maximize_window()
cls.driver.get('https://www.cnblogs.com/')
#创建HomePage()类的对象实例
home_page = HomePage(cls.driver)
home_page.register_click()
# 读取excel文件的数据作为参数
@data(*get_data('data/reTest.xlsx'))
@unpack
def test_register_new_user(self,email,phone,login_name,nickname,password,confirm_password,expected_result):
#创建RegisterPage()的对象实例
register_page = RegisterPage(self.driver)
self.assertTrue(register_page.validate_page(self.driver))
register_page.send_keys(email,phone,login_name,nickname,password,confirm_password)
if phone == '':
self.assertTrue(register_page.phone_err() == expected_result)
elif login_name == 'b':
self.assertTrue(register_page.loginName_error() == expected_result)

(六) 测试准备(basetestcase.py)

#这部分本来想放到第二步的,不过感觉有点影响对page object的理解,就放到最后了

  创建一个类,定义setup()和teardowm()方法,方便所有测试复用。这个类可以理解为是测试类的一部分,我只是把所有测试类(测试用例)都用到的setup()和teardowm()拿出来,方便复用。如果哪个测试用例有特殊要求,也可以重写。

 import unittest
from selenium import webdriver class BaseTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.driver.implicitly_wait(30)
cls.driver.maximize_window()
cls.driver.get('https://www.cnblogs.com/')
@classmethod
def tearDownClass(cls):
cls.driver.quit()

Python+Selenium笔记(十三):Page Object设计模式的更多相关文章

  1. python+ selenium&APPium自动化 page Object 设计模式

    题记: 之前公司项目比较稳定, 在进行了系统测试,想用自动化测试进行冒烟测试,或者对主要功能进行测试, 因此用到了PO模式 因此做个记录: Page Object Page Object模式是使用Se ...

  2. Python+Selenium框架设计--- Page Object Model

    POM(Page Object Model):页面对象模型,POM是一种最近几年非常流行的自动化测试模型,或者思想,POM不是一个框架,就是一个解决问题的思想.采用POM的目的,是为了解决前端中UI变 ...

  3. selenium+Python(Page Object 设计模式实例)

    以下实例演示了采用了page Object设计模式的方式登录qq空间: 1.创建基础类page:在初始方法__init__()定义驱动的(driver),基本url(base_url)和超时时间(ti ...

  4. Python+selenium之Page Object设计模式

    Page Object是selenium自动化测试项目开发实践的最佳设计模式之一,他主要提现在对界面交互细节的封装,这样可以使测试案例隔你给加关注于业务而非界面细节,从而提高测试案例的可读性. Pag ...

  5. web端自动化——selenium Page Object设计模式

    Page Object设计模式的优点如下: ①    减少代码的重复. ②    提高测试用例的可读性. ③    提高测试用例的可维护性,特别是针对UI频繁变化的项目. 当为Web页面编写测试时,需 ...

  6. Selenium+java - Page Object设计模式

    前言 Page Object(页面对象)模式,是Selenium实战中最为流行,并且被自动化测试同学所熟悉和推崇的一种设计模式之一.在设计测试时,把页面元素定位和元素操作方法按照页面抽象出来,分离成一 ...

  7. Selenium(十九):unittest单元测试框架(五) Page Object设计模式

    1. Page Object设计模式 Page Object是Selenium自动化测试项目开发实践的最佳设计模式之一,它主要体现在对界面交互细节的封装,这样可以使测试方案更关注于业务而非界面细节.从 ...

  8. Selenium 2自动化测试实战39(Page Object设计模式)

    Page Object设计模式 Page object是selenium自动化测试项目开发时间的最佳设计模式之一,主要体现在对界面交互细节的封装. 1.认识page object优点如下:1.减少代码 ...

  9. Page Object设计模式实践

    Page Object模式是使用Selenium的广大同行最为公认的一种设计模式.在设计测试时,把元素和方法按照页面抽象出来,分离成一定的对象,然后再进行组织. Page Object模式,创建一个对 ...

  10. Page Object 设计模式介绍

    Page Object 是 Selenium 自动化测试项目开发实践的最佳设计模式之一,Page Object 的主要体现于对界面交互细节的封装,这样可以使测试案例更关注与业务而非界面细节,提高测试案 ...

随机推荐

  1. Jfinal QuartzPlugin 简单使用案例

    之前一直使用spring quartz感觉还挺好用的,就想着jfinal是不是也可以使用quartz插件,于是发现了QuartzPlugin和jfinal-scheduler<参考:https: ...

  2. Android在代码中获取meta标签内容

    最近写SDK需要获取<meta>标签的值,网上资料很多~分享是件好事~我很快就找到了相关资料. 下面贴上代码: ApplicationInfo appInfo = null; String ...

  3. JAR 介绍-百度百科

    JAR(Java Archive,Java 归档文件)是与平台无关的文件格式,它允许将许多文件组合成一个压缩文件.为 J2EE 应用程序创建的 JAR 文件是 EAR 文件(企业 JAR 文件). J ...

  4. 图解RAID 0, RAID 1, RAID 5, RAID 10

    RAID(Redundant Array of Independent Disk 独立冗余磁盘阵列)技术是加州大学伯克利分校1987年提出,最初是为了组合小的廉价磁盘来代替大的昂贵磁盘,同时希望磁盘失 ...

  5. 【LeetCode题解】25_k个一组翻转链表(Reverse-Nodes-in-k-Group)

    目录 描述 解法一:迭代 思路 Java 实现 Python 实现 复杂度分析 解法二:递归(不满足空间复杂度) 思路 Java 实现 Python 实现 复杂度分析 更多 LeetCode 题解笔记 ...

  6. 线程池ThreadPoolExecutor的一种扩展办法

    概述 在JAVA的世界里,如果想并行的执行一些任务,可以使用ThreadPoolExecutor. 大部分情况下直接使用ThreadPoolExecutor就可以满足要求了,但是在某些场景下,比如瞬时 ...

  7. Docker环境下搭建DNS LVS(keepAlived) OpenResty服务器简易集群

    现在上网已经成为每个人必备的技能,打开浏览器,输入网址,回车,简单的几步就能浏览到漂亮的网页,那从请求发出到返回漂亮的页面是怎么做到的呢,我将从公司中一般的分层架构角度考虑搭建一个简易集群来实现.目标 ...

  8. 【转】CSS3 Box-sizing

    box-sizing是CSS3的box属性之一.一说到CSS的盒模型(Box model)我想很多人都会比较烦,特别是对于新手,然而这个Box model又是我们CSS运用中比较重要的一个属性.那么C ...

  9. ASP.NET MVC加载ASCX之后,并为之赋值

    Insus.NET有写过一篇<ASP.NET MVC显示UserControl控件(扩展篇)>http://www.cnblogs.com/insus/p/3642634.html ,还没 ...

  10. WinMain函数详解(转载再编辑)

    在Windows应用程序中,我们可以认为 WinMain() 函数是程序的入口,WinMain()的原型如下: int WINAPI WinMain( HINSTANCE hInstance, HIN ...