Client-Page Object,对PO模式的一个扩展

Client-Page Object,对PO模式的一个扩展

Page Object模式

熟悉UI自动化测试的同学们应该都听过并使用过大名鼎鼎的Page Object模式吧,就是将页面上的元素定位信息和页面操作逻辑与测试用例层分开,一般根据元素定位与页面操作逻辑是否分开分成两到三层,即测试用例层—操作逻辑层—元素对象层,或测试用例层—页面对象层。以playwright测试百度页面为例:

# baidu_page.py
class BasePage(object):
    def __init__(self, page):
        self.page = page

class BaiduPageLocator(BasePage):
    @property
    def search_input(self):
        return self.page.query_selector("input[name=\"wd\"]")

    @property
    def search_button(self):
        return self.page.query_selector("text=百度一下")

class BaiduPage(BaiduPageLocator):
    def search(self, text):
        self.search_input.fill(text)
        self.search_button.click()
# test_case.py
import pytest
from playwright.sync_api import sync_playwright 
from baidu_page import BaiduPage

@pytest.fixture
def page():
    playwright = sync_playwright().start()
    browser = playwright.chromium.launch(headless=False)
    page_ = browser.new_page()
    page_.goto("https://www.baidu.com/")
    yield page_
    page_.close()
    browser.close()
    playwright.stop()

class TestBaidu(object):
    def test_baidu(self, page):
        baidu_page = BaiduPage(page)
        baidu_page.search('playwright')

以上为在不考虑页面元素封装,基于pytest的一种实现方式,优点是可以更方便的进行代码复用,减少重复代码,以及当界面元素定位发生变化时,可以集中在同一个地方修改即可。

使用中的问题

开始,我在项目中也是像上述方式进行使用,但是不久就发现了一个问题,首先页面驱动需要自行管理(如playwright中的page对象和selenium中的driver对象),在用例中还要做初始化页面类实例这种与业务无关的操作,如果用例涉及多个页面和多个用户,编写用例时就会有较大的心智负担,无论是写还是读都不是很友好。基于以上,我就尝试在传统的Page Object模式中又加入一层client层,专门处理页面驱动部分,并且对于多角色的系统,可以将不同角色分为不同的client,相当于对角色的一层抽象,暂且将他称为Client-Page Object模式。

Client-Page Object模式

示例代码如下:

# client.py
from playwright.sync_api import sync_playwright
from baidu_page import BaiduPage

class Client(object):
    playwright = None
    browser = None

    def __init__(self, url):
        self.url = url
        self.page = None

    def register_page(self):
        self.baidu_page = BaiduPage(self.page)

    def start(self):
        if Client.playwright is None:
            Client.playwright = sync_playwright().start()
        if Client.browser is None:
            Client.browser = Client.playwright.chromium.launch(headless=False)
        self.page = Client.browser.new_page()
        self.page.goto(self.url)
        self.register_page()

    def close(self):
        self.page.close()

    @staticmethod
    def close_all():
        if Client.browser is not None:
            Client.browser.close()
            Client.browser = None
        if Client.playwright is not None:
            Client.playwright.stop()
            Client.playwright = None
# test_case.py
import pytest
from client import Client

@pytest.fixture
def user():
    user_ = Client('http://www.baidu.com')
    user_.start()
    yield user_
    user_.close()

class TestBaidu:
    def test_baidu(self, user):
        user.baidu_page.search('playwright')

如上所示,所有驱动相关内容由client来管理,就可以在编写测试用例时不需要管理驱动,也不需要创建页面对象,只需要关注测试业务即可,而且如果需要在同一个用例中用到两个不同的角色进行操作时,也是非常简单的,如下:

class TestSome:
    def test_Some_business(self, normal_user, admin_user):
        # normal_user 进行一些操作
				# admin_user 进行另一些操作

而这两个用户只需定义两个Client类,注册不同页面即可。

此次分享到此结束,各位如有更好的方法欢迎告诉我,谢谢。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值