1. 什么是框架

  1.1 定义:

  框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件(类)及构件(类)实例间交互的方法。

  1.2 为什么要搭建自动化测试框架

    自动化测试的开发,通常是由自动化测试的需求决定的。这个需求主要包括:

    • 自动化测试更便于实施
    • 解决自动化测试脚本本身存在的问题,如异常处理和场景恢复。
    • 测试易于维护。好的框架,可以减少你在管理维护中所投入的人力物力精力。
    • 可重用性。框架的意义之一就在于可重用吧。所以在框架里,你可以实现一些通用功能,简化脚本开发过程。      
    • 美观易读的测试报告。拿Selenium来说,它产出的测试报告只是基于测试脚本的,并没有那种基于测试集的报告,所以如果你要,测试框架里可以实现。

  1.3 自动化测试框架

(1)定义:是一个集成体系,在这一体系中包含测试功能的函数库、测试数据源、测试对象识别标准,以及种可重用的模块。

(2)经历阶段 自动化测试框架在发展的过程中经历了几个阶段,模块驱动测试、数据驱动测试、对象驱动测试。

  2. 什么是设计模式?

  2.1 定义

设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

  2.2使用设计模式

  是为了重用代码、让代码更容易被他人理解、保证代码可靠性。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。

  参见网站:http://www.runoob.com/design-pattern/design-pattern-tutorial.html

  3. Page Object Model设计模式

  3.1 定义

  对于简单的Selenium自动化测试,我们要做的不过是找到页面元素,并且值传递给这些元素。但是假如有10个脚本同时调用了一个相同的页面元素,当这个元素发生改变,我们需要修改10个脚本。随着脚本数的增加,时间工作复杂度也飞速增长。这个时候我们就可以考虑设计一个类,专门用来页面元素的查找、传递值和修正。这样,当一个页面元素发生改变的时候,只用修改一个类,而不用同时修改10个脚本。 

  Page Object是一种程序设计模式,将面向过程转变为面向对象(页面对象),将测试对象(按钮、输入框、标题等)及单个的测试步骤封装在每个Page对象中,以page为单位进行管理。

  这样,在Selenium测试页面中可以通过调用页面类来获取页面元素,从而巧妙的避免了当页面元素id或者位置变化时,需要改测试页面代码的情况。当页面元素id变化时,只需要更改测试页Class中页面的属性即可。可以使代码复用,降低维护成本,提高程序可读性和编写效率。

  3.2 优点

  • 以页面为单位,集中管理元素对象和方法。当页面元素或流程变动时只需要修改相关页面方法即可,不需要修改相应脚本
  • 编写脚本简单,顺着业务逻辑写脚本。page object模式以业务逻辑上的每一步操作作为区分点,页面方法代表了此页面的一个业务操作并严格控制此操作的后续流程
  • 后期维护方便

  3.3 Page Factory

Page Factory是一个很好的设计Object repository的模式,以此来实现Selenium WebDriver中的POM概念。

  4. Page Object的对象

  4.1 Page模式:

  1. 抽象出一个BasePage基类,包含一个指向selenium.webdriver的属性

2. 每一个webpage都继承BasePage,通过driver来获取本页面的元素,每个页面的操作都抽象为一个个方法

3. TestCase继承unnitest.TestCase类,并依赖相应的Page类来实现相应的test case步骤

4.2 PO对象以及整个项目结构

  • data

    • 存放公共数据,例如用户名和密码
  • Public

    • 设计全局方法和变量

  例如:设计一个可以代表项目所在根目录的全局变量

 # coding = utf-8
import os
class global_value():
# 1. 项目所在的根目录
def get_project_dir():
try:
project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print("The project_dir is :", project_dir)
return project_dir
except:
print("Cannot find the project directory") PROJECT_DIR = get_project_dir()

  如果在其他类中需要这个全局变量,则需要先导入该类,例如在run_test中导入

 from public import GlobalValue
project_dir = GlobalValue.global_value.PROJECT_DIR
  • report

    • 存放报告
  • Page 基类(BasePage)

    • 设计了一个基本的Page类,以便所有的页面进行继承,该类标明了一个sub page类的基本功能和公共的功能。
 # coding utf-8
"""
@ author: 宋博文
封装所有的功用方法,例如driver, url, FindElement
"""
from selenium import webdriver
import time
import os
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
from public import GlobalValue
project_dir = GlobalValue.global_value.PROJECT_DIR class base_page(): # 初始化driver、url、pagetitle等
# 实例化BasePage类时,最先执行的就是__init__方法,该方法的入参,其实就是BasePage类的入参。
# __init__方法不能有返回值,只能返回None
# self指实例本身,相较于类-Page而言。 """
构造方法
:param driver: 封装好的webdriver
:param base_url: 基本url:"http://www.pzcnet.com/"
:param PROJECT_DIR: 项目所在目录
"""
def __init__(self):
"""
# 定义driver和base_url
"""
driver = webdriver.Firefox()
try:
self.driver = driver
except Exception:
raise NameError("Firefox Not Found!") self.base_url = "http://www.pzcnet.com/" def captureScreenshot(self, filename):
# 截取屏幕截图并保存到指定路径
try:
self.driver.get_screenshot_as_file(filename)
except BaseException as e:
print('保存屏幕截图失败,失败信息:' + e) def operationCheck(self, Name, isSucceed):
'''
判断运行是否成功:
1、若成功,输出运行成功;
2、若不成功,则对失败页面进行屏幕截图,并保存:
(1)保存路径为'screenshot'--day_now--Name_time_now.png;
(2)保存前先判断'screenshot'文件夹下是否存在day_now文件夹,若不存在,则先新建'day_now'文件夹
(3)保存的文件名为 “所检查的操作名Name”_“所检查的时间time_now”.png
'''
# 判断运行是否成功
if isSucceed:
print(Name + u":运行成功!") else:
day_now = time.strftime("%Y%m%d", time.localtime(time.time()))
time_now = time.strftime("%H%M%S", time.localtime(time.time()))
path = os.path.join(project_dir, 'screenshot', day_now)
if not os.path.exists(path):
os.mkdir(path)
png_path = os.path.join(path, Name + "_" + time_now + '.png')
self.captureScreenshot(png_path)
print(Name + u":运行失败!请查看截图快照:" + png_path)
self.driver.quit() def openPage(self, url):
"""
打开页面,通过拼接URL的方式
:param url:
:return:
"""
  • Sub Pages(s)子类

    • 具体的页面的类,定义了某个具体的页面的功能。

例如:在盘中餐网站中实现消费者的登录,主要功能未:消费者输入用户名-密码-验证码-点击“登录”-跳转到订餐首页

1. 引入BasePage中的所有基本方法
 from pages import BasePage
  2. 根据该页面的具体功能设计方法,例如消费者登录页面(CustomerLogin.py)
 class customer_login(BasePage.base_page):
def __init__(self):
BasePage.base_page.__init__(self)
self.customer_login_page_url = 'customer/toLogin'
self.order_main_page_url = 'customer/toIndex' def customer_account_login(self, user_name, user_password, captcha):
self.openPage(self.customer_login_page_url)
self.sendkeys("id,login-username", user_name)
self.sendkeys("id,login-password", user_password)
self.sendkeys("id,checkCode",captcha)
self.click("name,commit") def get_orderMainPage(self):
return self.base_url + self.order_main_page_url

  

  • Tests 类

    • 这部分描述的是具体的测试用例。
    • 一个页面对应一个测试用例
    • 测试用例都以test_开头,因为在使用unittest.main()时,默认会执行所有以test开头的测试用例

例如:对于消费者登录页面(CustomerLogin.py)对应一个测试用例(test_CustomerLogin.py)

1. 继承对应页面(CustomerLogin.py)中所有的方法
 from pages import CustomerLogin
2. 声明一个操作员operator,用操作员来调用BasePage中的方法
 # coding = utf-8

 import unittest
from pages import CustomerLogin class CustomerLoginTest(unittest.TestCase): #在用例类中,只需要声明一个操作员(operator),用操作员来调用basepage类中的方法便可
def setUp(self):
self.operator = CustomerLogin.customer_login() def test_customer_account_login(self):
u"""消费者登录"""
operator = self.operator
user_name = "xxxx"
user_password = "xxxx"
captcha = "xxxx"
operator.customer_account_login(user_name, user_password, captcha)
operator.get_orderMainPage() def tearDown(self):
pass if __name__ == "__main__":
unittest.main()
  • run_test 执行所用用例

  1. 引入全局变量或方法:
 from public import GlobalValue
project_dir = GlobalValue.global_value.PROJECT_DIR
testcase_dir = project_dir + "\\testcase"
  2. 将测试目录testcase添加到系统的path
 import sys
sys.path.append(testcase_dir)
  3. 定义Test Suite
    • 用discover()方法找到testcase下面所有的测试用例
    • 将discover筛选出的测试用例,循环添加到测试套件中
 import unittest
import HTMLTestRunner
import time def create_suite(): test_unit = unittest.TestSuite() # 1. discover()方法定义,找到testcase目录下面所有的用例
# TestLoader:测试用例加载器,包含多个加载测试用例的方法,返回一个测试套件
# 其中的discover方法:discover(start_dir,pattern='test*.py',top_level_dir=None
# 到指定目录下所有测试模块,并可递归查到子目录下的测试模块,只有匹配到文件名才能被加载
discover = unittest.defaultTestLoader.discover(
testcase_dir,
pattern='test_*.py',
# top_level_dir=None
) # 2. 将discover筛选出的用例,循环添加到测试套件中
for test_suit in discover:
for test_case in test_suit:
test_unit.addTest(test_case)
print(test_unit)
return test_unit
  4. 生成HTML测试报告,(并通过邮件发送到指定邮箱——暂未实现)
 # 创建测试报告文件
def run_and_generate_report(test_object):
now = time.strftime('%Y-%m-%d_%H_M_S', time.localtime(time.time()))
filename = project_dir + "\\report\\" + now + 'report.html'
fp = open(filename,'wb') runner = HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='测试报告',
description='用例执行情况:'
)
  5. 定义测试的主入口
    • 定义测试的主要入口类,代码的入口
 all_testSuit_names = create_suite()
run_and_generate_report(all_testSuit_names)
 

Page Object设计模式(项目整体结构)的更多相关文章

  1. Page Object 设计模式介绍

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

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

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

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

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

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

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

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

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

  6. 18、Page Object 设计模式

    Page Object 设计模式的优点如下: 减少代码的重复. 提高测试用例的可读性. 提高测试用例的可维护性, 特别是针对 UI 频繁变化的项目. 当你针对网页编写测试时,你需要引用该网页中的元素, ...

  7. Page Object设计模式(一)

    一.简介 主要特点体现在“对界面交互细节的封装”上,使测试用例更专注于业务的操作,从而提高测试用例的可维护性.解决UI变动问题. page对象的一个基本原则经验法则是:凡是人能做的事,page对象通过 ...

  8. Page Object设计模式实践

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

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

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

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

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

随机推荐

  1. 2019 Java面试题

    马上又是一个金九银十的招聘旺季,小编在这里给大家整理了一套各大互联网公司面试都喜欢问的一些问题或者一些出场率很高的Java面试题,给在校招或者社招路上的你一臂之力. 首先我们需要明白一个事实,招聘的一 ...

  2. sqlserver查询表字段描述(转)

    原文地址:https://blog.csdn.net/changhong009/article/details/29587063 --快速查看表结构(比较全面的) SELECT CASE WHEN c ...

  3. 【转】Dom节点操作常用方法

    1.访问/获取节点 document.getElementById(id); //返回对拥有指定id的第一个对象进行访问 document.getElementsByName(name); //返回带 ...

  4. 【转】OkHttp使用进阶 译自OkHttp Github官方教程

    作者:GavinCT 出处:http://www.cnblogs.com/ct2011/ 英文版原版地址 Recipes · square/okhttp Wiki 同步get 下载一个文件,打印他的响 ...

  5. easyui汉化啊!

    <script type="text/javascript" src="__PUBLIC__/jquery-easyui-1.4.4/locale/easyui-l ...

  6. ActiveMQ相关:

    MQ连接字符串:failover:tcp://127.0.0.1:61616 管理地址:http://localhost:8161/admin/

  7. codeforces之始

    很早就听说acmer界的CF嘞!还记得刚开始听到神犇们在讨论CF的时候我还以为是网游CF(穿越火线)呢... 今年刚开学的时候就打算开始打cf的,由于一些事情耽搁了.之后又要准备省赛所以就一直拖到现在 ...

  8. 【创客+】偷心锁屏创始人Jerry创业心得分享

    偷心锁屏创始人Jerry创业心得分享 作者:Jerry权泉,偷心锁屏创始人 我创业的起因非常偶然.08年在东京早稻田大学读博士期间,每周六都去社区活动中心跟日本人志愿者日语对话练习日语.有一次练习结束 ...

  9. Jmeter对HTTP请求压力测试、并发测试

    最近公司需要开发一个简单的报名系统,供外网用户提供报名服务,由于我们公司是个初创的微型公司,开发人员都是刚毕业不久,开发经验相当缺乏. 对于服务器性能测试这块的经验更是少得可以忽略.迫使不得不让我们去 ...

  10. arcgis api for silverlight 3.1 更新说明

    前言: 查看arcgis sl api 老版本帮助的方式:http://resources.arcgis.com/en/help/silverlight-api/3.0/xxxxxxx 新版本的帮助默 ...