第22章:python自动化——关键字驱动加Excel数据驱动案例

目录

一、整个案例的要求

二、案例结构的设计

1.web_keys.py文件的内容

2.test_data文件夹中excel测试用例数据准备

3.excel_read.py文件的内容

4.conf存放日志及其他的相关配置项

5.在main.py文件中将以上几个内容串联起来并运行

6.工程结构详情


一、整个案例的要求

  1. 熟悉上一章的基于Openpyxl实现的excel数据驱动

  2. 结合之前课程中所教的options类,日志类,关键字驱动类。实现一个单独的工程:

    1. 整个工程完全独立,新建立工程来实现

    2. 关键字驱动的底层结构

    3. 基于Excel进行测试用例和数据的管理

    4. 运行过程中,需要有日志的记录和显示

    5. 要清晰化的工程结构

    6. 源码需要有注释

    7. 断言结果需要亮眼显示,比如PASS则单元格为绿色,FAILED,单元格为红色

    8. 可以自我发挥想象,优化原有代码结构

    9. 整个工程通过main.py文件来实现自动化测试的执行,也可以通过命令行形态来实现执行。

二、案例结构的设计

完整的工程实现独立的UI自动化测试:
整体技术内容是基于关键字驱动的逻辑代码底层,关联到excel数据驱动形态,整个运行过程需要有日志记录。
web_keys:实现关键字驱动,实现UI自动化常用关键字的封装

test_data:存放测试数据管理所有的excel数据内容

excel_read:实现excel测试数据的读取与调用,基于openpyxl库来完成对excel数据的获取以及函数的调用。

conf:用于存放日志及其他的相关配置项

1.web_keys.py文件的内容

'''
    关键字驱动逻辑代码类:
        webUI的自动化是基于Selenium来实现的。Selenium就类似于一个巨大的商城。
        逻辑代码就类似于一个工具箱,需要什么东西就从Selenium商城里面取
        关键字驱动类就类似于创建一个工具类,将常用的操作行为进行封装,以方便后续的直接调用
        封装关键字的时候,要确保代码的复用性,要确保代码的维护性。
        逻辑代码在没有被调用的时候,一毛钱都不值
        没有十全十美的逻辑代码,也不要想着一次性把所有的内容都写完。用到什么就封装什么。因为在实际的常规
        测试中,很多操作行为在当前系统是用不上的。

        代码在执行过程中,很可能会出现异常,如果想要通过日志记录异常的话,可以选择在每个函数中添加
        log.  通过try...except将所有的异常信息,记录在log之中,这样报错信息就会记录在日志文件之中。
'''
import time
from logging import getLogger

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from conf import chrome_options

# 获取日志对象getLogger
log = getLogger()


# 用于将指定的浏览器对象进行实现。
def open_browser(type_):
    try:
        driver = getattr(webdriver, type_.capitalize())(options=chrome_options.options())
    except Exception as e:
        log.error(e)
        driver = webdriver.Chrome()
    return driver


# 关键字驱动类:逻辑代码实现
class WebKeys:
    # 构造函数
    def __init__(self, type_):
        # 实例化driver对象
        self.driver = open_browser(type_)
        self.driver.implicitly_wait(5)

    # 访问url
    def open(self, url):
        self.driver.get(url)

    # 元素定位:要满足不同的定位需求将定位到的元素进行返回,以便后续操作
    def locator(self, by, value):
        return self.driver.find_element(by, value)

    # 输入
    def input(self, by, value, txt):
        # self.driver.find_element(by, value).send_keys(txt)    # 不要这样写
        el = self.locator(by, value)
        el.clear()
        el.send_keys(txt)

    # 点击
    def click(self, by, value):
        self.locator(by, value).click()

    # 关闭
    def quit(self):
        self.driver.quit()

    # 强制等待
    def wait(self, time_):
        time.sleep(int(time_))

    # 显式等待:结合实际需要进行等待时长的变化
    def driver_wait(self, by, value, time_=5):
        WebDriverWait(self.driver, time_, 0.5). \
            until(lambda el: self.locator(by, value), message="显式等待失败")

    # 句柄切换
    def window_switch(self):
        handles = self.driver.window_handles
        self.driver.close()
        self.driver.switch_to.window(handles[1])

    # 句柄切换
    def window_switch_without_close(self):
        handles = self.driver.window_handles
        self.driver.switch_to.window(handles[1])

    # 断言文本是否被包含
    def assert_text_in(self, by, value, expected):
        try:
            reality = self.locator(by, value).text
            assert expected in reality, '断言失败:{}!={}\n预期结果为:{}\n实际结果为:{}'.format(expected, reality,
                                                                                               expected, reality)
            return True
        except Exception as e:
            log.error(e)
            return False

    # 元素悬停操作
    def hover_element(self, by, value):
        ActionChains(self.driver).move_to_element(self.locator(by, value)).perform()

    # 断言文本是否被包含
    def assert_equal(self, by, value, expected):
        try:
            reality = self.locator(by, value).text
            assert expected == reality, '断言失败:{}!={}\n预期结果为:{}\n实际结果为:{}'.format(expected, reality,
                                                                                               expected, reality)
            return True
        except Exception as e:
            log.error(e)
            return False


2.test_data文件夹中excel测试用例数据准备

test.xlsx的数据内容如下

test_fecmall.xlsx的数据内容如下

3.excel_read.py文件的内容

'''
    基于测试用例,实现关键字驱动类的调用,根据测试用例的步骤,自动执行对应的操作行为。
'''
import pathlib
from time import sleep

import openpyxl

from excel_read import excel_conf
from conf.logging_config import getLogger
from web_keys.web_keys import WebKeys


# 参数从str转换为dict的方法
def arguments(value):
    # 定义返回对象
    data = dict()
    # 如果value有值,需要进行数据处理
    if value:
        str_temp = value.split(";")
        for temp in str_temp:
            # by = id
            t = temp.split('=', 1)
            # {"by":"id"}
            data[t[0]] = t[1]
    return data



def excel_driver(case):
    # 获取log日志对象
    log = getLogger()
    # 获取excel文件路径
    # file = pathlib.Path(__file__).parents[1].resolve() / 'test_data' / 'test.xlsx'
    log.info('**************开始执行测试用例{}*********************'.format(case))
    # 获取excel文件
    excel = openpyxl.load_workbook(case)

    # 获取sheet页
    for name in excel.sheetnames:
        sheet = excel[name]
        log.info('当前正在执行{}页'.format(name))
        for values in sheet.values:
            # 判断是否为用例正文
            if type(values[0]) is int:
                # 日志信息输出
                log.info('当前正在执行:{}'.format(values[3]))
                # print(values)
                # 参数的处理
                data = arguments(values[2])
                # print(data)
                sleep(3)
                # 执行事件的处理
                # 实例化浏览器对象
                if values[1] == 'open_browser':
                    wk = WebKeys(**data)
                # 断言处理:因为断言的种类是多样化的,所以需要考虑用例写的什么断言方法,就调用对应的断言方法
                elif "assert" in values[1]:
                    # 因为断言是需要有结果反馈的,所以要根据断言成功或失败,对excel文件写入对应的pass或者failed
                    status = getattr(wk, values[1])(expected=values[4], **data)
                    # 根据断言状态对用例结果进行写入
                    if status:
                        excel_conf.pass_(sheet.cell(row=values[0] + 2, column=6))
                    else:
                        excel_conf.failed(sheet.cell(row=values[0] + 2, column=6))
                    excel.save(case)
                # 执行常规操作行为
                else:
                    getattr(wk, values[1])(**data)


# excel_driver()

为了实现在excel文件中将断言的结果进行写入excel表格和高亮显示,在excel_read.py文件下新建一个excel_conf.py文件,内容如下:

'''
 EXCEL文件的操作配置,用于定义excel的写入格式
'''
from openpyxl.styles import PatternFill, Font


# pass的写入配置
def pass_(cell):
    # 定义写入的内容
    cell.value = 'PASS'
    # 定义单元格的格式颜色和样式,绿色加粗
    cell.fill = PatternFill('solid', fgColor='AACF91')
    cell.font = Font(bold=True)


# failed的写入配置
def failed(cell):
    # 定义写入的内容
    cell.value = 'FAILED'
    # 定义单元格的格式颜色和样式,红色加粗
    cell.fill = PatternFill('solid', fgColor='FF0000')
    cell.font = Font(bold=True)


4.conf存放日志及其他的相关配置项

chrome_options.py浏览器配置文件代码

'''
    options类,将chrome浏览器的常用配置进行封装,便于后续driver对象的调用
'''
from selenium import webdriver


def options():
    options = webdriver.ChromeOptions()
    # 页面加载策略
    options.page_load_strategy = 'normal'
    # 窗体最大化
    options.add_argument('start-maximized')
    # 指定浏览器的启动坐标
    # options.add_argument('window-position=500,500')
    # 指定浏览器的窗体大小
    # options.add_argument('window-size=1200,800')
    # 去掉浏览器的自动化黄条:目前的阶段下已经不是那么有需要的了。
    options.add_experimental_option('excludeSwitches', ['enable-automation', 'enable-logging'])
    # options.add_experimental_option('disable-infobars')   # 只限于python2.7的版本有效,现在已经失效

    # 无头模式:不在桌面生成浏览器的运行,浏览器作为后台程序,静默后台运行。虽然无法肉眼看到,但实际上一切照旧,该运行的依旧会正常运行。可以减少测试设备的资源损耗。一般可用于持续集成中,虽然有可能出现错误。
    # options.add_argument('--headless')

    # 去掉账号密码保存弹窗
    prefs = {
        'credentials_enable_service': False,
        'profile.password_manager_enable': False
    }
    options.add_experimental_option("prefs", prefs)

    # 加载本地缓存信息:Selenium默认启动的浏览器是不会加载本地缓存的。
    '''
        1. 该功能可以实现验证码的绕过,但前提条件是需要提前手动登录一次(只对可以记住登录状态的网站有效)。
        2. 该功能可以起到一定程度的反爬效果,具体根据被访问系统的反爬机制而决定
        3. 该功能的使用,只能够在一个浏览器生效,如果在启动之前开启有其他的chrome浏览器,则该功能无法生效,会报错。一定要关闭所有浏览器以后再运行webdriver
    '''
    # 自动化测试不会处理验证码,因为验证码本身就是防止自动化脚本的。
    # options.add_argument(r"--user-data-dir=C:\Users\15414\AppData\Local\Google\Chrome\User Data")

    # 启动隐身模式
    # options.add_argument('incognito')

    # 去除控制台多余的信息:避免掉无用的信息内容
    # options.add_experimental_option('excludeSwitches', ['enable-logging'])

    # 去除控制台多余的信息手段二
    options.add_argument('--log_level=3')
    options.add_argument('--disable-gpu')
    options.add_argument('--ignore-certificate-errors')

    # 返回options对象
    return options

log_conf.ini配置项文件内容:

[loggers]
keys = root

[handlers]
keys = fileHandler,streamHandler

[formatters]
keys = simpleFormatter

[logger_root]
level = DEBUG
handlers = fileHandler,streamHandler

[handler_fileHandler]
class = FileHandler
level = DEBUG
formatter = simpleFormatter
args = ('log_conf.log','a','utf-8')

[handler_streamHandler]
class = StreamHandler
level = DEBUG
formatter = simpleFormatter

[formatter_simpleFormatter]
format =  %(levelname)s %(asctime)s %(filename)s %(module)s %(funcName)s %(lineno)s:%(message)s

调用logging.config模块,读取ini配置项,实现logging的配置与输出:

'''
    读取ini配置项,实现logging的配置与输出,要读取ini实现日志库的配置,则需要调用logging.config模块
'''

# 导入logging.config
import logging.config
import pathlib


# 将日志记录器封装为函数,如果需要,则直接调用,生成logger来进行日志的记录
def getLogger():
    # 获取日志配置文件
    file = pathlib.Path(__file__).parents[0]/'log_conf.ini'
    # 读取配置文件
    logging.config.fileConfig(file)
    # 获取记录器
    logger = logging.getLogger()
    return logger


5.在main.py文件中将以上几个内容串联起来并运行

'''
    整个工程的主入口,用于调用其他模块运行的唯一入口
    main.py只是用来作为启动的主入口,所有的内容都是从此处开始进行启动的。调用所有的函数、方法,运行所有的逻辑
    都是在这个文件下进行相互关联,通过这种方法可以很好的去约束工程启动状态。
'''
import os
import threading
from logging import getLogger
from excel_read import excel_read

if __name__ == '__main__':
    # 日志对象创建
    log = getLogger()
    # 想要将所有excel都运行,则需要在用例获取的时候进行一定的处理
    # 获取测试用例:读取指定路径下的测试用例,对获取的文件进行测试用例的判断,判断是否为测试用例
    cases = list()
    # 获取指定路径下的路径、文件、文件夹
    for path, dir, files in os.walk('./test_data/'):
        for file in files:
            # 文件名称与后缀名的获取
            file_name = os.path.splitext(file)[0]
            file_type = os.path.splitext(file)[1]
            # 确定文件实xlsx格式
            if file_type == '.xlsx':
                # 确定文件实测试用例(这里修改文件名,可以运行指定测试用例表格)
                if 'fecmall' in file_name:
                    # 保存测试用例路径
                    case_path = path + file
                    cases.append(case_path)
            else:
                log.error('文件类型错误,{}不是测试用例'.format(file))
    # 运行所有的测试用例
    for case in cases:
        excel_read.excel_driver(case)

    # 拓展知识:提高运行效率,可以通过多线程运行的方式来实现
    # 建立线程组
    # th = list()
    # # 基于用例数量,将所有的用例添加到线程组内
    # for case in cases:
    # th.append(threading.Thread(target=excel_driver,args=[case,]))
    # 运行线程组
    # for t in th:
    #     t.start()


6.工程结构详情

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值