Selenium 項目實戰(三)BasePage 封裝


之前寫的代碼中都沒有加入異常處理,規范寫法,應該在每次查找元素或操作時加上異常處理、日志信息、失敗截圖等,如下:

    def input_account(self, account):
        '''輸入賬號'''
        try:
            WebDriverWait(self.driver, 20).until(EC.visibility_of_element_located(self.account))
            self.driver.find_element(*self.account).send_keys(account)
        except Exception:
            raise 

但是為所有的查找元素和操作都加上這些耗時且不方便維護,為了簡化操作,可以把一些公用的方法封裝到 BasePage 類,其它頁面 page 直接繼承 BasePage 即可調用公共方法。

BasePage 類:

1. 封裝基本函數:執行日志、失敗截圖、異常處理等

2. 所有頁面公共操作方法

文件結構:

示例代碼:

base_page.py

import os
import time
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from common.logger import logger
import configs

class BasePage:

    def __init__(self, driver):
        self.driver = driver

    def open(self, url):
        self.driver.get(url)

    def wait_ele_visible(self, locator:tuple, doc="", timeout=30, poll_frequency=0.5, ignored_exceptions=None):
        '''
        等待元素可見
        :param locator: 元素定位方式,元組形式
        :param timeout: 超時時間,默認30秒
        :param poll_frequency: 輪詢時間,默認0.5秒
        :param ignored_exceptions: 要忽略的異常
        :param doc: 截圖模塊名稱,若沒有則只以時間戳明明
        :return:
        '''
        logger.info(f"等待元素 {locator} 可見")
        try:
            WebDriverWait(self.driver, timeout, poll_frequency, ignored_exceptions).until(EC.visibility_of_element_located(locator))
        except Exception as e:
            logger.exception(f"等待元素 {locator} 可見失敗")
            self.save_screenshot(doc)
            raise e

    # 查找元素
    def get_element(self, locator: tuple, doc="")->WebElement:
        logger.info(f"查找元素 {locator} ")
        try:
            return self.driver.find_element(*locator)
        except:
            logger.exception(f"查找元素 {locator} 失敗")
            self.save_screenshot(doc)
            raise

    # 點擊元素
    def click_element(self, locator:tuple, doc=""):
        ele = self.get_element(locator, doc)
        try:
            ele.click()
        except:
            logger.exception(f"點擊元素 {locator} 失敗")
            self.save_screenshot(doc)
            raise

    # 輸入文本
    def input_text(self, locator:tuple, text, doc=""):
        ele = self.get_element(locator, doc)
        try:
            ele.send_keys(text)
        except:
            logger.exception(f"元素 {locator} 輸入文本 {text} 失敗")
            self.save_screenshot(doc)
            raise

    # iframe 切換
    def switch_to_iframe(self, locator:tuple, doc=""):
        ele = self.get_element(locator, doc)
        try:
            self.driver.switch_to.frame(ele)
        except:
            logger.exception(f"切換到iframe {locator} 失敗")
            self.save_screenshot(doc)
            raise

    # 失敗截圖
    def save_screenshot(self, filename):
        if not os.path.exists(configs.SCREENSHOT_PATH):
            os.mkdir(configs.SCREENSHOT_PATH)

        # 圖片名稱:模塊名-頁面名-函數名-年月日時分秒.png
        file_name = configs.SCREENSHOT_PATH + filename + "_" + time.strftime("%Y%m%d%H%M%S") + ".png"
        self.driver.save_screenshot(file_name)
        logger.info(f"成功獲取截圖,路徑:{file_name}")

demo_login_page.py,頁面 page 類需繼承 BasePage 類

import os
from configparser import ConfigParser
from common.base_page import BasePage

class LoginPage(BasePage):

    def get_locator(self):
        conf = ConfigParser()
        print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "\\page_locator\\demo_locator.ini")
        conf.read(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "\\page_locator\\demo_locator.ini", encoding="utf-8")
        self.url = conf.get("Base", "url")

        section = "LoginPageLocator"
        # eval 將字符串元組轉換為元組
        self.login_by_pwd_btn = eval(conf.get(section, "login_by_pwd_btn"))
        self.account = eval(conf.get(section, "account"))
        self.pwd = eval(conf.get(section, "pwd"))
        self.login_btn = eval(conf.get(section, "login_btn"))

    def __init__(self, driver):
        super().__init__(driver)
        self.get_locator()

    def login(self, account, password):
        doc = "登錄頁面_登錄"
        self.driver.get(self.url)                   # 打開登錄頁面
        self.click_element(self.login_by_pwd_btn, doc)    # 點擊密碼登錄
        self.input_text(self.account, account, doc)  # 輸入賬號
        self.input_text(self.pwd, password, doc)     # 輸入密碼
        self.click_element(self.login_btn, doc)      # 點擊登錄

demo_home_page.py,頁面 page 類需繼承 BasePage 類

import os
from configparser import ConfigParser
from common.base_page import BasePage

class HomePage(BasePage):
    def get_locator(self):
        conf = ConfigParser()
        conf.read(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "\\page_locator\\demo_locator.ini",encoding="utf-8")

        section = "HomePageLocator"
        self.account_info = eval(conf.get(section, "account_info"))

    def __init__(self, driver):
        super().__init__(driver)
        self.get_locator()

    def is_account_info_exist(self):
        try:
            self.wait_ele_visible(self.account_info)
            return True
        except Exception:
            return False

test_demo.py

from pytest_assume.plugin import assume
from selenium import webdriver
from po.page_object.demo_home_page import HomePage
from po.page_object.demo_login_page import LoginPage

class TestLogin():
    def setup_class(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(10)

    def teardown_class(self):
        self.driver.quit()

    def test_demo(self):
        self.login_page = LoginPage(self.driver)
        self.home_page = HomePage(self.driver)
        self.login_page.login("15348369418", "Pan910124")
        with assume:
            assert self.home_page.is_account_info_exist()

對於一些通用的方法,我們也可根據自己的需要進行封裝,譬如從 demo_locator.ini 文件獲取數據,我們可以封裝一個工具類 handle_ini.py 放在 common 模塊下:

import os
from configparser import ConfigParser

class HandleIni(ConfigParser):

    # 已字典格式返回 ini 文件中某個 section 的數據
    def get_locator_dict(self, locator_file, section):
        conf = ConfigParser()
        conf.read(os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "\\po\\page_locator\\" + locator_file, encoding="utf-8")
        section_data = {}
        for key in conf.options(section):
            section_data[key] = conf.get(section, key)
        return section_data

那么其他頁面類就可以使用 HandleIni 工具類來獲取數據:

# demo_home_page.py

from common.base_page import BasePage
from common.handle_ini import HandleIni

class HomePage(BasePage):
    def get_locator(self):
        locators = HandleIni().get_locator_dict("demo_locator.ini", "HomePageLocator")
        self.account_info = eval(locators.get("account_info"))

    def __init__(self, driver):
        super().__init__(driver)
        self.get_locator()

    def is_account_info_exist(self):
        try:
            self.wait_ele_visible(self.account_info)
            return True
        except Exception:
            return False


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM