【WEB自动化测试】-PO设计模式

一、PO模式V2版本实现浏览器打开方法的前置:setup_class

class TestLoginPage(object):
    login_data = [{'resault':'账户不存在','username':'admin1','pwd':'123456'},
                  {'resault':'密码错误','username':'admin','pwd':'1234567'}]
    def setup_class(self):
        # 浏览器打开和设置一次
        self.driver = webdriver.Chrome()
        self.driver.get('http://localhost/backend/page/login/login.html')
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)

    def teardown_class(self):
        time.sleep(5)
        self.driver.quit()

    def setup(self):
        time.sleep(2)
        # 登陆方法执行前,刷新一次首页,可以去掉上一次执行的弹出框
        self.driver.get('http://localhost/backend/page/login/login.html')

    def teardown(self):
        pass

    @pytest.mark.parametrize('login_info',login_data)
    def test_login(self,login_info):

        holder = self.driver.find_element(By.CSS_SELECTOR,'[placeholder="账号"]')
        holder.clear()
        holder.send_keys(login_info['username'])

        pwd = self.driver.find_element(By.CSS_SELECTOR, '[placeholder="密码"]')
        pwd.clear()
        pwd.send_keys(login_info['pwd'])
        self.driver.find_element(By.CSS_SELECTOR, 'button[class*=login-btn]').click()

二、PO模式V3版本

如用例多了,那么登陆的代码就需要在每个模块化中都加入,所以考虑公共部分提取出来,做成一个公共的工具类。习惯命名为utils.py。

2.1 定义获取驱动对象的工具类

  • 定义获取驱动对象的工具类
  • 封装"获取弹出框的提示信息"
"""
utils.py
公共方法模块:习惯命名 utils
"""
def get_alert_msg():
    time.sleep(0.5)
    msg = DriverUtil.get_driver().find_element(By.CSS_SELECTOR, 'p[class="el-message__content"]').text
    return msg


class DriverUtil(object):
    """浏览器对象管理类"""
    __driver = None

    @classmethod   #类装饰器,类方法可以直接由类对象调用,省略实例化对象步骤
    def get_driver(cls):
        """获取浏览器对象方法"""
        if cls.__driver is None:
            cls.__driver = webdriver.Chrome()
            cls.__driver.get('http://localhost:8001/backend/page/login/login.html')
            cls.__driver.maximize_window()  # 窗口最大化
            cls.__driver.implicitly_wait(10)  # 隐式等待
        return cls.__driver

    @classmethod
    def quit_driver(cls):
        """推出浏览器方法"""
        if cls.__driver:
            time.sleep(3)
            cls.__driver.quit()
            cls.__driver = None

    @classmethod
    def refresh_windows(cls):
        time.sleep(2)
        cls.__driver.get('http://localhost:8001/backend/page/login/login.html')

2.2 调用utils

class TestLoginPage(object):
    login_data = [{'resault':'账户不存在','username':'admin1','pwd':'123456'},
                  {'resault':'密码错误','username':'admin','pwd':'1234567'}]
    def setup_class(self):
        # 浏览器打开和设置一次
        self.driver = DriverUtil.get_driver()

    def teardown_class(self):
        DriverUtil.quit_driver()

    def setup(self):
        DriverUtil.refresh_windows()

    def teardown(self):
        pass

    @pytest.mark.parametrize('login_info',login_data)
    def test_login(self,login_info):

        holder = self.driver.find_element(By.CSS_SELECTOR,'[placeholder="账号"]')
        holder.clear()
        holder.send_keys(login_info['username'])

        pwd = self.driver.find_element(By.CSS_SELECTOR, '[placeholder="密码"]')
        pwd.clear()
        pwd.send_keys(login_info['pwd'])
        self.driver.find_element(By.CSS_SELECTOR, 'button[class*=login-btn]').click()
        msg = get_alert_msg()
        print("错误信息为:"+msg)
        assert msg == login_info['resault']

三、PO设计模式

PO是Page Object的缩写,PO模式是自动化测试项目开发实践的最佳设计模式之一。核心思想是通过对界面元素的封装减少冗余代码,同时在后期维护中,若元素定位发生变化,只需要调整页面元素封装的代码,提高测试用例的可维护性,可读性。

PO模式可以把一个页面分为三层,对象库层,操作层,业务层。每一层对应一个类。

  • 对象库层:封装定位元素的方法:page(页面对象)
  • 操作层:封装对元素的操作   base(基类,操作元素的类)
  • 业务层:将一个或多个操作组合起来完成一个业务功能,比如登录:需要输入账号,密码,点击登录三个操作。

3.1 代码

base/base.py-操作元素的类

from selenium.webdriver.support.wait import WebDriverWait

"""
元组解包:loc变量:类型为元组,*loc为解包
"""
class Base(object):
    # 初始化
    def __init__(self,driver):
        self.driver = driver

    # 查找元素方法(提供:点击、输入、获取文本等方法使用)
    # loc:元素的配置信息,格式为元组,例如(By.ID, "username")
    def base_find_element(self, loc, timeout=30, poll=0.5):
        return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).until(lambda x: x.find_element(*loc))

    # 点击控件方法
    def base_click(self, loc):
        self.base_find_element(loc).click()

    # 输入控件方法
    def base_input(self, loc, value):
        ele = self.base_find_element(loc)
        # 清空
        ele.clear()
        # 输入
        ele.send_keys(value)

    # 获取文本方法
    def base_get_text(self, loc):
        return self.base_find_element(loc).text

    # 截图方法
    def base_get_image(self, imagepath):
        self.driver.get_screenshot_as_file(imagepath)

page/__init__.py-存储元素

from selenium.webdriver.common.by import By

# 用户名
login_username = By.ID, "username"
# 密码
login_pwd = By.CSS_SELECTOR, 'input[placeholder="密码"]'
# 登录按钮
login_btn = By.XPATH, '//button[contains(@class,"login-btn")]'
# 错误信息
login_error_msg = By.CSS_SELECTOR,'div[class="el-message el-message--error"]'

page/page_login.py-封装元素,继承自base

from pompage.base.base import Base
from pompage import page


class PageLogin(Base):
    
    def __init__(self,driver):
        super(PageLogin, self).__init__(driver)

    # 输入用户名
    def page_input_username(self,username):
        self.base_input(page.login_username,username)

    # 输入密码
    def page_input_pwd(self, pwd):
        self.base_input(page.login_pwd, pwd)

    # 点击登录
    def page_click_btn(self):
        self.base_click(page.login_btn)

    # 获取错误信息
    def page_error_msg(self):
        return self.base_get_text(page.login_error_msg)

    def page_login(self, username, pwd):
        self.page_input_username(username)
        self.page_input_pwd(pwd)
        self.page_click_btn()

scripts/test_login.py -- 用例执行


import pytest

from pompage.utils import DriverUtil
from pompage.page.page_login import PageLogin

def get_login_data():
    return [{'resault':'账户不存在','username':'admin1','pwd':'123456'},
                {'resault':'密码错误','username':'admin','pwd':'1234567'}]
class TestLogin(object):

    def setup_class(self):
        self.driver = DriverUtil.get_driver()
        self.login = PageLogin(self.driver)

    def teardown_class(self):
        DriverUtil.quit_driver()

    def setup(self):
        DriverUtil.refresh_windows()

    def teardown(self):
        pass

    @pytest.mark.parametrize("login_info",get_login_data())
    def test_login(self,login_info):
        self.login.page_login(login_info['username'],login_info['pwd'])
        msg = self.login.page_error_msg()
        assert msg == login_info['resault']


utils.py-公共类

import time

from selenium import webdriver
from selenium.webdriver.common.by import By

"""
公共方法模块:习惯命名 utils
"""
def get_alert_msg():
    time.sleep(0.5)
    msg = DriverUtil.get_driver().find_element(By.CSS_SELECTOR, 'p[class="el-message__content"]').text
    return msg


class DriverUtil(object):
    """浏览器对象管理类"""
    __driver = None

    @classmethod   #类装饰器,类方法可以直接由类对象调用,省略实例化对象步骤
    def get_driver(cls):
        """获取浏览器对象方法"""
        if cls.__driver is None:
            cls.__driver = webdriver.Chrome()
            cls.__driver.get('http://localhost:8001/backend/page/login/login.html')
            cls.__driver.maximize_window()  # 窗口最大化
            cls.__driver.implicitly_wait(10)  # 隐式等待
        return cls.__driver

    @classmethod
    def quit_driver(cls):
        """推出浏览器方法"""
        if cls.__driver:
            time.sleep(3)
            cls.__driver.quit()
            cls.__driver = None

    @classmethod
    def refresh_windows(cls):
        time.sleep(2)
        cls.__driver.get('http://localhost:8001/backend/page/login/login.html')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值