游戏测试 【测试工具】配置表检查的另一种思路

特尔斯特 · 2021年04月29日 · 最后由 千奇百怪果冻冻 回复于 2022年11月16日 · 5832 次阅读

之前采用 Pytest 做了一个配置表检查工具,最近看了一些 “数据驱动” 和 “关键字驱动” 的相关文章,有了一些新的思路,并用这种思想重新做了一个配置表检查工具,只需要 3 个 py 文件 + 一张 xlsx 表格就可以实现,比用 pytest 来实现更简单更高效。并且不了解代码的人也可以写用例,只需要懂一点正则表达式即可。
效果展现:

关键字:
check_null 为空检查
check_repeat 重复检查
check_regex 格式检查,后面的参数配对应的正则表达式
check_reference 索引检查,后面的参数配对应的表格和列名
check_range 值域检查,后面的参数配值域

运行脚本直接把结果写入另外一张表格中,如图

代码只有 3 个 py 文件
XlsxReader.py 用于读表格
ConfigCheckerXlsx.py 用来写检查逻辑
ConfigCheckDriver.py 用来执行检查

XlsxReader.py

#coding=utf-8
import xlrd

xlsx_path = r"E:\Common\Config"

class XlsxReader:
    def __init__(self,xlsx_name):
        self.path = xlsx_path
        self.xlsx_name= xlsx_name
        self.ignore_lines = 3;#忽略的行数,一般配置表前3行有特殊作用不做配置,所以读取数据时忽略这3行
        self.xl = xlrd.open_workbook(self.path+"\\"+self.xlsx_name)
        #self.xl = xlrd.open_workbook(self.xlsx_name)
        self.sheet = self.xl.sheet_by_index(0)
        self.column_name_list  = self.get_head_list() #得到表的列名(表头)
        self.num_rows = self.sheet.nrows  # 获取总行数

    #得到列名也就是第一行(表头)
    def get_head_list(self):
        return self.sheet.row_values(0)


    #通过列名得到某一列的数据
    def get_column_list_by_name(self,name):
        #把名字转换成index再通过self.sheet.col_values(index)得到整列数据
        head_list = self.get_head_list()
        if name in head_list:
            index  = head_list.index(name)
            return self.sheet.col_values(index,self.ignore_lines)
        else:
            print("该配置表没有%s列"%name )

    #得到一行的数据
    def get_row_list_by_index(self,index):
        return self.sheet.row_values(index)





if __name__ == '__main__':
    xlrd = XlsxReader("ChapterConfig.xlsx")
    res = xlrd.get_column_list_by_name("id")
    print(res)

ConfigCheckerXlsx.py

import pytest
import re
from collections import Counter
from xlutils.copy import copy
import xlrd
import xlwt
import time

class ConfigCheckerXlsx:
    def __init__(self,check_table):
        #一般配置表前3行是表头,不参与检查
        self.ignore_row = 3
        self.check_table =  check_table
        self.oldwb = xlrd.open_workbook(check_table)
        self.newWb = copy(self.oldwb)
        self.newWbs = self.newWb.get_sheet(0)


    # 索引检查
    def check_reference(self, list_checK,column_name, com_table_name,com_column_name,com_column_list,row,column):
        # list_check 被检查的列
        # com_talbe_name 需要索引到的表名
        # com_column_name 需要索引到的列名
        print("check reference")
        res_list= list()
        for index, sub in enumerate(list_checK):
            if sub not in com_column_list:
                res_list.append(index+self.ignore_row+1)
        if(len(res_list)==0):
            self.newWbs.write(row, column, "pass")
        else:
            self.newWbs.write(row,column,'{0}列    第{1}行  无法索引到  {2}表的{3}列'.format(column_name,res_list,com_table_name,com_column_name))

    # 为空检查
    def check_null(self, list_check,column_name,row,column):
        print("check null")
        res_list= list()
        self.newWbs.write(row, column,"pass")
        for index, sub in enumerate(list_check):
            if(len(str(sub).strip()) == 0):
                res_list.append(index+self.ignore_row+1)
        if (len(res_list) == 0):
            self.newWbs.write(row, column, "pass")
        else:
            self.newWbs.write(row,column,' {0}列  第{1}行  为空 '.format(column_name,res_list))

    # 重复检查
    def check_repeat(self, list_check,column_name,row,column):
        print("check repeat")

        if(list_check==None):
            self.newWbs.write(row,column, "{0}为空".format(list_check))
        else:
            if (len(set(list_check)) == len(list_check)):#set() 的长度和原来的相等说明没有重复项
                self.newWbs.write(row,column, "pass")
                return

        counter_list_check = Counter(list_check)
        repeat_item = [key for key,value in counter_list_check.items() if value>1] #得到重复元素的列表
        res_str= str()
        for item in repeat_item:
            item_repeat_row = [i+self.ignore_row+1 for i,sub in enumerate(list_check) if sub == item]
            res_str+='   {0}列   {1}   在{2}行重复\n  '.format(column_name,item,item_repeat_row)
        self.newWbs.write(row,column ,res_str)


    # 格式检查
    # 检查指定列是否符合给定的正则表达式
    def check_regex(self,list_check,regex ,column_name,row,column):
        print("check regex")
        self.newWbs.write(row, column, 'pass')
        res_list= list()
        for index, sub in enumerate(list_check):
            #sub= str(sub)
            pattern = re.compile(regex)
            if pattern.fullmatch(sub)==None:
                res_list.append(index+self.ignore_row+1)

        if (len(res_list) == 0):
            self.newWbs.write(row, column, "pass")
        else:
            self.newWbs.write(row, column, ' {0}列  第{1}行  格式有误'.format(column_name, res_list))

    # 值域检查
    def check_range(self,list_check,min,max,column_name,row,column):
        #被检查的内容必须是数值
        #todo 考虑字符也可以装换成数字
        res_list = list()

        for  index,sub  in enumerate(list_check):
            if len(str(sub).strip()) != 0:
                num = float(sub)
            if(num<min or num>max or len(str(sub).strip()) == 0):
                res_list.append(index+self.ignore_row+1)
        if(len(res_list)==0):
            self.newWbs.write(row,column,'pass')
        else:
            self.newWbs.write(row,column,' {0}列  第{1}行  超出预期范围[{2} ,{3}]'.format(column_name,res_list,min,max))


    def save_xls(self):
        time_str= time.time()
        now = time.strftime("%Y%m%d_%H%M%S", time.localtime(time.time()))
        self.newWb.save("result/result"+now+".xls")



ConfigCheckDriver.py

from Tools.XlsxReader import  XlsxReader
from Tools.ConfigBase import  ConfigBase
from Tools.ConfigCheckerXlsx import  ConfigCheckerXlsx
import pytest

config_path= "E:\Common\Config\\"

configChecker =ConfigCheckerXlsx("E:\Common\Config\checklist.xlsx")
xlsxReader_checklist = XlsxReader("checklist.xlsx")

for  index  in  range(1,xlsxReader_checklist.num_rows):
    check_row  =  xlsxReader_checklist.get_row_list_by_index(index)

    table_name =check_row[0]
    xlsxReader_table = XlsxReader(table_name)

    column_name_list =list()
    if check_row[1] == "ALL":
        column_name_list = xlsxReader_table.get_head_list()
    else:
        column_name_list =check_row[1].split(";")

    # action  关键字驱动
    action  = check_row[2]
    for index_column_name_list,column_name in  enumerate(column_name_list):
        list_check = xlsxReader_table.get_column_list_by_name(column_name)
        if action == "check_repeat":
            configChecker.check_repeat(list_check, column_name, index, 4+index_column_name_list)
        elif action == "check_null":
            configChecker.check_null(list_check,column_name,index,4+index_column_name_list)
        elif action == "check_range":
            range_list = check_row[3].split(";")
            configChecker.check_range(list_check,float(range_list[0]),float(range_list[1]),column_name,index,4+index_column_name_list)
        elif action == "check_regex":
            regex = check_row[3]
            configChecker.check_regex(list_check,regex,column_name,index,4+index_column_name_list)
        elif action == "check_reference":
            com_table_info = check_row[3].split(";")
            com_table_name = com_table_info[0]
            com_column_name = com_table_info[1]
            com_column_list =XlsxReader(com_table_name).get_column_list_by_name(com_column_name)
            configChecker.check_reference(list_check,column_name,com_table_name,com_column_name,com_column_list,index,4+index_column_name_list)



        configChecker.save_xls()

共收到 5 条回复 时间 点赞

赞,很好的思路!
改进下让不懂正则的人也能使用,那就是锦上添花了!

水山 想做好的配置表检查工具 中提及了此贴 09月13日 17:55

你们有投入使用了嘛,实战效果咋样

吴晓世 回复

策划懒得用,我也不想和他纠结,出问题自己背锅吧

我面试时,面试官聊过这种思路,不知道是不是你们公司

特尔斯特 回复

不如就加到策划的打表工具里,检测不过打不出表来😏

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册