一、PO模型

1、PO介绍:page(页面) object(对象)

在自动化中,Selenium 自动化测试中有一个名字经常被提及 PageObject (思想与面向对象的特征相同),通常PO 模型可以大大提高测试用例的维护效率。

优点:

提交测试脚本可读性

减少代码重复

提高测试用例的可维护性,特别是针对UI变动频繁的项目

缺点:

结构复杂:基于流程进行了模块化的拆分

结构:

  1. base(基类)
  2. page(页面对象)
  3. scripts(业务层)

扩展:

loc 变量:类型为元组:*loc为解包

2、PageObject 设计模式

3、PO 的核心要素

  1. 在 PO 模式中抽离封装集成一个 BasePage 类,该基类应该拥有一个只实现 webdriver 实例的属性

  2. 每一个page 都继承BasePage,通过 driver 来管理 page 中元素,将 page 中的操作封装成一个个方法

  3. TestCase 继承 unittest.TestCase类,并依赖page类,从而实现相应的测试步骤

二、将Selenium代码封装成PO模型

1、案例说明(简单的登录测试用例)

(1)改造案例思路:

  • 第一, 我们要分离测试对象(元素对象)和测试脚本(用例脚本),那么我们分别创建两个脚本文件,分别为:

    • LoginPage.py 用于定义页面元素对象,每一个元素都封装成组件(可以看做存放页面元素对象的仓库)
    • TestCaseLogin.py 测试用例脚本。
  • 第二,抽取出公共方法定义在base.py文件中,每个Page类都要继承这个base.py文件,也就是每Page类都能使用base类中的方法,来操作页面中的元素,同时也可以在每个Page类中定义自己独有的方法,解决工作中的实际需求。
  • 第三,设计实现思想,一切元素和元素的操作组件化定义在Page页面,用例脚本页面,通过调用Page中的组件对象,进行拼凑成一个登录脚本。

(2)封装公共操作在base类(base.py)

把一些公共的方法放到此类中,这个类将被PO对象继承。

from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait class Base(object): def __init__(self, driver):
self.driver = driver # 查找元素方法(提供:点击、输入、获取文本)使用
def base_find_element(self, loc, timeout=30, poll=0.5):
element, index = loc[:2], loc[-1]
try:
ele = WebDriverWait(
self.driver, timeout=timeout, poll_frequency=poll
).until(
lambda x: x.find_elements(*element)
)[index]
except (NoSuchElementException, TimeoutError, IndexError):
return False
else:
return ele # 点击方法
def base_click(self, loc):
self.base_find_element(loc).click() # 输入方法
def base_input(self, loc, value):
el = self.base_find_element(loc)
# 清空
el.clear()
# 输入
el.send_keys(value) # 获取文本方法
def base_get_text(self, loc):
return self.base_find_element(loc).text # 获取当前页面地址
def base_get_current_url(self):
return self.driver.current_url # 鼠标悬停事件
def base_move_to_element(self, loc):
ActionChains(self.driver).move_to_element(loc).perform()

(3)每个页面对应一个Page类(login_page.py)

定位元素的定位器和操作元素方法分离开,元素定位器全部放一起,然后每一个操作元素动作写成一个方法。

from selenium.webdriver.common.by import By
from public.base import Base login_username = (By.CLASS_NAME, 'el-input__inner', 1)
login_password = (By.CLASS_NAME, 'el-input__inner', 2)
login_btn = (By.CLASS_NAME, 'login__button', 0)
organ_name = (By.CSS_SELECTOR, '.role-names-button', 0)
logout_btn = (By.CLASS_NAME, 'logout', 0)
password_login_text = (By.CSS_SELECTOR, '.pwd-login', 0) class LoginPage(object): def __init__(self, driver):
self.element = Base(driver) # 输入手机号
def input_username(self, content):
self.element.base_input(login_username, content) # 输入密码
def input_password(self, content):
self.element.base_input(login_password, content) # 点击登录
def click_login_button(self):
self.element.base_click(login_btn) # 获取当前页面url
def get_current_url(self):
return self.element.base_get_current_url() # 点击机构名称
def click_to_organ_name(self):
self.element.base_click(organ_name) # 点击退出
def click_logout(self):
self.element.base_click(logout_btn) # 获取“密码登录”文字
def get_password_login_text(self):
return self.element.base_get_text(password_login_text)

(4)封装业务层(login_business.py)

import time

from Test.Page.login_page import *

class LoginBusiness(object):

    def __init__(self, driver):
self.login_business = LoginPage(driver) # 登录系统
def go_system(self, username, password):
self.login_business.input_username(username)
self.login_business.input_password(password)
self.login_business.click_login_button()
time.sleep(2)
return self.login_business.get_current_url() # 退出成功
def logout(self):
self.login_business.click_to_organ_name()
self.login_business.click_logout()
return self.login_business.get_password_login_text()

(4)原登陆案例封装完成代码

测试方法及测试类的执行都在此文件中。

from Test.Case.base_case import LoginBaseCase
from public.get_log import LogInfo
from public.read_ini import get_value
from Test.Business.login_business import LoginBusiness class TestLogin(LoginBaseCase, LogInfo):
""" 登录退出测试用例 """ @classmethod
def setUpClass(cls) -> None:
cls.case_forward()
LogInfo().log.info('TestLogin Cases Suite Start Running')
cls.login = LoginBusiness(cls.driver) @LogInfo.get_error
def test_1(self):
""" 登录流程 """
self.log.info('TestCase1 Start Running')
# 获取用户名密码
username = get_value(get_value('Base', 'Env'), 'username')
password = get_value(get_value('Base', 'Env'), 'password')
url = self.login.go_system(username, password)
text = "https://gssdev.haoshengy.com/pc_workbench/workbench/overview"
self.assertEqual(url, text, '当前页面URL不正确--测试不通过') def test_2(self):
""" 退出登录 """
self.log.info('TestCase2 Start Running')
text = self.login.logout()
self.assertEqual("密码登录", text, '首页密码登录字样错误--测试不通过')

三、数据驱动

1.1 什么是数据驱动

数据驱动:是以数据来驱动整个测试用例的执行,也就是测试数据决定测试结果

1.2 数据驱动的特点
  1. 数据驱动本身不是一个工业级标砖的概念,因此在不同的公司都会有不同的解释
  2. 可以把数据驱动理解成一种模式或者一种思想
  3. 数据驱动技术可以让用户把关注点放在测试数据的构建和维护上,而不是直接维护脚本,可以利用同样的过程对不同的数据输入进行测试
  4. 数据驱动的实现要依赖参数化的技术
1.3 传入数据的方式(测试数据的来源)
  1. 直接定义在测试脚本中(简单直观,但代码和数据未实现真正的分离,不方便后期维护)
  2. 从文件读取数据,如json、Excel、xml、txt、等格式文件
  3. 从数据库中读取数据
  4. 直接调用接口获取数据源
  5. 本地封装一些生成数据的方法

UI自动化学习笔记- PO模型介绍和使用的更多相关文章

  1. UI自动化学习笔记- UnitTest单元测试框架详解

    一.UnitTest基本使用 1. UnitTest框架 1.1 什么是框架 说明: 框架英文单词frame 为解决一类事情的功能集合 1.2什么是UnitTest框架 概念:UnitTest是pyt ...

  2. UI自动化学习笔记- Selenium一些特殊操作的处理

    一.特殊操作处理 1. 下拉选择框操作 1.1 如何操作下拉选择框 实现方式一 思路:先定位到要操作的option元素,然后执行点击操作 driver.find_element_by_css_sele ...

  3. UI自动化学习笔记- Selenium元素定位及元素操作

    一.元素定位 1. 如何进行元素定位? 元素定位就是通过元素的信息或元素层级结构来定位元素的 2.定位工具 浏览器开发者工具 3.元素定位方式 Selenium提供了八种定位元素方式 id name ...

  4. UI自动化学习笔记- Selenium元素等待(强制等待、显示等待、隐式等待)

    一.元素等待 1. 元素等待 1.1 什么是元素等待 概念:在定位页面元素时如果未找到,会在指定时间内一直等待的过程 意思就是:等待指定元素已被加载出来之后,我们才去定位该元素,就不会出现定位失败的现 ...

  5. UI自动化学习笔记- 日志相关操作

    一.日志相关 1.日志 概念:日志就是用于记录系统运行时的信息,对一个事件的记录,也称log 1.1 日志的作用 调试程序 了解系统程序运行的情况,是否正常 系统程序运行故障分析与问题定位 用来做用户 ...

  6. Android自动化学习笔记之MonkeyRunner:官方介绍和简单实例

    ---------------------------------------------------------------------------------------------------- ...

  7. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  8. ArcGIS案例学习笔记2_2_模型构建器和山顶点提取批处理

    ArcGIS案例学习笔记2_2_模型构建器和山顶点提取批处理 计划时间:第二天下午 背景:数据量大,工程大 目的:自动化,批处理,定制业务流程,不写程序 教程:Pdf/343 数据:chap8/ex5 ...

  9. UI设计学习笔记(7-12)

    UI学习笔记(7)--扁平化图标 认识扁平化 Flat Design 抛弃传统的渐变.阴影.高光等拟真视觉效果,打造看上去更平的界面.(颜色.形状) 扁平化图标有什么优缺点 优点: 简约不简单.有新鲜 ...

随机推荐

  1. NVIDIA Turing Architecture架构设计(上)

    NVIDIA Turing Architecture架构设计(上) 在游戏市场持续增长和对更好的 3D 图形的永不满足的需求的推动下, NVIDIA 已经将 GPU 发展成为许多计算密集型应用的世界领 ...

  2. 深度学习Anchor Boxes原理与实战技术

    深度学习Anchor Boxes原理与实战技术 目标检测算法通常对输入图像中的大量区域进行采样,判断这些区域是否包含感兴趣的目标,并调整这些区域的边缘,以便更准确地预测目标的地面真实边界框.不同的模型 ...

  3. C语言代码区错误以及编译过程

    C语言代码区错误 欲想了解C语言代码段会有如何错误,我们必须首先了解编译器是如何把C语言文本信息编译成为可以执行的机器码的. 背景介绍 测试使用的C语言代码 导入标准库,定义宏变量,定义结构体,重命名 ...

  4. 【Java实现】剑指offer53.1——在排序数组中查找数字(LeetCode34:在排序数组中查找元素的起始位置)

    序数组中查找元素的起始位置):思路分享 <剑指offer>题目和LeetCode主站本质是一样的,想要找到target数目,也需要找到左右边界 题目解析: 在一个排序数组中,找到targe ...

  5. Scala语言笔记 - 第三篇(容器方法篇)

    Scala语言笔记 - 第三篇(容器方法篇) 目录 Scala语言笔记 - 第三篇(容器方法篇) map和flapMap方法: ​ 最近研究了下scala语言,这个语言最强大的就是它强大的函数式编程( ...

  6. 循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示

    在BootstrapVue组件库里面,提供了很多对Bootstrap同等类似的组件封装,其中图片轮播可以采用b-carousel-slide组件实现,而有一些小的图片,如客户/合作伙伴Logo或者友情 ...

  7. .Net Core with 微服务 - Elastic APM

    上一次我们介绍了Seq日志聚合组件.这次要给大家介绍的是Elastic APM ,一款应用程序性能监控组件.APM 监控围绕对应用.服务.容器的健康监控,对接口的调用链.性能进行监控.在我们实施微服务 ...

  8. CosId 1.0.0 发布,通用、灵活、高性能的分布式 ID 生成器

    CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...

  9. Mongo3基础操作

    由于3.X的文档是在3.X当前最新版本前记录,所以这里列出一些常用的操作,比如建立库,删除库,等一些格式,然后在描述开启远程和创建用户的一些区别,以及讲解2.X和3.X配置文件区别. 1. Mongo ...

  10. layui comfirm 监听点击确定、取消、“X”关闭按钮

    layer.confirm('数据已存在,是否继续', { offset: '200px' , cancel: function (index, layero) { console.log('点击X按 ...