点击上方蓝字关注我们吧
每一次底层服务的变动都牵动着QA同学的神经(这次又改了啥?),咨询开发当前版本影响到哪些接口或功能点时,通常得到的回答是就改了一点点或者变动挺大,建议全部回归测试。是否有一种更精确、可量化的方式来度量是改了“一点点”还是“亿点点”呢?基于此我们做了“精准测试”的尝试。
在做测试效率提升时,我们发现一种可以让代码“讲话”的测试流程,可以为QA提供指引,让测试策略更透明、更精准的测试手段,对于这种测试手段方式我们称之为精准测试。
结合网易传媒项目的特点,目前精准测试的最终技术选型为java-callgraph+全链路(网易传媒项目线上问题的追溯定位平台)+Neo4j+jenkins+overmind(测试流程平台),其中overmind触发jenkins的job进行提测版本和master分支的代码diff,最后将提测版本影响的接口邮件给业务测试同学。
在精准测试中,如何获取方法与方法之间的调用链路呢?我们引入开源框架java-callgraph,该工具可以通过静态或动态方式获取java项目的方法调用关系图。java-callgraph的开源地址:https://github.com/gousiosg/java-callgraph。
编译
java-callgraph工具用maven构建的,安装maven并使用mvn install进行打包,打包后再target目录下会生成3个jar包:
javacg-0.1-SNAPSHOT.jar:静态和动态调用图生成的标准jar
javacg-0.1-SNAPSHOT-static.jar:静态调用图生成器
javacg-0.1-SNAPSHOT-dycg-agent.jar:动态调用图生成器
java -jar javacg-0.1-SNAPSHOT-static.jar lib1.jar lib2.jar...。其中lib1.jar lib2.jar...为要执行的项目jar包,除了可以直接解析jar包,还可以解析war包。
M:class1:<method1>(arg_types) (typeofcall)class2:<method2>(arg_types)表示class1的method1调用了class2中的method2
private String getMethodParams(String className,String methodName){
StringBuilder result = new StringBuilder(); try{ ClassPool pool = ClassPool.getDefault(); ClassClassPath classPath = new ClassClassPath(this.getClass()); pool.insertClassPath(classPath); CtMethod cm = pool.getMethod(className, methodName); // 使用javaassist的反射方法获取方法的参数名 MethodInfo methodInfo = cm.getMethodInfo(); CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); result.append(cm.getName()).append("("); ……….. CtClass[] pTypes = cm.getParameterTypes(); String[] paramNames = new String[pTypes.length]; ………. }catch(Exception e){ e.printStackTrace();} return result.toString(); }
获取到数据后,如何存储数据可以方便我们回溯查找呢?RDBMS数据库不太方便表示
非结构化连接数据,而且即使将此类数据存储到RDBMS数据库中,检索或遍历性能也会较差。但图形DBMS存储这种连接数据非常简便,将数据作为节点存储在内部,通过关系连接相邻节点,这样检索或遍历是非常快的。
Neo4j是一个世界领先的开源图形数据库,图形数据库数据模型主要包括节点、关系和属性3类构建块,其中圆圈表示节点,箭头表示关系且关系是有方向性的。我们可以用Properties(键值对)来表示Node数据如下所示。
{ "name":"/api/v1/elephant/cindex/batch/xxInterface.do", "project": "elephant" }
同时Neo4j提供了Cypher查询图形数据,Cypher是描述性的图形查询语言、语法简单,功能强大。Cypher提供了“模式”查询方式,模式的格式是:使用()标识节点,使用[]标识关系。查询模式包括节点模式、关系模式、关联节点模式和变长路径模式,精准测试常用后两种。
目前传媒后台的重要项目已基本全接入了精准测试,以跟贴项目展开精准测试的执行流程如下图所示:
MATCH ownership = shortestPath((a:InterfaceNode)-[*0..]->(b:MethodNode{name:"A"})) WHERE NOT()-[:has]->(a) RETURN head(nodes(ownership)).name AS interface
一个大版本的提测可能会影响到非常多的方法或接口,如果精准测试报告中只是统一给出所有受影响的接口会导致看起来比较混乱。将受影响的接口按优先级进行分类,对业务测试同学展开测试工作会更加友好。