最近碰到一个小需求, 需要根据调用拦截打印出的日志数据, 生成测试代码(主要是构造测试数据), 用于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",...,
)
)
}
分享到:
相关推荐
Log4j是Apache的一个开源项目,主要用于日志记录,提供了灵活的日志配置,允许开发者根据需求调整日志输出的级别和格式。Log4j2作为Log4j的升级版本,它在性能、可配置性和可扩展性上有了显著提升,同时也修复了Log4...
在本场景下,"springboot中的 动态代理的选择测试代码"涉及到的是如何在Spring Boot环境中利用Java或CGLIB动态代理来实现方法拦截、事务管理、日志记录等跨切面关注点。下面我们将深入探讨这一主题。 首先,让我们...
这是Android Studio为每个模块生成的项目文件,包含了模块的配置信息,如源代码路径、构建类型和产品Flavor等。 7. **gradle.properties**: 此文件存储了Gradle构建过程中的属性设置,例如用户ID、密码或者特定...
Spring框架使得组件间的耦合度降低,提高了代码的可测试性和可维护性。 **SpringMVC** 是Spring框架的一部分,专门用于处理Web请求。它采用模型-视图-控制器(MVC)设计模式,实现了请求和业务逻辑的解耦,使开发者...
4. **单元测试**:为了验证拦截器的功能,我们编写单元测试类`RepeatSubmitTest`,使用`@SpringBootTest`注解启动整个Spring Boot应用,并通过`@Autowired`注入`RepeatSubmitController`进行测试。 ```java @Run...
1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合...
**Log4j** 是一款强大的日志记录框架,用于收集、分类和存储应用程序运行时的信息。它提供了丰富的日志级别(如DEBUG、INFO、WARN、ERROR等),可以根据需求调整日志输出的详细程度。Log4j还可以配置不同的Appenders...
系统中活动用户状态监控,监视当前系统CPU,内存,磁盘,磁盘等相关信息,基于元素UI在线表单设计及生成Vue代码。 前一级统一异常拦截处理,统一输出异常,避免繁琐的判断 高效率开发,使用代码生成器可以一键生成前...
Log4j的配置文件控制了日志的输出行为,可以在开发、测试和生产环境中方便地调整日志级别,帮助调试和监控应用程序。 在这个“struts2+freemarker+log4j”的项目中,可能包含了以下内容: 1. **Struts2的配置文件...
4. **Log4j**:Log4j是Apache的一个开源日志框架,用于记录应用程序运行过程中的各种信息。通过配置,可以选择不同的日志级别(如DEBUG、INFO、WARN等),方便调试和排查问题。在分布式系统中,日志管理尤为重要,...
通用Mapper和MyBatis的代码生成工具进一步提高了开发效率,Log4j用于日志记录,拦截器增强了系统功能,而Layui则提供了用户友好的界面。这个框架组合广泛应用于企业级Java Web开发,深受开发者喜爱。
CodeBehind插件可能是Struts2的一个扩展,它可能提供了将业务逻辑代码与视图分离的能力,增强代码的可维护性和可测试性。Struts2的核心特性包括拦截器、动作类、结果类型等,使得开发者可以更加规范和高效地构建Web...
10. **测试与调试**:使用JUnit进行单元测试,确保代码质量;而Struts的调试工具如Log4j可以帮助开发者追踪和调试应用程序。 通过这个商品销售源代码,开发者不仅可以学习到Struts框架的基本用法,还能了解到一个...
Castle.DynamicProxy2.dll是Castle项目的一部分,提供动态代理功能,这在测试中用于模拟对象或者拦截方法调用,对于测试驱动开发(TDD)和模拟对象非常有用。 nunit.framework.dll是NUnit测试框架的库,这是一个广泛...
3. **SQL动态标签**:MyBatis允许我们在XML映射文件中使用动态SQL,例如`<if>`、`<choose>`、`<when>`、`<otherwise>`等,使得SQL语句可以根据条件灵活生成,提高代码复用性。 4. **结果映射**:MyBatis提供了强大...
* 测试代码生成 第七节:插件扩展 * 插件机制 * 插件原理 * 在 spring 配置文件中注册插件 * 分页插件 * 执行分析插件 * 性能分析插件 第八节:性能分析插件 * 用途 * 执行sql分析 * 打印引入依赖 * 更改配置...
12. **单元测试**:使用JUnit或TestNG编写单元测试,确保代码质量,减少bug。 13. **异常处理**:合理的异常处理机制能够优雅地处理错误情况,提供友好的用户反馈。 14. **文件上传与下载**:如果系统包含附件管理...
10. **部署与测试**:源代码还可能包含部署描述符(如web.xml),以及自动化测试的代码,如JUnit和Mockito的使用。 通过对这些知识点的深入理解和实践,开发者可以更有效地利用提供的源代码进行学习,提升自己的...
2. **崩溃日志(Crash Log)**:当应用程序因异常情况导致崩溃时,系统会生成崩溃日志,其中包含导致崩溃的堆栈跟踪信息、错误代码、设备状态等关键数据,用于分析问题原因。 3. **本地存储**:App崩溃日志可以被...
9. **单元测试**:包含了大量的单元测试用例,这些测试用例覆盖了框架的各个功能,有助于理解MyBatis的工作流程。 通过对这些源代码的阅读和学习,开发者不仅可以掌握MyBatis的基本用法,还能了解到其背后的实现...