写在前面:

Page Object模式,目的是将元素定位和元素操作分层,只接触测试内容,不写基础内容,便于后续对自动化测试用例体系的维护,这是中心思想,也是核心。

那么我们继续将简洁延续,这里沿用JavaPage Factory模式思想,旨在减少代码冗余,简单易用,具有高度的可扩展能力。

所以,这里我们使用基于PythonPage Factory设计模式

Page Factory的使用

作用:

  • 支持以注解的方式定义元素
  • 支持同一个元素多种定位方式
  • 支持动态的定位方式

1、安装

pip install pythium

2、使用 Page Factory 模式将页面元素分离

我们将继续沿用Page Object模式的风格,这里我又加了一层自己暂时定义叫基础层,现在就变成了四层:基础层、对象层、操作层、业务层。

下面将举例说明Page Factory设计模式,以登陆功能为例,来做进一步讲解。

3、基础层

用来存放driver及初始化使用,示例代码如下:

  1. # -*- coding: utf-8 -*-
  2. """
  3. @Time : 2022/12/5 21:07
  4. @Auth : 软件测试君
  5. @File :BasePage.py
  6. @IDE :PyCharm
  7. @Motto:ABC(Always Be Coding)
  8. """
  9. from selenium import webdriver
  10. from webdriver_manager.chrome import ChromeDriverManager
  11. from pagefactory.LoginPage import LoginPage
  12. class BasePage(object):
  13. """
  14. 用来存放driver及初始化使用
  15. """
  16. def __init__(self) -> None:
  17. """
  18. 初始化driver
  19. """
  20. self.driver = webdriver.Chrome(ChromeDriverManager().install())
  21. self.driver.maximize_window()
  22. def open_url(self, url: str) -> None:
  23. """
  24. 打开项目首页
  25. :param url:
  26. :return:
  27. """
  28. self.driver.get(url)
  29. def quit_browser(self) -> None:
  30. """
  31. 退出浏览器
  32. :return:
  33. """
  34. self.driver.quit()
  35. def get_LoginPage(self) -> LoginPage:
  36. # 返回登陆实体
  37. return LoginPage(self.driver)

4、对象层

用于存放页面元素定位和控件操作,示例代码如下:

  1. # -*- coding: utf-8 -*-
  2. """
  3. @Time : 2022/12/5 21:13
  4. @Auth : 软件测试君
  5. @File :LoginPage.py
  6. @IDE :PyCharm
  7. @Motto:ABC(Always Be Coding)
  8. """
  9. import time
  10. from pythium import find_by, Page
  11. from selenium.webdriver.remote.webelement import WebElement
  12. class LoginPage(Page):
  13. """
  14. 用于存放页面元素定位和控件操作
  15. """
  16. # 定位用户名元素
  17. @find_by(css="input[type='text']")
  18. def username_el(self) -> WebElement: ...
  19. # 定位密码元素
  20. @find_by(css="input[type='password']")
  21. def password_el(self) -> WebElement: ...
  22. # 定位登陆元素
  23. @find_by(name="submit")
  24. def loginbtn_el(self) -> WebElement: ...
  25. # 定位错误信息元素
  26. @find_by(id_="alert")
  27. def errormsg_el(self) -> WebElement: ...
  28. # 输入用户名
  29. def send_username(self, username: str):
  30. """
  31. 输入用户名
  32. :param self:
  33. :param username:
  34. :return:
  35. """
  36. self.username_el().clear()
  37. self.username_el().send_keys(username)
  38. # 输入密码
  39. def send_password(self, password: str):
  40. """
  41. 输入密码
  42. :param self:
  43. :param password:
  44. :return:
  45. """
  46. self.password_el().clear()
  47. self.password_el().send_keys(password)
  48. # 点击登陆按钮
  49. def click_loginbtn(self):
  50. """
  51. 点击登陆按钮
  52. :return:
  53. """
  54. self.loginbtn_el().click()
  55. # 获取错误信息
  56. def get_erorMsg(self) -> str:
  57. """
  58. 获取错误信息
  59. :return:
  60. """
  61. time.sleep(1)
  62. return self.errormsg_el().text

5、操作层

则是一些封装好的功能用例模块,也可以理解成我们写测试用例的步骤,示例代码如下:

  1. # -*- coding: utf-8 -*-
  2. """
  3. @Time : 2022/12/5 21:33
  4. @Auth : 软件测试君
  5. @File :LoginAction.py
  6. @IDE :PyCharm
  7. @Motto:ABC(Always Be Coding)
  8. """
  9. from pagefactory.BasePage import BasePage
  10. class LoginAction(object):
  11. """
  12. 登陆操作
  13. """
  14. def login(self, username: str, password: str):
  15. """
  16. 登陆操作
  17. :param username: 用户名
  18. :param password: 密码
  19. :return:
  20. """
  21. basepage = BasePage()
  22. basepage.open_url('http://localhost:8080/login')
  23. basepage.get_LoginPage().send_username(username)
  24. basepage.get_LoginPage().send_password(password)
  25. basepage.get_LoginPage().click_loginbtn()
  26. msg = basepage.get_LoginPage().get_erorMsg()
  27. basepage.quit_browser()
  28. return msg

6、业务层

则是我们真正的测试用例的操作部分,示例代码如下:

  1. # -*- coding: utf-8 -*-
  2. """
  3. @Time : 2022/12/5 21:40
  4. @Auth : 软件测试君
  5. @File :TestLogin.py
  6. @IDE :PyCharm
  7. @Motto:ABC(Always Be Coding)
  8. """
  9. import unittest
  10. from pagefactory.LoginAction import LoginAction
  11. class TestLogin(unittest.TestCase):
  12. """
  13. 测试登陆功能
  14. """
  15. def test_login(self):
  16. msg = LoginAction().login("1", "1")
  17. self.assertEquals(msg, "用户名或密码错误!")

从以上代码看,如果页面元素发生变化,我们在对应类里修改对应元素即可,而操作和业务层流程类及用例都不用改,如果仅是业务流程更改,只需要维护业务层流程类业务脚本,其他几个类都不用改,从而做到了很好的将页面、元素、脚本进行了分离。

至此,关于Page Factory的使用分享完毕,有兴趣的同学可以自行拓展。

写在最后

又有很久没有更文了,因为一直都是996工作制,很难有时间去写文章,这里还请各位粉丝朋友理解,不过,我会努力持续更文。

我是六哥,如果觉得文章对您有帮助,请继续关注我,原创不易,不求打赏,只求转发!

Selenium4+Python3系列(十一) - Page Factory设计模式的更多相关文章

  1. Selenium4+Python3系列(五) - 多窗口处理之句柄切换

    写在前面 感觉到很惭愧呀,因为居然在Selenium+Java系列中没有写过多窗口处理及句柄切换的文章,不过也无妨,不管什么语言,其思路是一样的,下面我们来演示,使用python语言来实现窗口句柄的切 ...

  2. Selenium4+Python3系列(六) - Selenium的三种等待,强制等待、隐式等待、显式等待

    为什么要设置元素等待 直白点说,怕报错,哈哈哈! 肯定有人会说,这也有点太直白了吧. 用一句通俗易懂的话就是:等待元素已被加载完全之后,再去定位该元素,就不会出现定位失败的报错了. 如何避免元素未加载 ...

  3. SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案

    原文:SQL Server 2008空间数据应用系列十一:提取MapInfo地图数据中的空间数据解决方案 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Serv ...

  4. Page Object设计模式(项目整体结构)

    1. 什么是框架 1.1 定义: 框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件(类)及构件(类)实例间交互的方法. 1.2 为什么要搭建自动化测试框架 自动化测试的开发, ...

  5. selenium page object & Page Factory

    package demo; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa ...

  6. java基础解析系列(十一)---equals、==和hashcode方法

    java基础解析系列(十一)---equals.==和hashcode方法 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系 ...

  7. Page Object设计模式实践

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

  8. Python3 系列之 基础语法篇

    基础数据类型 整数 python 可以处理任意大小的整数 浮点数 python 可以处理任意大小的浮点数,但是需要注意的一点是:整数运算永远是精确的(除法也是精确的),而浮点数运算则可能会有四舍五入的 ...

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

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

  10. struts2官方 中文教程 系列十一:使用XML进行表单验证

    在本教程中,我们将讨论如何使用Struts 2的XML验证方法来验证表单字段中用户的输入.在前面的教程中,我们讨论了在Action类中使用validate方法验证用户的输入.使用单独的XML验证文件让 ...

随机推荐

  1. Elasticsearch官方文档离线访问实操指南

    文章转载自:https://mp.weixin.qq.com/s/Cn9ddkj-cne5pKtfOgNPbg 延申一下,不仅能下载Elasticsearch官方文档,还能下载其他软件的官方文档,详看 ...

  2. 4_爬NMPA药监总局_动态加载_传ID

    http://scxk.nmpa.gov.cn:81/xk/ import requests url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAc ...

  3. java基础二、类与继承

    员工类 Employee, 经理类:Manager public class Employee { private String name; private double salary; privat ...

  4. day03-MySQL基础知识02

    MySQL基础知识02 4.CRUD 数据库CRUD语句:增(create).删(delete).改(update).查(Retrieve) Insert 语句 (添加数据) Update 语句(更新 ...

  5. Tableau Server 常用命令

    Tableau Server 常用命令 1> 停止tableau server服务 tabadmin stop 2> 恢复tableau server数据 tabadmin restore ...

  6. 集合元素的遍历操作,使用迭代器Iterator接口

    1.内部的方法:hasNext() 和 next() 推荐的方式: //hasNext():判断是否还有下一个元素while(iterator.hasNext()){ //next():①指针下移 ② ...

  7. 算法设计(动态规划实验报告) 基于动态规划的背包问题、Warshall算法和Floyd算法

    一.名称 动态规划法应用 二.目的 1.掌握动态规划法的基本思想: 2.学会运用动态规划法解决实际设计应用中碰到的问题. 三.要求 1.基于动态规划法思想解决背包问题(递归或自底向上的实现均可): 2 ...

  8. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(29)-Fiddler如何抓取Android7.0以上的Https包-终篇

    1.简介 上一篇宏哥介绍的Xposed是一款可以在不修改APK的情况下影响程序运行的框架.可以编写并加载自己编写的插件app,实现对目标apk的注入.拦截等.一般研究移动安全的都会使用Xposed. ...

  9. 《Java并发编程的艺术》读书笔记:一、并发编程的目的与挑战

    发现自己有很多读书笔记了,但是一直都是自己闷头背,没有输出,突然想起还有博客圆这么个好平台给我留着位置,可不能荒废了. 此文读的书是<Jvava并发编程的艺术>,方腾飞等著,非常经典的一本 ...

  10. go-zero docker-compose搭建课件服务(四):生成Dockerfile

    0.转载 go-zero docker-compose 搭建课件服务(四):生成Dockerfile并在docker-compose中启动 0.1源码地址 https://github.com/liu ...