`

根据log拦截信息生成测试代码

阅读更多
最近碰到一个小需求, 需要根据调用拦截打印出的日志数据, 生成测试代码(主要是构造测试数据), 用于debug分析问题. 因为我们的调用数据比较复杂, 因此构造起来比较麻烦, 而根据log里面的调用信息直接生成测试数据, 相对来说会容易一些.
主要用groovy脚本来处理, 重点是字符串的解析, 而解析主要借助正则表达式.
感觉类似这种解析应该大同小异吧. 算是一个以后处理类似问题的一个参考:

String log = """ItemServiceImpl.save(arg1=1602962222, arg2=2018265146, arg3=ItemUpdateDO[...])"""
   public void parse(String log){  
        // 对日志里面的()[]{}进行调整以便切分
        String[] adjustedLog = adjustSeperator(log)
        
        // 对日志中的无用参数信息进行清理
        List<String> argList = processArgument(adjustedLog)
        
        // 对括号进行处理
        replaceBrace(argList)
        
        // 输出最终结果
        printResult(argList)
    }
    
    private String[] adjustSeperator(String log) {
        String replacedResult = "";
        log.eachLine { replacedResult += it }
        // 在"{}[]()"前后加","以便后面切分
        replacedResult = (replacedResult =~ /\(/).replaceAll("(,")
        replacedResult = (replacedResult =~ /\)/).replaceAll(",),")
        replacedResult = (replacedResult =~ /\{/).replaceAll("{,")
        replacedResult = (replacedResult =~ /\}/).replaceAll(",},")
        replacedResult = (replacedResult =~ /\[/).replaceAll("[,")
        replacedResult = (replacedResult =~ /\]/).replaceAll(",],")
        
        return replacedResult.split(",");
    }
    
    private List<String> processArgument(String[] fulls) {
        List<String> argList = []
        fulls.each{
            // 去掉空值
            if (it.equals("") || it ==~/.+=$/  || it ==~ /.*=null$/) {
                return;
            }
            // 去掉arg1, arg2...
            def arg = (it =~/arg[0-9]+=/).replaceAll("")
            
            // 将=替换成:
            arg = (arg =~ /=/).replaceAll(":")
            
            // 将{}替换成[]
            arg = (arg =~ /\{/).replaceAll("[")
            arg = (arg =~ /\}/).replaceAll("]")
            
            argList << arg
        }
        
        return argList
    }
    
    void replaceBrace(List<String> argList) {
        int recursiveLevel = 0; // 递归次数
        for(int i = 0; i <argList.size(); i++ ) {
            String arg = argList[i];
            if (argList[i]  ==~ /.*:*[a-zA-Z]+\[$/) {
                def matcher = (argList[i]  =~ /([a-zA-Z]+)(\[)$/)
                String className = matcher[0][1];
                argList[i] = matcher.replaceAll(" new ${className}(")
                continue
            }
            
            // 检查内部是否还有类定义
            if (argList[i]  ==~ /.*\[$/) {
                recursiveLevel ++
                continue
            }
            
            if (argList[i].equals("]")) {
                if (recursiveLevel==0) {
                    argList[i] = ")"
                }else {
                    recursiveLevel--
                }
            }
        }
    }
    
    private printResult(List argList) {
        // 要转换为String的属性列表
        List stringValueList = ["title", "pictUrl", "city", "prov", "lang", "sourceIp"]
        // 要去掉的属性列表
        List deleteFieldList = ["isCardCode", "isSupplier", "updateFeatureCc"]
        // 要替换的属性列表
        Map replaceFieldMap = [
                clientAppName:{String[] pair ->
                    return "${pair[0]}:ClientAppName.${pair[1].toUpperCase()}"
                }, 
                descriptionLength:{String[] pair ->
                    def len = new Integer(pair[1])
                    return """description:\"${"A".center(len, 'A')}\""""
                }]
        
        for(int i = 0; i < argList.size(); i ++) {
            def pair = argList[i].split(":")
            
            if (pair?.length == 2) {
                
                if (deleteFieldList.contains(pair[0])) {
                    continue;
                }
                
                if (replaceFieldMap.keySet().contains(pair[0])) {
                    argList[i] = replaceFieldMap[pair[0]].call(pair)
                }else {
                    // 凡是数字都转换成long类型
                    if (NumberUtils.isDigits(pair[1])) { 
                        argList[i] = "${pair[0]}:${pair[1]}L"
                    }
                    
                    if (stringValueList.contains(pair[0])) {
                        argList[i] = """${pair[0]}:\"${pair[1]}\""""
                    }
                }
            }else if (pair?.length == 1) {
                if (NumberUtils.isDigits(pair[0])) {
                    argList[i] = "${pair[0]}L"
                }
            }
            
            // 对class进行处理
            if (i == 0) {
                pair = argList[i].split(/\./)
                if (pair?.length == 2) {
                    pair[0] = pair[0].replaceAll(/(^Default)|(Impl$)/, "")
                    pair[0] = pair[0].replaceAll(/^./){ it.toLowerCase()     }
                    argList[i] = """${pair[0]}.${pair[1]}"""
                }
            }
            
            if (i == 0
            || i == (argList.size()-1)
            || i == (argList.size()-2)
            || argList[i] ==~ /.*\($/
            || argList[i] ==~ /.*\[$/
            || argList[i] ==~ /.*\{$/
            ) {
                println argList[i]
            }else {
                println "${argList[i]},"
            }
        }
    }
    
    // 得到的测试结果
    @Test void parsed() {
        itemService.save(
                1602962222L,
                2018265146,
                new ItemUpdateDO(
                description:"AAAAAAAAAAAAAAAAAAAA",
                title:"123455666",...,
                )
                )
    }
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics