Backend Development 54 min read

Precise Testing Platform: Architecture, Recommendation Engine, and Graph Database Implementation

The Precise Testing Platform combines a recommendation engine—featuring a link analyzer, diff analyzer, and knowledge base—to automatically construct detailed method‑call graphs from source code, extract HTTP and Dubbo APIs, handle reflections and inheritance, and store billions of nodes in Nebula Graph, thereby eliminating blind, missed, and redundant tests while boosting coverage and reducing testing costs.

DeWu Technology
DeWu Technology
DeWu Technology
Precise Testing Platform: Architecture, Recommendation Engine, and Graph Database Implementation

This article introduces the concept of precise testing, a comprehensive technical system designed to improve software testing quality and efficiency by reducing blind, missed, and redundant tests.

It outlines the overall architecture of the "DeWu Precise Testing Platform", which consists of a recommendation engine (including a link analyzer, diff analyzer, knowledge base, and recommendation engine) and a graph database for storing method call chains.

Core Components of the Recommendation Engine

The link analyzer builds a complete method call graph from source code using Abstract Syntax Trees (AST) generated by JavaParser. It extracts HTTP and Dubbo interface information from annotations such as @RequestMapping , @PostMapping , and custom Dubbo configurations.

Key code for extracting HTTP paths from annotations:

if (an.isSingleMemberAnnotationExpr()) {
SingleMemberAnnotationExpr san = an.asSingleMemberAnnotationExpr();
Expression valueExpr = san.getMemberValue();
String path = InfoUtils.getHttpPathByValueExpression(valueExpr);
setHttpPath(info, path);
}
else if (an.isNormalAnnotationExpr()) {
NormalAnnotationExpr nan = an.asNormalAnnotationExpr();
List
childNodes = nan.getChildNodes();
for (Node cn : childNodes) {
MemberValuePair mvp = (MemberValuePair) cn;
String name = mvp.getName().getIdentifier();
if (name != null && (name.equals("value") || name.equals("path"))) {
Expression valueExpr = mvp.getValue();
String path = InfoUtils.getHttpPathByValueExpression(valueExpr);
setHttpPath(info, path);
break;
}
}
}

The engine also resolves method signatures, handling overloaded methods, generic types, and missing symbols by providing fallback strategies (e.g., MyResolvedMethodDeclaration and MyReferenceTypeImpl ).

static String methodSign(ResolvedMethodLikeDeclaration r, TypeInfo typeInfo) {
try {
return r.getQualifiedSignature().replace(" extends java.lang.Object", "");
} catch (UnsolvedSymbolException e) {
String sign = getPocketBottomQualifiedSignature(r, typeInfo);
return sign.replace(" extends java.lang.Object", "");
}
}

Reflection calls are specially handled by detecting the three‑step pattern ( Class.forName → Class.getMethod → Method.invoke ) and reconstructing the actual target method using expression value extraction.

if (callInfo.sign.contains("java.lang.Class.forName(java.lang.String)")) {
reflectionCallParser = ReflectionCallParser.addForNameCallExpr(callInfo, expr, reflectionCallParser, usageInfo);
} else if (callInfo.sign.contains("java.lang.Class.getMethod(java.lang.String, java.lang.Class<...>)")) {
reflectionCallParser = ReflectionCallParser.addGetMethodCallExpr(callInfo, expr, reflectionCallParser, usageInfo);
} else if (callInfo.sign.contains("java.lang.reflect.Method.invoke(")) {
reflectionCallParser = ReflectionCallParser.addInvokeCallExpr(callInfo, expr, reflectionCallParser, usageInfo);
}

To capture abstract calls (e.g., interface or superclass method invocations), the platform expands the call graph by traversing inheritance and interface hierarchies, ensuring that overridden and abstract methods are correctly linked.

API Detection and Path Construction

The system marks Dubbo services by parsing dubbo-provider.xml and matches classes, implemented interfaces, and super‑classes against the configuration. HTTP API paths are assembled from project‑level prefixes, class‑level prefixes, and method‑level annotations, following Spring's precedence rules.

if (classInfo.dApi) {
methodInfo.isApi = true;
methodInfo.apiProtocol = "dubbo";
methodInfo.apiPath = classInfo.dInterface + "::" + methodInfo.name;
return;
}
if (!typeInfo.hasRestControllerAnnotation) return;
if (memberInfo.httpPath != null && typeInfo.httpPathPrefix != null) {
methodInfo.isApi = true;
methodInfo.apiProtocol = "http";
methodInfo.apiPath = linkHttpPath(typeInfo.httpPathPrefix, memberInfo.httpPath);
return;
}

Graph Database Storage

Because the call graph can contain billions of nodes and edges, the platform stores the data in Nebula Graph, a distributed high‑performance graph database. Two vertex types are defined: JMethodTag (method vertices) and JClassTag (class/interface vertices). Four edge types model relationships: class‑to‑class inheritance/implementation, method‑to‑method calls and overrides, method‑to‑class ownership, and change‑to‑method edges for incremental recommendations.

Example ORM definitions (simplified):

class JMethodTag(Tag):
__NAME_PREFIX__ = 'tjm_'
vid = Vid('vid', String, nullable=False, comment='Vertex ID')
name = Field('name', String, nullable=False, comment='Short name')
sign = Field('sign', String, nullable=False, comment='Full signature', index_len=50)
api = Field('api', Bool, default=False, nullable=False, comment='Is API')
aPtl = Field('aPtl', String, default='', nullable=False, comment='API protocol')
aPath = Field('aPath', String, default='', nullable=False, comment='API path')
calls = Field('calls', String, default='', nullable=False, comment='Called methods')
usages = Field('usages', String, default='', nullable=False, comment='Methods that call this')

Typical queries retrieve all methods belonging to changed classes, locate API entry points, and traverse up to 50 hops to find reachable API methods.

GO 1 TO 50 STEPS FROM {vid_str} OVER ejmm_call REVERSELY WHERE properties(edge).api == true YIELD DISTINCT src(edge);

Finally, the article summarizes the benefits of precise testing, emphasizing its ability to reduce testing costs, improve coverage, and provide reliable risk assessment for releases.

JavaASTbackend developmentcode analysisgraph databaseprecise testingReflection
DeWu Technology
Written by

DeWu Technology

A platform for sharing and discussing tech knowledge, guiding you toward the cloud of technology.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.