Mobile Development 9 min read

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.

Xianyu Technology
Xianyu Technology
Xianyu Technology
Precise Code Instrumentation and Test Case Recommendation for Flutter Using Aspectd

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_test

During 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.

FlutterAspectDaoptestingCode Instrumentation
Xianyu Technology
Written by

Xianyu Technology

Official account of the Xianyu technology team

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.