之前写的代码中都没有加入异常处理、规范写法,应该在每次查找元素或操作时加上异常处理、日志信息、失败截图等,如下:
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 类,其它页面 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
资源分享【这份资料必须领取~】
下方这份完整的软件测试视频学习教程已经上传CSDN官方认证的二维码,朋友们如果需要可以自行免费领取 【保证100%免费】