"二战" UI 测试 之 代码设计

背景

UI 自动化测试一直是老生常谈的话题,css

做为处于"金字塔顶端"的自动化手段,用的很差就是一场灾难,用的好也没法雪中送炭。markdown

在本篇文章中,我将记录一下我"第二次"设计 UI 测试的心得体会。架构

正文

POM (页面对象模型)相信你们已经很是熟悉了,核心思想就是每一个页面对应一个类,在每一个类中放置页面中的定位信息以及相关操做函数。函数

然而在 POM 的基础上,咱们其实能够将每一个页面的操做抽象成字典映射。这样一来,全部的用例执行对应的操做会变得很是清晰。测试

self.actions_map = {
    '点击职位管理标签': self._click_job_position_management_tab,
    '点击新增职位按钮': self._click_add_job_position_button,
    '输入职位信息': self._input_job_position_info,
}
复制代码

在实战中,也相信你们发现很多页面带有重复的元素,好比标签栏,导航栏等通用组件。spa

针对这个状况,咱们能够设计一个页面基础类,储存全部页面通用的 基础操做通用定位,全部独立的页面类均可以继承这个基础类,从而使得代码架构变得更加整洁,有效减小重复代码。设计

class PageObjectModel:

    LOCATORS = {
        'el-message--success': {'css selector': '.el-message--success'},
        'bread_crumb_nav': {'css selector': 'div[role=\'navigation\']'},
    }

    def __init__(self, browser=None):
        self.browser = browser
        self.actions_map = {}
        self.base_actions_map = {
            '检查并激活主页面包屑导航': self._check_and_activate_tab_bar,
            '切换至新开窗口': self._switch_to_new_window,
            '关闭当前窗口': self._close_current_window,
            '关闭新开窗口': self._close_new_window,
        }

    def operate(self, action, **kwargs):
        if action in self.actions_map.keys():
            self.actions_map[action](**kwargs)
        elif action in self.base_actions_map.keys():
            self.base_actions_map[action](**kwargs)
        else:
            preporter.warn(msg=f'action: 【{action}】 不在 action_map 内!')
复制代码

这里的设计关键有两点:code

  1. 初始化 base_actions_map,也就是咱们的基础操做字典,咱们要在这里对全部的测试执行步骤和对应的执行函数进行映射。orm

  2. 实现 operate 方法,全部的用例执行操做步骤都将经过 operate 方法 优先 在自己的操做字典中寻找映射函数。对象

基础类设计完毕~。

假设咱们如今须要对某个页面作UI自动化,咱们的只须要继承刚刚实现 PageObjectModel, 而后构造 actions_map 就能够了~

class JobPositionManagement(PageObjectModel):

    LOCATORS = {
        # 职位管理列表页元素
        'job_position_management_page': {'tag name': 'li', 'text': '职位管理'},
    }

    def __init__(self, browser=None):
        super(JobPositionManagement, self).__init__(browser)

        self.actions_map = {
            '点击职位管理标签': self._click_job_position_management_tab,
        }

    def _click_job_position_management_tab(self, browser=None):
        _browser = self.browser if self.browser else browser
	_browser.v_click(locate_rule=self.LOCATORS['job_position_management_page'])

复制代码

最后在实际测试调用中,代码会变得很是整洁清晰,而这也是程序设计的魅力。

@HistoricalLogsDeletion
    @Test(enabled=False, tags=["职位管理", "回归测试", "冒烟测试"], description="验证点击【生成JD】后,JD输入框是否生成数据", timeout=30)
    def test_06(self):

        self.job_position_management.operate(action='生成JD')

        self.job_position_management.operate(action='等待页面加载完毕')

        self.job_position_management.operate(action='验证JD输入框内是否存在数据')
复制代码

结尾

虽然大部分公司都没法成功在 UI 自动化测试中得到正收益,但测试技术的发展永无止境~

相关文章
相关标签/搜索