场景:最近一个游戏版本发布后玩家发现游戏中的某个英雄在佩戴一把特殊 n 星武器后射程发生了异常,从远程变成了近战。一查是因为策划改动这个武器的技能配置,可是 QA 并不知道,因为没有口头告知或者有需求单,理论上所有的配置表变动都应该有对应的需求单,并且需求单要转到对应的 QA 进行测试,实际上大部分公司由于策划的个人素质或者管理方面的原因并不能做到这一点,结果是出了问题又来反问 “为什么没有测到?"或者默认把锅盖到 QA 头上,升职加薪年终奖都会受到影响,说多了容易 emo ~

解决方案:把游戏上次上线的节点到当前节点的配置表 SVN 变更输出到一个文件夹中用来在上线前做最后的检查和确认,有疑议再找策划确认,一定程度上能降低上述问题再发生。

分析:
1.配置表文件夹可能是多层级的,所以这里不能只按只有一层的文件夹来处理
2.配置表有可能是当前版本周期 (当前版本周期指上次发布到线上的最终 svn 版本号~这次版本最后发布的 svn 版本号) 创建的,diff 一个比它小的 svn 版本号会什么都没有
3.在处理了 2 的前提下,配置表可能是当前版本周期创建的同时没有任何变更,这种情况下我希望能把这个新增的且没有任何变更的配置文件复制到输出文件夹中和其他 log 文件一同检查避免某种风险。

算法:
取某个文件的最初的 svn 版本号和最后的 svn 版本号和要比对的版本号(comp_version) 对比,
if ( 最后的 svn 版本号< = comp_version):
    说明这个文件在当前版本周期根本没变过就不用检查了
else (最后的 svn 版本号 > comp_version):
     if ( 最初的 svn 版本号== 最后的 svn 版本号):
       说明这个文件是” 新增的 “同时” 没有任何变更 “的文件,把它复制出去
    else ( 最初的 svn 版本号!= 最后的 svn 版本号):
       说明这个文件在 comp_version 后是有变更的,读 diff log 并保存

最终效果:
配置表目录:

输出的报告目录:

完整代码:

#coding=utf-8
import os
import datetime
import re


config_path=r"E:\Trunk2ForTest\Client\TEST\Assets\Editor\QA\JsonFile\\"  #配置表路径
out_put_path ="E:\svncheck\\"#报告存放路径
comp_version="1000" #需要比对的版本号

#得到当前目录下所有json的文件名
def get_jsons():
    jsons =[]
    for root,dirs,files, in  os.walk(config_path):
        for file in files:
            if file.split('.')[-1]=="json":#筛选出json格式的文件,因为是Unity项目还会有很多.meta文件
                jsons.append(os.path.join(root, file))
    return jsons


#创建一个标记时间和comp_versoin的文件夹,用来保存报告
def make_report_path():
    current_date = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    print(current_date)
    report_path =out_put_path+"%s\\"%(current_date+"_"+comp_version)
    if not os.path.exists(report_path):
        os.makedirs(report_path)
    print("报告文件路径:"+report_path)
    return report_path

#检查svn变更输出日志
def check_json_svn_change(jsons,report_path):

    for json in jsons:
        def create_level_path(json):
            dir_and_json_name = json.split(config_path)[-1]
            json_name = dir_and_json_name.split('\\')[-1]
            dir = dir_and_json_name.rstrip(json_name)
            deep_report_path = report_path + "\\" + dir
            if (dir and not os.path.exists(deep_report_path)):
                os.makedirs(deep_report_path)
            return deep_report_path,dir_and_json_name

        init_version,last_versoin = get_init_version_and_last_version(json)
        #print(init_version,last_versoin)
        svn_comp_version = comp_version
        #如果最后的版本号不大于比对的版本号(comp_version),说明当前版本区间这个文件根本没有任何变化,可以跳过不做任何处理
        if last_versoin<svn_comp_version or last_versoin==svn_comp_version:
            continue
        elif last_versoin==init_version:#如果最后的版本号和最初的版本号相等,说明这个文件创建后没有做任何变更,如果这个版本号比comp_version大按照需求把它复制出来检查
            #考虑到有多级目录的情况,需要创建对应的目录
            temp_path= create_level_path(json)[0]
            cmd ="copy %s %s"%(json,temp_path)
            print(cmd)
            os.system(cmd)
        else:
            dir_and_json_name = create_level_path(json)[1]
            dir_and_json_name = dir_and_json_name.replace(".json",".log")
            svn_comp_version = svn_comp_version if comp_version> init_version else init_version
            svn_cmd = "svn diff -r %s %s > %s"%(svn_comp_version,json,report_path+dir_and_json_name)
            print(svn_cmd)
            os.system(svn_cmd)



#得到某个文件的最初svn版本号和最终svn版本号
def get_init_version_and_last_version(file):
    svn_log = os.popen('svn log %s'%file)
    svn_log = svn_log.read()
    pattern = "r(\d+) \|"
    res = re.findall(pattern,svn_log)
    return res[-1],res[0]



if __name__ == "__main__":
    report_path = make_report_path()
    jsons = get_jsons()
    print(jsons)
    check_json_svn_change(jsons,report_path)
    os.system("explorer %s"%out_put_path)#直接打开输出的文件夹,方便查看

测试用例执行结果:

**** 最开始想要用 pysvn 来实现,可惜在网上找了几个版本都有各种问题不好解决,所以直接用 os.system 来操作 svn 指令。


↙↙↙阅读原文可查看相关链接,并与作者交流