• 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. 框架形成后,需要对框架进行持续升级和优化,因为页面元素在变化、项目也在不断迭代,因此测试框架需要持续升级才能适应项目的更新迭代,特别是对于敏捷测试来讲。

    代码示例

    方法封装,封装基类,也叫关键字
    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红色
            )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    数据读取驱动
    import yaml
    
    
    def load_yaml(path):
        file = open(path, "r", encoding="utf-8")
        data = yaml.load(file, Loader=yaml.FullLoader)
        return data
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    页面定位元素
    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(),"章节")]']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    操作元素
    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()
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    用例层
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    使用main_run运行
    import pytest
    
    
    def run():
        pytest.main(['-vs'])
    
    
    if __name__ == '__main__':
        run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    总结

    搭建框架前,希望大家可以思考以下几个问题:
    1、封装后的框架,作用大不大?

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

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

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

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

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

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

  • 相关阅读:
    艾思AI-admin框架开发指导意见与规范1.0
    杰理之USB处理接口处理【篇】
    SpringBoot整合RabbitMQ(最新笔记)
    Dive into TensorFlow系列(3)- 揭开Tensor的神秘面纱
    揭秘BSN-DDC网络的自建城市算力中心
    SQL语句关联表 如何添加关联表的条件 [需要null值或不需要null值]
    助力商家高效接单发货,震坤行物流服务再升级
    搬家快递服务小程序的便利性
    【C++进阶(六)】STL大法--栈和队列深度剖析&优先级队列&适配器原理
    QP状态机学习①——QP状态机架构
  • 原文地址:https://blog.csdn.net/m0_66879271/article/details/136142672