背景:前面完善了swagger直接生成excel测试用例之后,在开发阶段,接口变更评率较高,如每次开发更新接口文档之后,都需要重新生成用例,如此不知道如何来对比两份excel测试用例哪里做了改动,故而需要做两个excel的文件对比,秉着向优秀程序员学习的态度,百年老梗:百度啊!

 完了,发现百度也真是个巨坑,每次搜索的代码,都要费老大劲的完善,不过不管怎么说,还是要感谢别人的辛勤付出!真心喜欢上了重构,改造别人的代码就是有成就感!

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @desc    : 对比接口excel

import xlrd
import time
import config
from utils.HandleLogging import log

#往日志文件中追加内容函数#个人感觉这个很鸡肋,实际以日志输出就可以
def write_file(filename,content):
    '''
           写入文件,将对比不同的测试用例写入日志
    '''
    with open(filename,'a',encoding='utf-8') as file: #以追加方式打开日志文件
        time_now= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())  #系统时间格式化
        file.write(time_now+':'+content+'\n')      #写入内容

def read_excel(ori_path,tar_path,sub_name):#
    '''读取excel表格'''
    success=0        #匹配一致数量
    fail=0           #匹配不一致数量
    origin_xls={} #存储源xls文件
    target_xls={} #比对的xls文件
    wb_ori=xlrd.open_workbook(ori_path) #打开原始文件
    wb_tar=xlrd.open_workbook(tar_path) #打开目标文件

    startime=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())    #获取系统当前时间并格式化为格式
    log.info('【{},开始对比,{}】...'.format(ori_path.split("\\")[-1],tar_path.split("\\")[-1]))
#     log.info(startime,"开始比对//。。。") #请用格式化输出
    #将对比结果重新写入一个日志文件
    logname='log_'+startime[0:10]+'.log' #截取日期年月日构成日志文件名

#创建日志文件,如果文件存在则清空内容,不存在则创建,如果需要同时批量比对多张表,可以考虑将日志文件名作为参数传入
    with open(logname,'w',encoding='utf-8') as logfile:    
        logfile.writelines(startime+':【开始比对】...'+'\n')
        
    try:
#         比较excel的表名
        sheet_ori=wb_ori.sheet_by_name(sub_name)
        sheet_tar=wb_tar.sheet_by_name(sub_name)
        if sheet_ori.name==sheet_tar.name:
            #sheet表名
            if sheet_ori.name==sub_name:
            #先将数存入dictionary中dictionary(rows:list)
            #第一行存储表头
            #源表取一行数据与目标表全表进行比对如果表中存在主键可以用主键进行索引
            #数据从excel第3行开始
                for rows in range(0,sheet_ori.nrows):
                    orign_list=sheet_ori.row_values(rows) #源表i行数据
                    origin_xls[rows]=orign_list     #源表写入字典
                for rows in range(0, sheet_tar.nrows):
                    target_list = sheet_tar.row_values(rows)  # 目标表i行数据
                    target_xls[rows] = target_list  # 目标表写入字典
#                     第一行表头比较
                if origin_xls[0]  == target_xls[0]:
                    log.info('表头一致')
                    
                orinum = len(origin_xls)
                log.info("源文件数量:{}".format(orinum)) 
                tarnum = len(target_xls)
                log.info("目标文件数量:{}".format(tarnum))
                
                mult_num=tarnum if tarnum<=orinum else orinum
#                 if num >= num1: #判断两个xlsx对象数据大于0即可
                if mult_num>0:
#                     文件行数的大小比较,谁行数少就返回来,因为多出来的数据无法对比
#                     如果目标行数小于源文件行数,则遍历最大行数的数据
                    xlsxfile=origin_xls if tarnum<orinum else target_xls
#                     为了不管传入对比xlsx文件的位置,都以最少的行数对比次数
                    for ori_num in xlsxfile:
                        log.info("开始对比第:{}条".format(ori_num+1))
                        flag='false'   #判断是否一致标志
#                         for tar_num in target_xls:#in的对象,写一个条件判断,哪个文件少就返回哪个
#                         xlsxfile=origin_xls if num1>=num else target_xls
#                         循环次数由最外成的for循环控制,返回最少的行数
                        for tar_num in target_xls:
                            if origin_xls[ori_num]==target_xls[tar_num]:
                                flag='true'
                                break              #如果匹配到结果退出循环
                        if flag=='true':           #匹配上结果输出后台日志
                            log.info(' 文件:{}, row:{}is ok'.format(ori_path,ori_num+1))
                            success+=1
                        else:                      #匹配不上将源表中行记录写入txt
                            log.info('文件:{} row:{} is different'.format(ori_path,ori_num+1))
                            fail+=1
                            data=origin_xls[ori_num]
                            try:
                                data1=target_xls[ori_num]
                            except:
#                                 避免对比最小行数,之后索引不足,
                                log.info("{}最大只有这么多行:{}".format(tar_path,tar_num))
                            logstr='文件:{},【不一致】row<{}>:{} vs {}'.format(ori_path,ori_num+1,data,data1)
                            write_file(logname,logstr)
                    logstr='【比对完成】总记录数:{:d}条,一致:{:d}条,不一致:{:d}条'.format(ori_num + 1,success,fail)
                    log.info(' 【{}】比对结束'.format(sheet_ori.name))
                    log.info(' 总记录数:{}条,一致:{}条,不一致:{}条'.format(ori_num+1,success,fail))
                    write_file(logname,logstr)
                else:
                    for tar_num in target_xls:
                        flag = 'false'  # 判断是否一致标志
                        for ori_num in origin_xls:
                            if target_xls[tar_num] == origin_xls[ori_num]:
                                flag = 'true'
                                break  # 如果匹配到结果退出循环
                        if flag == 'true':  # 匹配上结果输出后台日志
                            log.info(' 文件: {} row:{} is ok'.format(tar_path,tar_num + 1))
                            success += 1
                        else:  # 匹配不上将源表中行记录写入txt
                            log.info(' 文件: {}, row:{} is different'.format(tar_path,tar_num + 1))
                            fail += 1
                            data = target_xls[tar_num]
                            logstr = '【不一致】row<' + str(tar_num + 1) + '>:' + str(data)
                            write_file(logname, logstr)
                    logstr = '【比对完成】总记录数:{:d}条,一致:{:d}条,不一致:{:d}条'.format(tar_num + 1, success, fail)
                    log.info("【{}】比对结束".format(sheet_tar.name))
                    log.info('总记录数:{}条,一致:{}条,不一致:{}条'.format(tar_num + 1, success, fail))
                    write_file(logname, logstr)
        else:
            log.info("{}子表名不一致".format(sub_name))
    except Exception as e:
        log.info(e)
        raise e
    
if __name__ == '__main__':
    
    read_excel(config.data_path+"test123.xlsx",config.data_path+"test.xlsx","Sheet1")