Python+Selenium使用Page Object实现页面自动化测试


Posted in Python onJuly 14, 2019

  Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通过调用页面类来获取页面元素,这样巧妙的避免了当页面元素id或者位置变化时,需要改测试页面代码的情况。 当页面元素id变化时,只需要更改测试页Class中页面的属性即可。

    Page Object模式是一种自动化测试设计模式,将页面定位和业务操作分开,分离测试对象(元素对象)和测试脚本(用例脚本),提高用例的可维护性。

    unittest是一种单元测试框架,用于设计各式各样的测试用例,可调用PageObject设计的页面类(对象),设计出更加可维护的用例。它提供用例组织与执行,提供丰富的比较(断言)方法,提供丰富的日志,统一适用于web自动化用例的开发与执行。

使用PO模式设计思路如下:

1.定义页面基础类,封装所有页面公用的方法。

命名为test_8_3_2_BasePage.py

# coding=utf-8
'''
Created on 2016-8-13
@author: Jennifer
Project:基础类BasePage,封装所有页面都公用的方法,
定义open函数,重定义find_element,switch_frame,send_keys等函数。
在初始化方法中定义驱动driver,基本url,title
WebDriverWait提供了显式等待方式。
'''
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class BasePage(object):
  """
  BasePage封装所有页面都公用的方法,例如driver, url ,FindElement等
  """
  #初始化driver、url、pagetitle等
  #实例化BasePage类时,最先执行的就是__init__方法,该方法的入参,其实就是BasePage类的入参。
  #__init__方法不能有返回值,只能返回None
  #self只实例本身,相较于类Page而言。
  def __init__(self, selenium_driver, base_url, pagetitle):
    self.driver = selenium_driver
    self.base_url = base_url
    self.pagetitle = pagetitle
     
  #通过title断言进入的页面是否正确。
  #使用title获取当前窗口title,检查输入的title是否在当前title中,返回比较结果(True 或 False)
  def on_page(self, pagetitle):
    return pagetitle in self.driver.title
  
  #打开页面,并校验页面链接是否加载正确
  #以单下划线_开头的方法,在使用import *时,该方法不会被导入,保证该方法为类私有的。
  def _open(self, url, pagetitle):
    #使用get打开访问链接地址
    self.driver.get(url)
    self.driver.maximize_window()
    #使用assert进行校验,打开的窗口title是否与配置的title一致。调用on_page()方法
    assert self.on_page(pagetitle), u"打开开页面失败 %s"%url
  
  #定义open方法,调用_open()进行打开链接
  def open(self):
    self._open(self.base_url, self.pagetitle)
  
  #重写元素定位方法
  def find_element(self,*loc):
#    return self.driver.find_element(*loc)
    try:
      #确保元素是可见的。
      #注意:以下入参为元组的元素,需要加*。Python存在这种特性,就是将入参放在元组里。
#      WebDriverWait(self.driver,10).until(lambda driver: driver.find_element(*loc).is_displayed())
      #注意:以下入参本身是元组,不需要加*
      WebDriverWait(self.driver,10).until(EC.visibility_of_element_located(loc))
      return self.driver.find_element(*loc)
    except:
      print u"%s 页面中未能找到 %s 元素"%(self, loc)
  
  #重写switch_frame方法
  def switch_frame(self, loc):
    return self.driver.switch_to_frame(loc)
  
  #定义script方法,用于执行js脚本,范围执行结果
  def script(self, src):
    self.driver.execute_script(src)
  
  #重写定义send_keys方法
  def send_keys(self, loc, vaule, clear_first=True, click_first=True):
    try:
      loc = getattr(self,"_%s"% loc) #getattr相当于实现self.loc
      if click_first:
        self.find_element(*loc).click()
      if clear_first:
        self.find_element(*loc).clear()
        self.find_element(*loc).send_keys(vaule)
    except AttributeError:
      print u"%s 页面中未能找到 %s 元素"%(self, loc)

2.定义登录页面的基本操作方法。

所有页面元素定位都在此层定义,UI一旦有更改,只需在修改这一层页面对象属性即可。

命名为test_8_3_2_LoginPage.py

# coding=utf-8
'''
Created on 2016-8-13
@author: Jennifer
Project:页面基本操作方法:如open,input_username,input_password,click_submit
'''
from selenium.webdriver.common.by import By
from test_8_3_2_BasePage import BasePage

#继承BasePage类
class LoginPage(BasePage):
  #定位器,通过元素属性定位元素对象
  username_loc =(By.NAME,'email')
  password_loc =(By.NAME,'password')
  submit_loc =(By.ID,'dologin')
  span_loc =(By.CSS_SELECTOR,"div.error-tt>p")
  dynpw_loc =(By.ID,"lbDynPw")
  userid_loc =(By.ID,"spnUid")
  
  #操作
  #通过继承覆盖(Overriding)方法:如果子类和父类的方法名相同,优先用子类自己的方法。
  #打开网页
  def open(self):
  #调用page中的_open打开连接
    self._open(self.base_url, self.pagetitle)
  
  #输入用户名:调用send_keys对象,输入用户名
  def input_username(self, username):
#    self.find_element(*self.username_loc).clear()
    self.find_element(*self.username_loc).send_keys(username)
  
  #输入密码:调用send_keys对象,输入密码
  def input_password(self, password):
#    self.find_element(*self.password_loc).clear()
    self.find_element(*self.password_loc).send_keys(password)
    
  #点击登录:调用send_keys对象,点击登录
  def click_submit(self):
    self.find_element(*self.submit_loc).click()
  
  #用户名或密码不合理是Tip框内容展示
  def show_span(self):
    return self.find_element(*self.span_loc).text
  
  #切换登录模式为动态密码登录(IE下有效)
  def swich_DynPw(self):
    self.find_element(*self.dynpw_loc).click()
  
  #登录成功页面中的用户ID查找
  def show_userid(self):
    return self.find_element(*self.userid_loc).text

3.使用unittest框架编写测试用例 

# coding=utf-8
'''
Created on 2016-8-13
@author: Jennifer
Project:使用unittest框架编写测试用例。
'''
import unittest 
from test_8_3_2_LoginPage import LoginPage
from selenium import webdriver

class Caselogin126mail(unittest.TestCase):
  """
     登录126邮箱的case
  """
  def setUp(self):
    self.driver = webdriver.Firefox()
    self.driver.implicitly_wait(30)
    self.url ="http://mail.126.com"
    self.username ="XXX"
    self.password ="XXX"
  
  #用例执行体
  def test_login_mail(self):
    #声明LoginPage类对象
    login_page = LoginPage(self.driver, self.url, u"网易")
    #调用打开页面组件
    login_page.open()
    #切换到登录框Frame
    login_page.switch_frame('x-URS-iframe')
    #调用用户名输入组件
    login_page.input_username(self.username)  
    #调用密码输入组件
    login_page.input_password(self.password)    
    #调用点击登录按钮组件
    login_page.click_submit()

  def tearDown(self):
    self.driver.quit()
    
if __name__ == "__main__":
  unittest.main()

结语:

这样分层的好处是,不同层关心不同的问题。页面对象层只关心元素定位问题,测试用例只关心测试的数据。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
win7安装python生成随机数代码分享
Dec 27 Python
python装饰器decorator介绍
Nov 21 Python
Python实现方便使用的级联进度信息实例
May 05 Python
Python Matplotlib库入门指南
May 18 Python
Python 中开发pattern的string模板(template) 实例详解
Apr 01 Python
python的构建工具setup.py的方法使用示例
Oct 23 Python
python3.5 tkinter实现页面跳转
Jan 30 Python
详解Python字符串切片
May 20 Python
Python帮你微信头像任意添加装饰别再@微信官方了
Sep 25 Python
python 三种方法提取pdf中的图片
Feb 07 Python
python中random模块详解
Mar 01 Python
Pytorch 如何实现常用正则化
May 27 Python
Python实现Selenium自动化Page模式
Jul 14 #Python
详解Selenium+PhantomJS+python简单实现爬虫的功能
Jul 14 #Python
python基于Selenium的web自动化框架
Jul 14 #Python
Django项目使用CircleCI的方法示例
Jul 14 #Python
Python实现最常见加密方式详解
Jul 13 #Python
python Pandas库基础分析之时间序列的处理详解
Jul 13 #Python
简单了解python反射机制的一些知识
Jul 13 #Python
You might like
smarty内置函数section的用法
2015/01/22 PHP
使用php的HTTP请求的库Requests实现美女图片墙
2015/02/22 PHP
php实现网站顶踩功能的完整前端代码
2015/07/19 PHP
php实现简单的权限管理的示例代码
2017/08/25 PHP
动态样式类封装JS代码
2009/09/02 Javascript
Array.prototype 的泛型应用分析
2010/04/30 Javascript
js判断输入是否为正整数、浮点数等数字的函数代码
2010/11/17 Javascript
jquery lazyload延迟加载技术的实现原理分析
2011/01/24 Javascript
读jQuery之五(取DOM元素)
2011/06/20 Javascript
用jQuery与JSONP轻松解决跨域访问的问题
2014/02/04 Javascript
JS实现图片放大镜效果的方法
2015/02/27 Javascript
探讨JavaScript语句的执行过程
2016/01/28 Javascript
js的form表单提交url传参数(包含+等特殊字符)的两种解决方法
2016/05/25 Javascript
基于jQuery解决ios10以上版本缩放问题
2017/11/03 jQuery
原生JavaScript实现remove()和recover()功能示例
2018/07/24 Javascript
nodejs 使用nodejs-websocket模块实现点对点实时通讯
2018/11/28 NodeJs
vue实现路由懒加载及组件懒加载的方式
2019/06/11 Javascript
对vuex中getters计算过滤操作详解
2019/11/06 Javascript
如何在selenium中使用js实现定位
2020/08/18 Javascript
SublimeText 2编译python出错的解决方法(The system cannot find the file specified)
2013/11/27 Python
python通过socket查询whois的方法
2015/07/18 Python
浅谈Python中列表生成式和生成器的区别
2015/08/03 Python
实例Python处理XML文件的方法
2015/08/31 Python
pygame游戏之旅 创建游戏窗口界面
2018/11/20 Python
对python3中, print横向输出的方法详解
2019/01/28 Python
python-itchat 获取微信群用户信息的实例
2019/02/21 Python
django的模型类管理器——数据库操作的封装详解
2020/04/01 Python
Python用5行代码实现批量抠图的示例代码
2020/04/14 Python
使用Matplotlib绘制不同颜色的带箭头的线实例
2020/04/17 Python
python如何利用paramiko执行服务器命令
2020/11/07 Python
幼儿园亲子活动方案
2014/01/29 职场文书
超市创业计划书
2014/04/24 职场文书
医德考评自我评价
2014/09/14 职场文书
2014年乡镇民政工作总结
2014/12/02 职场文书
认真学习保证书
2015/02/26 职场文书
美容院管理规章制度
2015/08/05 职场文书