POM设计模式思路,详解POM:概述与介绍,POM思路梳理+代码示例(全)

概述

在UI自动化测试中,POM模式是一种设计思路 ,它的核心思想是方法的封装 。它将方法类和页面元素进行分离,增强了代码的可维护性。值得注意的是,这种分层的设计模式,最好也是从线性代码开始,逐步将代码进行升级,最后形成以POM设计思路为核心的自动化测试框架。

思路梳理

版本升级思路

  1. V1(不使用任何设计模式和单元测试框架)
  2. V2(使用PyTest管理用例)
  3. V3(使用方法封装的思想,对代码进行优化。)
  4. V4(引入POM设计思路,也就是对象层、操作层、业务层,将方法类和页面元素进行分离)

编写思路梳理

技术架构:python+selenium+pytest+allure

思路和步骤

  1. 搭建测试环境,配置pycharm以及python环境并进行验证。
  2. 安装所需的测试依赖包
  3. 进行代码编写:首先导入我需要的包。例如selenium、pytest、sleep等必需的工具包。其次,在编写的过程中,需要使用定位方法,例如xpath等合适的方法对登录框和密码框、登陆按钮进行定位。之后使用sendkey等方法进行网页操作。最后使用assert进行断言。
  4. 代码运行成功后,需要对代码进行持续的升级,以及优化。例如,方法的封装、调用,以及页面元素的封装以及调用等,直到形成测试框架的初始形态,对于登录页功能来讲,代码量较少,较易理解。
  5. 框架形成后,需要对框架进行持续升级和优化,因为页面元素在变化、项目也在不断迭代,因此测试框架需要持续升级才能适应项目的更新迭代,特别是对于敏捷测试来讲。

代码示例

方法封装,封装基类,也叫关键字
python 复制代码
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait


# 工具类
class WebKeys:
    # 构造方法,用于接受driver对象
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(self.driver, 5)

    # 打开浏览器
    def open(self, url):
        self.driver.get(url)
        self.wait.until(ec.url_contains(url))

    # 元素定位
    def locator(self, name, value):
        el = self.driver.find_element(name, value)
        # 将元素的所在框标记出来
        self.locator_station(el)
        return el

    # 定位+显示等待
    def locator_with_wait(self, name, value):
        """元素的定位+显示等待"""
        locator = (name, value)
        self.wait.until(ec.visibility_of_element_located(locator))
        el = self.driver.find_element(name, value)
        # 将元素的所在框标记出来
        self.locator_station(el)
        return el

    # 窗口切换
    def change_window(self, n):
        """窗口切换的功能"""
        # 获取句柄
        handles = self.driver.window_handles
        # 切换到原始的页面, n = 0
        # 切换到第二个页面, n = 1 依次类推
        # 切换到最新的页面, n = -1
        self.driver.switch_to.window(handles[n])
        print("当前跳转成功的页面:", self.driver.title)

    # 元素文本获取 + 显示等待
    def text_wait(self, name, value, text):
        el = (name, value)
        res = self.wait.until(ec.text_to_be_present_in_element(el, text))
        return res

    # 对获取到的元素进行判断
    # 获取到的元素的文本信息进行判断
    # 鼠标事件
    def mouse_hold(self):
        """鼠标事件的操作"""
        action = ActionChains(self.driver)
        action.click().click_and_hold().scroll_to_element().perform()
    # 键盘事件
    # 滚轮事件

    # 显示定位的地方,方便确认定位位置
    def locator_station(self, ele):
        self.driver.execute_script(
            "arguments[0].setAttribute('style',arguments[1]);",
            ele,
            "border: 2px solid red"  # 边框,red红色
        )
数据读取驱动
python 复制代码
import yaml


def load_yaml(path):
    file = open(path, "r", encoding="utf-8")
    data = yaml.load(file, Loader=yaml.FullLoader)
    return data
页面定位元素
python 复制代码
from selenium.webdriver.common.by import By

# 用户名输入框
page_login_user = ['xpath', "//input[@placeholder='手机号码']"]

# 密码输入框
page_login_indexPwd = ['xpath', "//input[@placeholder='密码']"]

# 登陆按钮
page_login_loginBtn = ['xpath', "//input[@name='btnLogin']"]

# 作家专区
page_index_author = [By.LINK_TEXT, "作家专区"]

# 章节管理按钮
page_authorManage_chapterManageBtn = [By.XPATH, '//*/a[contains(text(),"章节")]']
操作元素
python 复制代码
from selenium.webdriver.support.wait import WebDriverWait
from locate.allPages import *
from selenium.webdriver.support import expected_conditions as ec

from key_word.keyword import WebKeys

# 创建章节的业务场景类
class CreateChapterLogic(WebKeys):
    def createChapter(self, title):
        # 实例化wait
        wait = WebDriverWait(self.driver, 10)

        # 测试步骤
        # 01 点击作家专区、打开新页签
        self.locator_with_wait(*page_index_author).click()

        # 等待新页签出现
        wait.until(ec.number_of_windows_to_be(2))

        # 02 切换窗口
        self.change_window(-1)

        # 03 点击章节管理按钮
        self.locator_with_wait(*page_authorManage_chapterManageBtn).click()
用例层
python 复制代码
import time

import pytest
from selenium.webdriver.common.by import By

from data_driver.yaml_driver import load_yaml
from logic.create_chapter import CreateChapterLogic
from logic.login import LoginPage
from VAR.BOOKHOUSE_VAR import *


@pytest.mark.skip
def test_case01(borwser):
    # 需要谷歌浏览器的实例化对象
    login = LoginPage(borwser)
    login.login(LOGIN_URL, USERNAME, PASSWD)

    # 创建章节的步骤
    createChapter = CreateChapterLogic(borwser)
    createChapter.createChapter("章节0001")


@pytest.mark.parametrize('data', load_yaml("./data/userData.yaml"))
def test_case02(borwser, data):
    print("data:", data)

    # 需要谷歌浏览器的实例化对象
    login = LoginPage(borwser)
    login.login(LOGIN_URL, str(data['username']), str(data['passwd']))
    logic_text = login.text_wait('link text', str(data['username']), str(data['username']))
    assert logic_text is True
    login.mouse_hold()
使用main_run运行
python 复制代码
import pytest


def run():
    pytest.main(['-vs'])


if __name__ == '__main__':
    run()

总结

搭建框架前,希望大家可以思考以下几个问题:

1、封装后的框架,作用大不大?

2、封装什么内容,是否明白?

3、自动化的技术,到底可以帮助功能测试解决什么问题?
耗时、重复的步骤多、避免人为的因素导致测试的结果正确性低

4、需要把重复的内容给他挑出来?
因为程序可以反复的执行(循环、重复的调用)

5、下一次执行用例的时候,如果遇到了这么重复性的内容,可以干什么? (复用)

在这种方法思路(POM)的指导下,我们还可以对框架进行深度优化和二次封装,增强测试框架的易用性。

以上就是今天为大家分享的全部内容,下一篇文章,再见!感谢阅读。

相关推荐
费弗里43 分钟前
Python全栈应用开发利器Dash 3.x新版本介绍(1)
python·dash
李少兄9 天前
解决OSS存储桶未创建导致的XML错误
xml·开发语言·python
就叫飞六吧9 天前
基于keepalived、vip实现高可用nginx (centos)
python·nginx·centos
Vertira9 天前
PyTorch中的permute, transpose, view, reshape和flatten函数详解(已解决)
人工智能·pytorch·python
学Linux的语莫9 天前
python基础语法
开发语言·python
匿名的魔术师9 天前
实验问题记录:PyTorch Tensor 也会出现 a = b 赋值后,修改 a 会影响 b 的情况
人工智能·pytorch·python
Ven%9 天前
PyTorch 张量(Tensors)全面指南:从基础到实战
人工智能·pytorch·python
mahuifa9 天前
PySide环境配置及工具使用
python·qt·环境配置·开发经验·pyside
大熊猫侯佩9 天前
ruby、Python 以及 Swift 语言关于 “Finally” 实现的趣谈
python·ruby·swift
懒惰的bit9 天前
STM32F103C8T6 学习笔记摘要(四)
笔记·stm32·学习