Precise Code Instrumentation and Test Case Recommendation for Flutter Using Aspectd
The team enhanced the Dart AOP framework Aspectd to expose compile‑time module, class, method, and argument data, insert branch‑level instrumentation, and enable bulk injection via a configuration file, providing precise code coloring and automated test‑case recommendation for large‑scale Flutter applications.
Background: Xianyu’s quality team needed a way to accurately measure the impact range of code changes and ensure no test cases were missed in their large‑scale Flutter client. Existing native solutions (iOS/Android) were mature, but Flutter lacked a code‑coloring and test‑case association mechanism. The team evaluated Aspectd, an AOP framework for Dart, as a potential solution.
Problem: The initial use of Aspectd to report executed modules, classes, and functions revealed several limitations:
Inject aspects could not obtain join‑point information.
Inject aspects did not support regex‑based bulk insertion.
Aspectd could not weave at statement level (e.g., if, while).
Test engineers had to study the hooked code beforehand, which is cumbersome for unfamiliar projects.
Technical Solution: The team extended Aspectd to provide pre‑defined variables that expose module, class, method, and argument information at compile time. The generated pseudo‑code looks like:
Procedure procedure = methodNode;
Class methodClass = procedure.parent;
/*** Pre‑defined variable generation: function info ***/
final List
entries =
[];
entries.add(MapLiteralEntry(StringLiteral("library"), StringLiteral(library.importUri.toString())));
entries.add(MapLiteralEntry(StringLiteral("class"), StringLiteral(methodClass.name)));
entries.add(MapLiteralEntry(StringLiteral("method"), StringLiteral(procedure.name.text)));
entries.add(MapLiteralEntry(StringLiteral("args"), StringLiteral(procedure.function.positionalParameters.toString())));
final MapLiteral methodLiteral = MapLiteral(entries);
final VariableDeclaration methodInfo = VariableDeclaration("methodInfo", initializer: methodLiteral);
tmpStatements.add(methodInfo);
/*** Pre‑defined variable generation: parameter info ***/
Library core = _libraryMap['dart:core'];
final List
paramsEntries =
[];
final MapLiteral paramsLiteral = MapLiteral(paramsEntries);
final VariableDeclaration paramsInfo = VariableDeclaration("params", initializer: paramsLiteral);
tmpStatements.add(paramsInfo);
... (additional code for parameter handling) ...Branch‑level Instrumentation: To capture which branch (if/switch/try, etc.) is executed, the extended Aspectd traverses the function body statements and inserts custom code into each branch statement. Example pseudo‑code:
final List
statements = body.statements;
final int len = statements.length;
for (int i = 0; i < len; i++) {
final Statement statement = statements[i];
if (statement is IfStatement) {
insertStatementsToIfStatement(aopInsertStatements);
}
if (statement is SwitchStatement) {
insertStatementsToSwitchStatement(aopInsertStatements);
}
if (statement is TryStatement) {
insertStatementsToTryStatement(aopInsertStatements);
}
// ... other branch types ...
}Bulk Injection via Configuration: Because the client codebase is split into many independent libraries, the team introduced a configuration file that maps target modules to injection actions, allowing test engineers to specify only the module and action without knowing internal class or method names. Sample configuration:
fish_redux:
- type: 'inject'
module: package:fwn_idlefish/CodeExecutionLog.dart
action: CodeExection.Log
lineNum: 0
flutter_boost:
- type: 'call'
module: package:fwn_idlefish/CodeExecutionLog.dart
action: CodeExection.print
fish_test:
- type: 'inject'
module: package:fwn_idlefish/CodeExecutionLog.dart
action: CodeExection.Log
color: true # code coloring for all branches of fish_testDuring the transform phase, Aspectd reads this configuration, builds an AopItemInfo list, and applies the specified injections to the matching libraries and procedures.
Summary: The extended Aspectd framework now supports precise code coloring, branch‑level instrumentation, and bulk injection for Flutter clients. It has been deployed in Xianyu’s precise testing project, enabling automatic collection of executed functions, environment data, and test‑case recommendation. Future work includes using the same infrastructure for client‑side traffic replay and coverage analysis.
Xianyu Technology
Official account of the Xianyu technology team
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.