欢迎来到魔幻小生的博客

Page Object 设计模式

Page Object(PO) 设计模式

为了避免当页面元素的ID或位置改变时需要频繁更改 UI 自动化测试用例代码的情况。

PO(PageObject)设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个 Page 类,即一个 py 文件,并以页面为单位来写测试用例,实现页面对象和测试用例的分离,若元素发生变化,只需要进入对应的 Page 类,更新元素定位即可,不用修改用例。

PO 模式六大原则

  • 一个 public 方法代表一个公共的服务。就是说一个方法代替页面上的某个操作(公共方法表示页面提供的服务)

  • PageObject 中的方法细节不可暴露在外,通过提供公共服务接口的形式提供给外部(不要暴露页面的细节)

  • 一般不需要在 PageObject 中断言(Page 设计中不要出现断言,应该写在测试用例类中)

  • 当有页面跳转的操作时候,执行这个方法时应该在方法结束返回时能够跳转到另一个页面中(方法应该返回其他的 Page 对象)

  • 我们只需要对页面中我们需要的重要的内容进行封装(不要去代表整个 page,如果一个页面中有很多功能,只需要对重点功能封装方法即可)

  • 页面中相同的组件,但是不同的操作应该要被拆成不同的方法进行封装(不同的结果返回不同的方法,不同的模式)

PO 项目例子

企业微信的注册和登录

image

项目结构如下:page包括所有UI页面,testcase里放测试用例

页面对象只需要关心元素定位和操作方法封装问题,测试用例只需要关心测试就行。

image

base_page.py:定义页面基础类,用于所有页面的基础,封装所有测试页面的公共方法。

from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver

class BasePage:
    base_url = ''

    def __init__(self, driver: WebDriver = None):
        self.driver = ''
        if driver is None:
            self.driver = webdriver.Chrome()
        else:
            self.driver = driver
        if self.base_url != '':
            self.driver.get(self.base_url)
        self.driver.implicitly_wait(5)

    def find(self, by, locator):
        return self.driver.find_element(by, locator)

main.py:测试的首页,进行注册和登录操作。

from selenium.webdriver.common.by import By
from pageobject.page.base_page import BasePage
from pageobject.page.register import Register
from pageobject.page.login import Login

class Main(BasePage):
    base_url = 'https://work.weixin.qq.com/'

    def goto_register(self):
        self.find(By.XPATH, '//*[@id="tmp"]/div[1]/a').click()
        return Register(self.driver)

    def goto_login(self):
        self.find(By.XPATH, '//*[@id="indexTop"]/div[2]/aside/a[1]').click()
        return Login(self.driver)

login.py:登录页面元素定位和操作方法(若UI发生改变仅需修改该页面无需修改其它页面)。

from selenium.webdriver.common.by import By
from pageobject.page.register import Register
from pageobject.page.base_page import BasePage

class Login(BasePage):
    def scan(self):
        pass

    def goto_register(self):
        self.find(By.XPATH, '//*[@id="wework_admin.loginpage_wx2_$"]/main/div[2]/a').click()
        return Register(self.driver)

register.py:注册元素定位和操作方法(若UI发生改变仅需修改该页面无需修改其它页面)。

from selenium.webdriver.common.by import By
from pageobject.page.base_page import BasePage

class Register(BasePage):
    def register(self):
        self.find(By.ID, 'corp_name').send_keys('hello')
        self.find(By.ID, 'manager_name').send_keys('world')
        return True

test_register.py:需要执行的测试用例。

from pageobject.page.main import Main

class TestRegister:
    def setup_method(self):
        self.main = Main()

    def test_register(self):
        # assert self.main.goto_register().register()
        assert self.main.goto_login().goto_register().register()
posted @ 2025-07-13 01:47  魔幻小生  阅读(62)  评论(0)    收藏  举报