PO模式项目实战思路分析

PO模式学习思路

采用版本迭代的方式来学习, 便于对不同版本的优缺点进行对比和理解
        V1: 不使用任何设计模式和单元测试框架(线性模型)
        V2: 采用测试框架,使用UnitTest管理用例
        V3: 业务代码和页面对象进行分离,使用方法封装的思想, 对代码进行优化
        V4: 实际中的PO模式编写,PO模式深入封装, 把共同操作提取封装到父类中,
                 子类直接调用父类的方法

选择的测试用例

对项目的登录模块进行自动化测试

账号不存在
1. 点击首页的‘登录’链接, 进入登录页面
2. 输入一个不存在的用户名
3. 输入密码
4. 输入验证码
5. 点击登录按钮
6. 获取错误提示信息

密码错误
1. 点击首页的‘登录’链接, 进入登录页面
2. 输入用户名
3. 输入一个错误的密码
4. 输入验证码
5. 点击登录按钮
6. 获取错误提示信息

V1版本

不使用任何设计模式和单元测试框架。
每个文件里编写一个用例, 完全的面向过程的编程方式。

存在的问题

  • 一条测试用例对应一个文件, 用例较多时不方便管理维护
  • 代码高度冗余

 V2版本

使用UnitTest管理用例, 并断言用例的执行结果

引入UnitTest的好处

  • 方便组织、 管理多个测试用例
  • 提供了丰富的断言方法
  • 方便生成测试报告
  • 减少了代码冗余

存在的问题

  • 代码冗余
  • 页面操作和元素操作都在同一个文件,维护成本高

V3版本

使用方法封装的思想, 对代码进行优化。

  • 定义获取驱动对象的工具类
  • 封装“获取弹出框的提示消息”

方法封装

方法封装: 是将一些有共性的或多次被使用的代码提取到一个方法中, 供其他地方调用。

封装的好处:

  • 避免代码冗余
  • 容易维护
  • 隐藏代码实现的细节

目的: 用最少的代码实现最多的功能

PO介绍

存在的问题

在做UI自动化时定位元素特别依赖页面, 一旦页面发生变更就不得不跟着去修改定位元素的代码。

举例: 假设要对一个元素进行点击操作, 而且会经常对该元素进行操作, 那么你就可能会编写多处如下代码
        driver.find_element_by_id("login-btn").click()

存在的问题:

  • 如果开发人员修改了这个元素的id, 这时候你就不得不修改所有对应的代码
  • 存在大量冗余代码

PO模式

PO是Page Object的缩写, PO模式是自动化测试项目开发实践的最佳设计模式之一

核心思想是通过对界面元素的封装减少冗余代码, 同时在后期维护中, 若元素定位发生变化, 只需要调整页面元素封装的代码, 提高测试用例的可维护性、 可读性。

PO模式可以把一个页面分为三层, 对象库层、 操作层、 业务层。

  • 对象库层: 封装定位元素的方法
  • 操作层: 封装对元素的操作
  • 业务层: 将一个或多个操作组合起来完成一个业务功能。 比如登录: 需要输入帐号、 密码、 点击登录三个操作

引入PO模式的好处

引入PO模式前

  • 存在大量冗余代码
  • 业务流程不清晰
  • 后期维护成本大

引入PO模式后

  • 减少冗余代码
  • 业务代码和测试代码被分开, 降低耦合性
  • 维护成本低

V4版本

采用PO模式的分层思想对代码进行拆分

1、base(基类):page页面一些公共的方法

  • 初始化方法
  • 查找元素方法
  • 点击元素方法
  • 输入方法
  • 获取文本方法
  • 截图方法 

注:

  • 以上方法封装的时候,解包只需一次,在查找元素解包
  • driver为虚拟,谁调用base时,谁传入,无需关注从哪里来 

2、page(页面对象):一个页面封装成一个对象--继承base

  • page包下面的__init__.py存放基本的配置数据,
  • page_login.py直接导包即可以通过page.来使用
  • 或者导包之后通过继承的的方法在类里面直接通过self.调用

3、scrips(业务层):导包调用page页面 

初始化方法    setUp()  注:在unittest框架中不能使用def __init__()初始化方法;

  • 实例化页面对象
  • 前置操作  如:打开等等

结束方法    teardown()

  • 关闭驱动

测试方法

  • 根据要操作的业务来实现 

拓展:元组解包

loc变量为元组,*loc为解包

from selenium.webdriver.common.by import By
driver = None
# loc = (By.CSS_SELECTOR, ".telA")
loc = By.CSS_SELECTOR, ".telA"
# driver.find_element(By.CSS_SELECTOR, ".telA")
print(type(loc))
print("未解包之前:", loc)
print("解包之后:", *loc)

运行结果:解包之后,单引号被去掉了 

  

# 查找元素方法
    def base_find_element(self, loc, timeout=30, poll=0.5):
        # 使用显示等待
        """
        :param loc: 元素的配置信息,格式为元组 如:login_link = By.PartialLink, "登录"
        :param timeout: 默认超时时间为30,可以通过传入参数进行修改
        :param poll: 默认访问频率 0.5秒
        :return: 查找到的元素
        """
        return WebDriverWait(self.driver,
                             timeout=timeout,
                             poll_frequency=poll).until(lambda x: x.find_element(*loc))
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值