Python+selenium 【第十章】封装底层页面操作类,日志类

前情提要

上一章节我们说到的是对是配置文件的处理,方便我们对数据源进行操作,还有就是针对驱动类进行单独封装更方便其他方法调用

本章内容

主要是针对页面操作类进行封装,并加入日志模块,方便我们进行监控代码操作,并且结合我们之前封装的element_excel_utils中数据进行操作

为什么要封装Base_page(底层页面)

原因之前已经说过了,方便我们在编写测试用例或者测试操作的时候更加方便,另一个更方面是结合当前的操作输出日志,能够直观的告诉你代码当前正在运行什么东西,另一个原因就是我们封装好base类之后就更加符合我们的关键字驱动,只需要调用一个方法,就可以直接帮你实现你要的操作…

优化前

# -*- coding: utf-8 -*-
# @Time : 2022/1/7 16:57
# @Author : Limusen
# @File : demo_base
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)
driver.find_element(By.XPATH, '//*[@id="kw"]').send_keys("测试一下")
time.sleep(2)
driver.find_element(By.XPATH, '//*[@id="su"]').click()

优化后

这里可以看到出来,我们封装之后的操作只需要调用这个click或者send_keys就行了,减少了多余代码的编写,更加的方便了

# -*- coding: utf-8 -*-
# @Time : 2022/1/7 16:57
# @Author : Limusen
# @File : demo_base
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)

# excel中取出来的数据格式
element = {'baidu_input': {'element_name': '百度输入框', 'locator_type': 'id', 'locator_value': 'kw', 'timeout': 5.0},
           'query_button': {'element_name': '点击查询按钮', 'locator_type': 'id', 'locator_value': 'su', 'timeout': 5.0}}

input_text = element['baidu_input']
query_button = element['query_button']


# 由于我们从字典中取出来的数据是这样
# 所以我们封装base_page 代码

def find_element(element_info):
    locator_type = element_info["locator_type"]
    locator_value = element_info["locator_value"]
    locator_timeout = element_info["timeout"]

    if locator_type == "name":
        locator_type = By.NAME
    elif locator_type == "css":
        locator_type = By.CSS_SELECTOR
    elif locator_type == "xpath":
        locator_type = By.XPATH
    elif locator_type == "id":
        locator_type = By.ID
    elif locator_type == "class":
        locator_type = By.CLASS_NAME
    elif locator_type == "linktext":
        locator_type = By.LINK_TEXT
    elif locator_type == "partiallink":
        locator_type = By.PARTIAL_LINK_TEXT
    elif locator_type == "tag":
        locator_type = By.TAG_NAME

    element = WebDriverWait(driver, locator_timeout).until(
        lambda x: x.find_element(locator_type, locator_value))

    return element


def click(element):
    element = find_element(element)

    element.click()


def send_keys(element, text):
    element = find_element(element)
    element.send_keys(text)


send_keys(element['baidu_input'],"测试一下")
click(element['query_button'])

  • 整体代码
# -*- coding: utf-8 -*-
# @Time : 2022/1/7 16:57
# @Author : Limusen
# @File : demo_base
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.implicitly_wait(10)
# driver.find_element(By.XPATH, '//*[@id="kw"]').send_keys("测试一下")
# time.sleep(2)
# driver.find_element(By.XPATH, '//*[@id="su"]').click()

# excel中取出来的数据格式
element = {'baidu_input': {'element_name': '百度输入框', 'locator_type': 'id', 'locator_value': 'kw', 'timeout': 5.0},
           'query_button': {'element_name': '点击查询按钮', 'locator_type': 'id', 'locator_value': 'su', 'timeout': 5.0}}

input_text = element['baidu_input']
query_button = element['query_button']


# 由于我们从字典中取出来的数据是这样
# 所以我们封装base_page 代码

def find_element(element_info):
    locator_type = element_info["locator_type"]
    locator_value = element_info["locator_value"]
    locator_timeout = element_info["timeout"]

    if locator_type == "name":
        locator_type = By.NAME
    elif locator_type == "css":
        locator_type = By.CSS_SELECTOR
    elif locator_type == "xpath":
        locator_type = By.XPATH
    elif locator_type == "id":
        locator_type = By.ID
    elif locator_type == "class":
        locator_type = By.CLASS_NAME
    elif locator_type == "linktext":
        locator_type = By.LINK_TEXT
    elif locator_type == "partiallink":
        locator_type = By.PARTIAL_LINK_TEXT
    elif locator_type == "tag":
        locator_type = By.TAG_NAME

    element = WebDriverWait(driver, locator_timeout).until(
        lambda x: x.find_element(locator_type, locator_value))

    return element


def click(element):
    element = find_element(element)

    element.click()


def send_keys(element, text):
    element = find_element(element)
    element.send_keys(text)


send_keys(element['baidu_input'],"测试一下")
click(element['query_button'])

封装Base_page

封装Base_page之前先了解一下匿名函数

匿名函数

在此我们先了解一下匿名函数的用法,匿名函数有哪些优点?

不用取名称,因为给函数取名是比较头疼的一件事,特别是函数比较多的时候
可以直接在使用的地方定义,如果需要修改,直接找到修改即可,方便以后代码的维护工作 语法结构简单,不用使用def
函数名(参数名):这种方式定义,直接使用lambda 参数:返回值 定义即可

匿名函数

# -*- coding: utf-8 -*-
# @Time : 2022/1/5 13:16
# @Author : Limusen
# @File : demo_lambda_24


# 阶层
def x(y, z):
    return y * z

print(x(3, 2))

# 用匿名函数写的话
xx = lambda x, y: x * y

print(xx(3, 3))

新建Base_page

  • 在common文件夹下新建base_page.py 将写好的代码copy进去
# -*- coding: utf-8 -*-
# @Time : 2022/1/5 11:05
# @Author : Limusen
# @File : demo_base_page_23

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait


class DemoBasePage:

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

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

    def find_element(self, element_info):
        """
        通过分离处理的元素识别字典信息,返回一个元素
        :param element_info: 元素信息,字典类型{}
        :return: element对象
        """
        try:
            locator_type = element_info["locator_type"]
            locator_value = element_info["locator_value"]
            locator_timeout = element_info["timeout"]

            if locator_type == "name":
                locator_type = By.NAME
            elif locator_type == "css":
                locator_type = By.CSS_SELECTOR
            elif locator_type == "xpath":
                locator_type = By.XPATH
            elif locator_type == "id":
                locator_type = By.ID
            elif locator_type == "class":
                locator_type = By.CLASS_NAME
            elif locator_type == "linktext":
                locator_type = By.LINK_TEXT
            elif locator_type == "partiallink":
                locator_type = By.PARTIAL_LINK_TEXT
            elif locator_type == "tag":
                locator_type = By.TAG_NAME
            # 采用匿名函数 将元素存在x变量当中,然后去查找页面是否存在当前元素
            element = WebDriverWait(self.driver, locator_timeout).until(
                lambda x: x.find_element(locator_type, locator_value))
        except Exception:
            raise

        return element

    def click(self, element_info):
        # 优化
        element = self.find_element(element_info)
        element.click()

    def send_keys(self, element_info, text):
        # 优化
        element = self.find_element(element_info)
        element.send_keys(text)


if __name__ == '__main__':
    driver = webdriver.Chrome()
    db = DemoBasePage(driver)
    db.open_url("http://www.baidu.com")
    driver.implicitly_wait(10)

    # db.send_keys((By.XPATH, '//*[@id="kw"]'), "测试一下")
    # time.sleep(2)
    # db.click((By.XPATH, '//*[@id="su"]'))

    # 优化代码 读取excel中的数据
    element_info = {
        'input_text': {'element_name': '输入框', 'locator_type': 'xpath', 'locator_value': '//*[@id="kw"]',
                       'timeout': 5.0},
        'click_button': {'element_name': '点击按钮', 'locator_type': 'xpath', 'locator_value': '//*[@id="su"]',
                         'timeout': 5.0}}

    input_t = element_info['input_text']
    click_b = element_info['click_button']

    db.send_keys(input_t, "测试一下")
    db.click(click_b)

在这里插入图片描述

其他方法封装

  • 大家可以自己封装自己想要的方法,这里就不一一列举了
# -*- coding: utf-8 -*-
# @Time : 2022/1/5 13:50
# @Author : Limusen
# @File : base_page


import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from common.log_utils import logger
from common.config_utils import local_config


class BasePage:

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

    def open_url(self, url):
        try:
            self.driver.get(url)
            logger.info("打开url:%s" % url)
        except Exception as e:
            logger.error("不能打开制定网站,原因是: %s" % e.__str__())

    def close_browser(self):
        self.driver.close()
        logger.info("关闭当前tab页签")

    def exit_driver(self):
        self.driver.quit()
        logger.info("退出浏览器")

    def set_window_max(self):
        self.driver.maximize_window()
        logger.info("浏览器最大化")

    def page_refresh(self):
        self.driver.refresh()
        logger.info("浏览器刷新")

    def get_title(self):
        value = self.driver.title
        logger.info("获取标题:%s" % value)
        return value

    def get_url(self):
        value = self.driver.current_url
        logger.info("获取url:%s" % value)
        return value

    def get_page_source(self):
        self.wait(1)
        source = self.driver.page_source
        logger.info("获取页面源码,用来检查是否包含某个元素:%s" % source)
        return source

    def back_up(self):
        self.driver.back()
        logger.info("返回上一页")

    def forward(self):
        self.driver.forward()
        logger.info("前进一页")

    def clear_input(self, element_info):
        element = self.find_element(element_info)
        element.clear()
        logger.info("清除内容输入框内容: %s" % element_info["locator_value"])

    #  封装时间
    def wait(self, seconds=local_config.time_out):
        """
        固定等待--加入默认值,如果没有设置超时时间,则默认等待五秒钟

        :param seconds: 如果没有传入值则默认等待5秒钟
        """
        time.sleep(seconds)
        logger.info("休息一会儿 %s 秒钟~" % seconds)

    def implicitly_wait(self, seconds=local_config.time_out):
        """
        隐式等待--加入默认值,如果没有设置超时时间,则默认等待五秒钟

        :param seconds: 如果没有传入值则默认等待5秒钟
        """
        self.driver.implicitly_wait(seconds)
        logger.info("隐式等待个 %s 秒" % seconds)

    def find_element(self, element_info):
        """
        通过分离处理的元素识别字典信息,返回一个元素
        :param element_info: 元素信息,字典类型{}
        :return: element对象
        """
        try:
            locator_type = element_info["locator_type"]
            locator_value = element_info["locator_value"]
            locator_timeout = element_info["timeout"]

            if locator_type == "name":
                locator_type = By.NAME
            elif locator_type == "css":
                locator_type = By.CSS_SELECTOR
            elif locator_type == "xpath":
                locator_type = By.XPATH
            elif locator_type == "id":
                locator_type = By.ID
            elif locator_type == "class":
                locator_type = By.CLASS_NAME
            elif locator_type == "linktext":
                locator_type = By.LINK_TEXT
            elif locator_type == "partiallink":
                locator_type = By.PARTIAL_LINK_TEXT
            elif locator_type == "tag":
                locator_type = By.TAG_NAME
            element = WebDriverWait(self.driver, locator_timeout).until(
                lambda x: x.find_element(locator_type, locator_value))
            logger.info('[%s]元素识别成功' % element_info['element_name'])
        except Exception as e:
            logger.error("[%s]元素不能识别,原因是: %s" % (element_info['element_name'], e.__str__()))

        return element

    def get_text(self, element_info):
        element = self.find_element(element_info)
        try:
            text = element.text
            logger.info("获取文本信息:%s" % text)
            return text
        except Exception as e:
            logger.error("[%s]元素不能识别,原因是: %s" % (element_info['element_name'], e.__str__()))

    def input(self, element_info, inputs):
        """
        :param element_info: 元素信息,字典类型{}
        :param inputs: 输入参数
        """
        element = self.find_element(element_info)
        try:
            element.send_keys(inputs)
            logger.info("输入框输入内容:%s , 识别输入框:%s" % (inputs, element_info["locator_value"]))
        except Exception as e:
            logger.error("[%s]元素不能识别,原因是: %s" % (element_info['element_name'], e.__str__()))

    def click(self, element_info):
        """
        :param element_info: 元素信息,字典类型{}
        """
        element = self.find_element(element_info)
        try:
            element.click()
            logger.info("识别元素进行点击操作:%s" % element_info["locator_value"])
        except Exception as e:
            logger.error("[%s]元素不能识别,原因是: %s" % (element_info['element_name'], e.__str__()))


if __name__ == '__main__':
    driver = webdriver.Chrome()
    db = BasePage(driver)
    db.open_url("http://www.baidu.com")
    driver.implicitly_wait(10)

    # 优化代码 读取excel中的数据
    element_info = {
        'input_text': {'element_name': '输入框', 'locator_type': 'xpath', 'locator_value': '//*[@id="kw"]',
                       'timeout': 5.0},
        'click_button': {'element_name': '点击按钮', 'locator_type': 'xpath', 'locator_value': '//*[@id="su"]',
                         'timeout': 5.0}}

    input_t = element_info['input_text']
    click_b = element_info['click_button']

    db.input(input_t, "测试一下")
    db.click(click_b)

日志模块

日志模块能够帮助我们快速定位到代码的错误地方,所以很有必要在代码中添加日志

新建log_demo进行学习

代码示例

# -*- coding: utf-8 -*-
# @Time : 2022/1/5 14:14
# @Author : Limusen
# @File : demo_log_24

# log日志demo

import os
import logging
import time

current_path = os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
logs_path = os.path.join(current_path, 'logs')

# logger输入的地址
login_name = os.path.join(logs_path, 'Test_%s.log' % time.strftime("%Y_%m_%d"))

# 创建logger对象
logger = logging.getLogger("logger")
# logger的等级 info
logger.setLevel(20)

fh = logging.FileHandler(login_name, 'a', encoding="utf-8")  # 输出日志到文件
fh.setLevel(20)
ch = logging.StreamHandler()  # 输出日志到控制台
ch.setLevel(20)

logger.addHandler(fh)
logger.addHandler(ch)
fh.close()  # 关闭以免重复打印
ch.close()

logger.info("测试一下")

代码图示

在这里插入图片描述

封装log_utils类

# -*- coding: utf-8 -*-
# @Time : 2022/1/5 14:13
# @Author : Limusen
# @File : log_utils


import os
import time
import logging
from common.config_utils import local_config

current_path = os.path.dirname(os.path.abspath(__file__))
log_path = os.path.join(current_path, '..','logs')


class LogUtils:

    def __init__(self, logger=None):
        self.log_name = os.path.join(log_path, 'Test_%s.log' % time.strftime('%Y_%m_%d'))
        self.logger = logging.getLogger(logger)  # 日志对象
        self.logger.setLevel(local_config.log_level)  # 日志级别

        self.fh = logging.FileHandler(self.log_name, 'a', encoding='utf-8')  # 输出到文件
        self.fh.setLevel(local_config.log_level)
        self.ch = logging.StreamHandler()  # 输出到控制台
        self.ch.setLevel(local_config.log_level)

        formatter = logging.Formatter(
            '[%(asctime)s] %(filename)s->%(funcName)s line:%(lineno)d [%(levelname)s] : %(message)s')
        self.fh.setFormatter(formatter)
        self.ch.setFormatter(formatter)
        self.logger.addHandler(self.fh)
        self.logger.addHandler(self.ch)
        self.fh.close()
        self.ch.close()

    def get_log(self):
        return self.logger


logger = LogUtils().get_log()

if __name__ == '__main__':
    logger.info('测试一下日志文件')

在这里插入图片描述

其他类引入新建的日志类

base_page.py

# -*- coding: utf-8 -*-
# @Time : 2022/1/5 13:50
# @Author : Limusen
# @File : base_page


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from common.log_utils import logger


class BasePage:

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

    def open_url(self, url):
        self.driver.get(url)
        logger.info("当前正在打开网址: [%s]" % url)

    def find_element(self, element_info):
        """
        通过分离处理的元素识别字典信息,返回一个元素
        :param element_info: 元素信息,字典类型{}
        :return: element对象
        """
        try:
            locator_type = element_info["locator_type"]
            locator_value = element_info["locator_value"]
            locator_timeout = element_info["timeout"]

            if locator_type == "name":
                locator_type = By.NAME
            elif locator_type == "css":
                locator_type = By.CSS_SELECTOR
            elif locator_type == "xpath":
                locator_type = By.XPATH
            elif locator_type == "id":
                locator_type = By.ID
            elif locator_type == "class":
                locator_type = By.CLASS_NAME
            elif locator_type == "linktext":
                locator_type = By.LINK_TEXT
            elif locator_type == "partiallink":
                locator_type = By.PARTIAL_LINK_TEXT
            elif locator_type == "tag":
                locator_type = By.TAG_NAME
            # 采用匿名函数 将元素存在x变量当中,然后去查找页面是否存在当前元素
            element = WebDriverWait(self.driver, locator_timeout).until(
                lambda x: x.find_element(locator_type, locator_value))
            logger.info("当前进行元素识别操作,元素名称为: [%s] " % (element_info["element_name"]))
        except Exception as e:
            logger.error("[%s]元素不能识别,原因是: %s" % (element_info['element_name'], e.__str__()))
            raise

        return element

    def click(self, element_info):
        # 优化
        try:
            element = self.find_element(element_info)
            logger.info("当前进行点击操作,点击元素名称为: [%s] " % (element_info["element_name"]))
        except Exception as e:
            logger.error("当前元素不能点击,原因是: [%s]" % e.__str__())
            raise
        element.click()

    def send_keys(self, element_info, inputs):
        # 优化
        try:
            element = self.find_element(element_info)
            logger.info("输入框输入内容:%s ,识别输入元素:[%s]" % (inputs, element_info["locator_value"]))
        except Exception as e:
            logger.error("[%s]元素不能识别,原因是: %s" % (element_info['element_name'], e.__str__()))
            raise
        element.send_keys(inputs)


if __name__ == '__main__':
    driver = webdriver.Chrome()
    db = BasePage(driver)
    db.open_url("http://www.baidu.com")
    driver.implicitly_wait(10)

    # 优化代码 读取excel中的数据
    element_info = {
        'input_text': {'element_name': '输入框', 'locator_type': 'xpath', 'locator_value': '//*[@id="kw"]',
                       'timeout': 5.0},
        'click_button': {'element_name': '点击按钮', 'locator_type': 'xpath', 'locator_value': '//*[@id="su"]',
                         'timeout': 5.0}}

    input_t = element_info['input_text']
    click_b = element_info['click_button']

    db.send_keys(input_t, "测试一下")
    db.click(click_b)

在这里插入图片描述

browser_utils.py

# -*- coding: utf-8 -*-
# @Time : 2022/1/4 19:44
# @Author : Limusen
# @File : browser_utils
#  封装驱动类

import os
import sys
import warnings
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from common.config_utils import local_config
from common.log_utils import logger

current_path = os.path.dirname(os.path.abspath(__file__))
system_driver = sys.platform


class BrowserUtils:

    def __init__(self):
        # 去除控制台警告
        warnings.filterwarnings("ignore", category=DeprecationWarning)
        self.driver_name = local_config.driver_name

    def get_driver(self):
        if self.driver_name.lower() == 'chrome':
            logger.info("当前正在打开:%s" % self.driver_name)
            return self.__get_chrome_driver()
        elif self.driver_name.lower() == 'firefox':
            logger.info("当前正在打开:%s" % self.driver_name)
            return self.__get_firefox_driver()
        elif self.driver_name.lower() == 'edge':
            logger.info("当前正在打开:%s" % self.driver_name)
            return self.__get_edge_driver()

    def __get_chrome_driver(self):
        # 先封装简易代码
        # 加入系统环境判断
        chrome_options = Options()
        chrome_options.add_argument('--disable-gpu')  # 谷歌文档提到需要加上这个属性来规避bug
        chrome_options.add_argument('lang=zh_CN.UTF-8')  # 设置默认编码为utf-8
        chrome_options.add_experimental_option('useAutomationExtension', False)  # 取消chrome受自动控制提示
        chrome_options.add_experimental_option("excludeSwitches", ['enable-automation'])  # 取消chrome受自动控制提示
        if system_driver.lower() == "darwin":
            """如果是mac系统执行这个驱动"""
            chrome_path = os.path.join(current_path, '..', 'webdriver', 'chrome', 'chromedriver.exe')
            driver = webdriver.Chrome(executable_path=chrome_path, options=chrome_options)
            logger.info('初始化Google浏览器并启动')
            return driver
        else:
            chrome_path = os.path.join(current_path, '..', 'webdriver', 'chrome', 'chromedriver93.exe')
            driver = webdriver.Chrome(executable_path=chrome_path, options=chrome_options)
            logger.info('初始化Google浏览器并启动')
            return driver

    def __get_firefox_driver(self):
        if system_driver.lower() == "darwin":
            firefox_path = os.path.join(current_path, '..', 'webdriver', 'firefox', 'geckodriver')
            driver = webdriver.Firefox(executable_path=firefox_path)
            logger.info('初始化Firefox浏览器并启动')
            return driver
        else:
            firefox_path = os.path.join(current_path, '..', 'webdriver', 'firefox', 'geckodriver.exe')
            driver = webdriver.Firefox(executable_path=firefox_path)
            logger.info('初始化Firefox浏览器并启动')
            return driver

    def __get_edge_driver(self):
        """
        驱动下载地址:https://developer.microsoft.com/zh-cn/microsoft-edge/tools/webdriver/
        :return:
        """
        edge_path = os.path.join(current_path, '..', 'webdriver', 'edge', 'msedgedriver.exe')
        driver = webdriver.Edge(executable_path=edge_path)
        logger.info('初始化Edge浏览器并启动')
        return driver


if __name__ == '__main__':
    driver = BrowserUtils().get_driver()
    driver.get("https://www.baidu.com")

在这里插入图片描述

总结

本章节主要是讲述的是封装底层模块方便其他模块调用,封装日志模块,能够更好的帮助测试人员定位代码报错的位置,能够快速定位到问题的所在

代码

地址 : https://gitee.com/todayisgoodday/PythonSelenium

博客园地址

https://www.cnblogs.com/yushengaqingzhijiao/category/2000515.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罐装七喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值