Client-Page Object,对PO模式的一个扩展
Page Object模式
熟悉UI自动化测试的同学们应该都听过并使用过大名鼎鼎的Page Object模式吧,就是将页面上的元素定位信息和页面操作逻辑与测试用例层分开,一般根据元素定位与页面操作逻辑是否分开分成两到三层,即测试用例层—操作逻辑层—元素对象层,或测试用例层—页面对象层。以playwright测试百度页面为例:
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()
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模式
示例代码如下:
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 = page
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 = playwright.chromium.launch(headless=False)
self.page = Client.browser.new_page()
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
import pytest
from client import Client
@pytest.fixture
def user():
user_ = Client('http://www.baidu.com')
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):
而这两个用户只需定义两个Client类,注册不同页面即可。
此次分享到此结束,各位如有更好的方法欢迎告诉我,谢谢。
|