详解Postman校验响应数据之设置断言编写Test脚本

2021-07-16 15:01:47 浏览数 (1)

首先,大家在做selenium自动化的时候,通常都是调用官网提供的元素定位方法,直接调用,可能初期做自动化的时候,不会有什么问题,但是随着我们项目功能越来越多,业务也越来越复杂,有些定位功能,需要单独定制,如果是直接调用的话,我们需要修改所有调用元素定位方法的代码,这样我们维护代码需要耗费很多时间,下面我们通过将元素定位单独封装,来解决这个问题,话不多说,直接贴代码。

(注意:这里执行的地方,需要依赖driver驱动,这里我用的是Chrome浏览器,所以安装的是Chromedriver,大家可以直接去下载搭建环境)

log.py

代码语言:javascript复制
# -*- coding: utf-8 -*-
# @Time    : 2019/2/15 9:23 AM
# @Author  : 余少琪
# @FileName: log.py
# @email   : 1603453211@qq.com

"""
这里封装了打印日志,之后做自动化的过程中,可以调用直接LogHandler方法,
将元素定位的信息打印出来,方便我们查看及定位问题。
"""


import logging
from logging import handlers
import colorlog
from common.setting import DevConfig


class LogHandler(object):
    # 日志级别关系映射
    level_relations = {
   
        'debug': logging.DEBUG,
        'info': logging.INFO,
        'warning': logging.WARNING,
        'error': logging.ERROR,
        'crit': logging.CRITICAL
    }

    def __init__(self, filename, level='info', when='D', backCount=3, fmt='%(asctime)s - %(filename)s[line:%('
                                                                          'lineno)d] - %(levelname)s: %(message)s'):
        self.logger = logging.getLogger(filename)

        self.log_colors_config = {
   
            'DEBUG': 'cyan',
            'INFO': 'white',
            'WARNING': 'yellow',
            'ERROR': 'red',
            'CRITICAL': 'red',
        }
        formatter = colorlog.ColoredFormatter(
            '%(log_color)s[%(asctime)s] [%(name)s] [%(levelname)s]: %(message)s',
            log_colors=self.log_colors_config)

        # 设置日志格式
        format_str = logging.Formatter(fmt)
        # 设置日志级别
        self.logger.setLevel(self.level_relations.get(level))
        # 往屏幕上输出
        sh = logging.StreamHandler()
        # 设置屏幕上显示的格式
        sh.setFormatter(formatter)
        # 往文件里写入#指定间隔时间自动生成文件的处理器
        th = handlers.TimedRotatingFileHandler(filename=filename, when=when, backupCount=backCount, encoding='utf-8')
        """
        #实例化TimedRotatingFileHandler
        #interval是时间间隔,backupCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种:
        # S 秒
        # M 分
        # H 小时、
        # D 天、
        # W 每星期(interval==0时代表星期一)
        # midnight 每天凌晨    
        """
        # 设置文件里写入的格式
        th.setFormatter(format_str)
        # 把对象加到logger里
        self.logger.addHandler(sh)
        self.logger.addHandler(th)


log_path = DevConfig().log_path
Log = LogHandler(log_path   '/all.log', level='debug')
# get_info_log = LogHandler(log_path   '/info.log', level='info')
# get_error_log = LogHandler(log_path   '/error.log', level='error')


if __name__ == '__main__':
    msg = '111'
    # log = LogHandler('all.log', level='debug')
    Log.logger.debug('debug')
    # log.logger.info(msg)
    # log.logger.warning('警告')
    # log.logger.error('报错')
    # log.logger.critical('严重')
    # LogHandler('error.log', level='error').logger.error('error')
    # is_open = ReadIni(node='log').get_value("run")
    # get_info_log.logger.info("111")

依赖库

代码语言:javascript复制
> pip install PyUserInput 	 	
> pip intsall pyperclip
代码语言:javascript复制
# -*- coding: utf-8 -*-
# @Time    : 2019/2/15 8:54 AM
# @Author  : 余少琪
# @FileName: basepage.py
# @email   : 1603453211@qq.com

from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# DevConfig 是我自己存放项目文件地址的,你们可以结合自己的业务单独创建
from common.setting import DevConfig
import datetime
from Outputs.logs.log import Log
from selenium.webdriver.support.select import Select
from time import time, sleep
from pykeyboard import PyKeyboard
import pyperclip
from pymouse import PyMouse
import os
import platform


class BasePage:

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

    # 等待元素可见
    def wait_ele_visible(self, loc, img_name, timeout=20, poll_fre=0.5):
        """

        :param loc: 元素
        :param timeout:
        :param poll_fre:
        :return: 等待元素

        """
        start_time = time()

        try:
            WebDriverWait(self.driver, timeout, poll_frequency=poll_fre).until(EC.visibility_of_element_located(loc))

            Log.logger.info("等待{0}元素可见, 用时{1:.2f}秒.".format(loc, time()-start_time))

        except:
            self.save_page_shots(img_name)
            Log.logger.error("等待{0}元素可见失败, 用时{1:.2f}秒.".format(loc, time()-start_time))
            raise

    def send_pictures(self, loc, img_name, file):
        """
        上传图片
        :param loc:
        :param img_name:
        :param file: 图片路径
        :return:
        """
        start_time = time()
        platform_system = platform.system()
        if platform_system  == 'Windows':
            try:

                self.get_element(loc, img_name).send_keys(file)

                Log.logger.info("开始上传文件,文件路径{0}, 用时{1:.2f}秒.".format(file, time() - start_time))

            except:
                self.save_page_shots(img_name)
                Log.logger.error("上传图片失败!图片路径{0}".format(file))
                raise

        elif platform_system == 'Linux' or platform_system == "Darwin":

            def _is_China(file):

                # 判断文件名称中是否包含中文
                for ch in file:
                    if u'u4e00' <= ch <= u'u9fff':
                        return True

                return False

            try:
                if _is_China(file) is True:
                    Log.logger.error("文件路径中不允许包含中文字符!请修改文件命名。文件路径:{0}".format(file))

                if _is_China(file) is False:
                    Log.logger.info("开始上传图片, 图片路径:{0}".format(file))

                    self.click_element(loc, img_name)
                    k = PyKeyboard()
                    # k.press_keys(['Command', 'Shift', 'E'])

                    m = PyMouse()
                    filepath = '/'
                    # 模拟键盘点击 Command   Shift   G
                    k.press_keys(['Command', 'Shift', 'G'])

                    # 获取当前屏幕尺寸
                    x_dim, y_dim = m.screen_size()
                    m.click(x_dim // 2, y_dim // 2, 1)

                    # 复制文件路径开头的斜杠/
                    pyperclip.copy(filepath)

                    # 粘贴斜杠/
                    k.press_keys(['Command', 'V'])
                    # 输入文件全路径进去
                    k.type_string(file)
                    sleep(2)
                    k.press_key('Return')
                    sleep(2)
                    k.press_key('Return')
                    sleep(2)

            except:
                self.save_page_shots(img_name)
                Log.logger.error("上传图片失败!图片路径{0}".format(file))
                raise

        else:
            Log.logger.error("{0}操作系统不支持上传文件功能!".format(get_current_system()))

    # 精准 link text 定位
    def accurate_link_text(self, text, img_name):
        start_time = time()
        Log.logger.info("开始通过 link text 进行定位, 定位内容:{0},用时{1:.2f}秒.".format(text, time()-start_time))
        try:
            self.driver.find_element_by_link_text(str(text)).click()
        except:
            self.save_page_shots(img_name)
            Log.logger.error("精准 link text 定位失败!,用时{0:.2f}秒.".format(time()-start_time))

    # 等待元素可点击
    def wait_ele_clickable(self, loc, img_name, timeout=20, poll_fre=0.5):
        """

        :param loc: 元素
        :param timeout:
        :param poll_fre:
        :return: 等待元素

        """
        start_time = time()
        Log.logger.info("{0} 等待 {1} 元素可点击, 用时{2:.2f}秒.".format(img_name, loc, time()-start_time))

        try:
            WebDriverWait(self.driver, timeout, poll_frequency=poll_fre).until(EC.element_to_be_clickable(loc))

        except:
            self.save_page_shots(img_name)
            Log.logger.error("等待元素可点击失败:{0}, 用时{1:.2f}秒.".format(loc, time()-start_time))
            raise

    # 元素存在
    def wait_page_contain_element(self):
        pass

    # 查看元素
    def get_element(self, loc, img_name):
        start_time = time()
        Log.logger.info("在 {0} 查找元素:{1}, 用时{2:.2f}秒.".format(img_name, loc, time()-start_time))
        try:
            ele = self.driver.find_element(*loc)

        except:
            self.save_page_shots(img_name)
            Log.logger.error("查找元素{0}失败!用时{1:.2f}秒.".format(loc, time()-start_time))
            raise

        else:
            return ele

    # 查找所有元素
    def get_elements(self, loc, img_name):
        start_time = time()
        Log.logger.info("在 {0} 查找元素:{1}, 用时{2:.2f}秒.".format(img_name, loc, time()-start_time))
        try:
            ele = self.driver.find_elements(*loc)

        except:
            self.save_page_shots(img_name)
            Log.logger.error("查找元素{0}失败!用时{1:.2f}秒.".format(loc, time()-start_time))
            raise

        else:
            return ele

    # 点击元素
    def click_element(self, loc, img_name, timeout=20, poll_fre=0.5):
        start_time = time()
        self.wait_ele_visible(loc, img_name, timeout, poll_fre)
        ele = self.get_element(loc, img_name)
        Log.logger.info("对 {0} 点击元素:{1},用时{2:.2f}秒. ".format(img_name, loc, time()-start_time))

        try:
            ele.click()
        except:
            self.save_page_shots(img_name)
            Log.logger.error("点击元素失败, 元素内容:{0}".format(loc))
            raise

    # 元素的输入属性
    def input_text(self, loc, value, img_name, timeout=20, poll_fre=0.5):
        start_time = time()
        self.wait_ele_visible(loc, img_name, timeout, poll_fre)
        ele = self.get_element(loc, img_name)
        Log.logger.info("对 {0} 将元素 {1} 输入文本值:{2}, 用时{3:.2f}秒.".format(img_name, loc, value, time()-start_time))
        try:
            ele.send_keys(value)
        except:
            self.save_page_shots(img_name)
            Log.logger.error("元素输入文本失败!内容: {0}, 用时{1:.2f}秒. ".format(value, time()-start_time))
            raise

    # 获取元素属性
    def get_ele_attribute(self, loc, attr_name, img_name,  timeout=20, poll_fre=0.5):
        start_time = time()
        self.wait_ele_visible(loc, img_name, timeout, poll_fre)
        ele = self.get_element(loc, img_name)
        Log.logger.info("在 {0} 获取元素 {1} 的 {2} 属性, 用时{3:.2f}秒".format(img_name, loc, attr_name, time()-start_time))
        try:
            value = ele.get_attribute(attr_name)

        except:
            self.save_page_shots(img_name)
            Log.logger.error("获取元素属性{0}失败!用时{1:.2f}秒".format(loc, time()-start_time))

        else:
            Log.logger.info("属性值为:{}".format(value))
            return value

    # 获取属性的文本内容
    def get_ele_text(self, loc, img_name,  timeout=20, poll_fre=0.5):
        start_time = time()
        self.wait_ele_visible(loc, img_name, timeout, poll_fre)
        ele = self.get_element(loc, img_name)
        Log.logger.info("在 {0} 获取元素 {1} 的文本值, 用时{2:.2f}秒 ".format(img_name, loc, time()-start_time))
        try:
            text = ele.text
        except:
            self.save_page_shots(img_name)
            Log.logger.error("获取元素文本值失败!文本值内容:{0}, 用时{1:.2f}秒".format(loc, time()-start_time))

        else:
            Log.logger.info("属性值为:{0}, 用时{1:.2f}秒".format(text, time()-start_time))
            return text

    # 截图
    def save_page_shots(self, img_name):

        # 将图片存储在 OutPuts 的 screenshot 的文件中,唯一不同的是图片的命名

        file_name = "{}_{}.png".format(img_name, datetime.datetime.now())

        # 判断文件如果不存在,则创建存放一个文件夹
        # DevConfig.screenshots_path是我自己创建的文件夹路径,你们可以自己创建一个
        if not os.path.exists(DevConfig.screenshots_path):
            os.mkdir(DevConfig.screenshots_path)

        self.driver.save_screenshot(DevConfig.screenshots_path   "/"   file_name)
        Log.logger.info("页面图片保存在:{}".format(DevConfig.screenshots_path   "/"   file_name))

    # 切换至iframe页面
    def switch_to_ifaram(self, loc, img_name):
        Log.logger.info("切换ifram页面:{}".format(loc))
        try:
            WebDriverWait(self.driver, 20).until(EC.frame_to_be_available_and_switch_to_it(loc))

        except:
            self.save_page_shots(img_name)

            Log.logger.error("切换至iframe页面失败!")

    # 纵向滚动条操作
    def vertical_scroll_bar(self, img_name, *postion, type=None):
        """

        :param img_name:
        :param postion: 滚动条的坐标,为 postion 为 0,则表示滑动到顶部,为 1000 时则表示滑动到底部
                        横向滑动时,需要同时传 x ,y 轴的坐标
        :param type: 纵向 :portrait; 横向 :transverse
        :return:
        """
        Log.logger.info("开始滑动滚动条,滚动位置为{0}".format(postion))
        try:
            global js
            # 判断滚动类型为纵向
            if type == 'portrait' or type is None:
                js = 'var action=document.documentElement.scrollTop='   ",".join(map(str, postion))

            # 判断滚动类型为横向
            elif type == 'transverse':
                js = "window.scrollTo"   str(postion)   ";"

            self.driver.execute_script(js)

        except:
            self.save_page_shots(img_name)
            Log.logger.error("滚条条滑动失败!")

    # 富文本框输入
    def rishtext(self, content, loc, img_name, loc_type="Id"):
        """
        :param content: 富文本输入内容
        :param loc: 元素名称
        :param img_name:
        :param loc_type: Id , ClassName, Name,TagName
        :return:
        """
        try:

            Log.logger.info("开始输入富文本内容:{0}".format(content))

            js = 'document.getElementBy'   str(loc_type)   "("   str(
                loc)   ")"   'contentWindow.document.body.innerHTML="%s"' % content
            self.driver.execute_script(js)

        except:
            self.save_page_shots(img_name)
            Log.logger.error("富文本框输入失败!")

    # 下拉框定位
    def drop_down_menu_positioning(self, loc, img_name, type, value):
        """

        :param loc:  loc = driver.find_element_by_id("kw")
        :param img_name:
        :param type: 下拉框定位类型,index 为坐标元素定位,value 为值定位,text则为文字定位
        :param value:
        :return:
        """

        Log.logger.info("开始进行下拉框定位,定位类型:{0}, 定位内容:{1}".format(type, value))
        try:

            select = Select(loc)
            if type == "index":
                select.select_by_index(value)

            elif type == 'value':
                select.select_by_value(value)
            elif type == 'text':
                select.select_by_visible_text(value)

        except:
            self.save_page_shots(img_name)
            Log.logger.error("下拉框定位失败!")


if __name__ == '__main__':
    pass

元素定位我们已经封装好了,那么我们来看看具体的运行情况,下面我们以打开百度地址为例,然后在百度输入框中,输入“selenium”进行查询

代码语言:javascript复制
    from  selenium import webdriver
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
    
    # 打开百度地址
    driver.get("http://www.baidu.com")
    
    # 实例化BasePage,然后传入driver对象
    basepage = BasePage(driver)`在这里插入代码片`
    
    # 因为是输入内容,所以我们这里调用封装好的input_text()方法进行调用
    basepage.input_text((By.NAME, "wd"), 'selenium', '再输入框中输入内容')
    basepage.click_element((By.ID, 'su'), '点击搜索')

可以看到我们已经搜索成功了,下面我们再来看看日志的情况

查看日志信息

以上这些就是元素定位封装的方法,basepage中我只封装了一些常用的定位方法,selenium中元素定位的方式有很多,如果还有其他需要的,可以自己单独在进行封装。关于元素封装我也是基于自己对于自动化的学习和理解整理出来的,如果大家有什么更好的方式,欢迎随时讨论~

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/100660.html原文链接:https://javaforall.cn

0 人点赞