Skip to content

[integration_profiling] Support programmatic performance integration tests on Flutter Web #180821

Open

Description

@lucavenir

Use case

Hi!

We're trying to write down an automated way to measure RAM usage of our applications on Flutter Web.

That way should be an integration test, but as the documentation says:

Recording performance timelines isn't supported on web. For performance profiling on web, see Debugging performance for web apps

... And the latter link redirects to a page that shows how to profile a web app. But that's not programmatic!

Proposal

Let this code work, even on Flutter Web:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('Counter increments smoke test', (tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(
      MyApp(items: List<String>.generate(10_000, (i) => 'Item $i')),
    );

    final listFinder = find.byType(Scrollable);
    final itemFinder = find.byKey(const ValueKey('item_500_text'));

    await binding.traceAction(() async {
      await tester.scrollUntilVisible(
        itemFinder,
        500.0,
        scrollable: listFinder,
      );
    }, reportKey: 'scrolling_timeline');
  });
}

class MyApp extends StatelessWidget {
  final List<String> items;
  const MyApp({super.key, required this.items});

  @override
  Widget build(BuildContext context) {
    const title = 'Long List';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(title: const Text(title)),
        body: ListView.builder(
          key: const Key('long_list'),
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(
                key: Key('item_${index}_text'),
                items[index],
              ),
            );
          },
        ),
      ),
    );
  }
}

or, in other words, make this cookbook available for Flutter Web users, as well.

Activity

  1. ladlaladka681-ops commented on Jan 11, 2026

    @ladlaladka681-ops

    import 'package:flutter/material.dart';
    import 'package:flutter_test/flutter_test.dart';
    import 'package:integration_test/integration_test.dart';

    void main() {
    final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();

    testWidgets('Counter increments smoke test', (tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(
    MyApp(items: List.generate(10_000, (i) => 'Item $i')),
    );

    final listFinder = find.byType(Scrollable);
    final itemFinder = find.byKey(const ValueKey('item_500_text'));
    
    await binding.traceAction(() async {
      await tester.scrollUntilVisible(
        itemFinder,
        500.0,
        scrollable: listFinder,
      );
    }, reportKey: 'scrolling_timeline');
    

    });
    }

    class MyApp extends StatelessWidget {
    final List items;
    const MyApp({super.key, required this.items});

    @OverRide
    Widget build(BuildContext context) {
    const title = 'Long List';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(title: const Text(title)),
        body: ListView.builder(
          key: const Key('long_list'),
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text(
                key: Key('item_${index}_text'),
                items[index],
              ),
            );
          },
        ),
      ),
    );
    

    }
    }

  2. added
    in triagePresently being triaged by the triage team
    d: api docsIssues with https://api.flutter.dev/
    f: integration_testThe flutter/packages/integration_test plugin
    frameworkflutter/packages/flutter repository. See also f: labels.
    platform-webWeb applications specifically
    c: proposalA detailed proposal for a change to Flutter
    c: new featureNothing broken; request for a new capability
    and removed
    in triagePresently being triaged by the triage team
    on Jan 12, 2026
  3. added
    team-webOwned by Web platform team
    and removed on Jan 13, 2026
  4. justinmc commented on Jan 13, 2026

    @justinmc
    Contributor

    @mdebbar Passing this to team-web, but let me know if it's more our thing.

  5. yjbanov commented on Jan 14, 2026

    @yjbanov
    Contributor

    traceAction does not measure RAM usage. How do you propose RAM usage is extracted? It's also not clear how to attribute RAM usage to the scope of one traceAction. Objects in memory can come from inside as well as outside the scope of traceAction.

    Have you considered writing a FlutterDriver test instead of the integration test? This way you can connect to the browser's debug protocol and extract performance data. I believe Chrome debug protocol supports extracting memory usage as well.

  6. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 14, 2026
  7. lucavenir commented on Jan 14, 2026

    @lucavenir
    Author

    traceAction does not measure RAM usage

    yes, I realized this only afterwards; but because of #180690 (comment), now I need benchmark performance in general (and not just RAM) to evaluate if introducing WASM is worth the trade.

    How do you propose RAM usage is extracted?

    I have no clue, but in desperation, I made something:

    import 'dart:js_interop';
    import 'dart:js_interop_unsafe';
    
    import 'package:flutter_test/flutter_test.dart';
    import 'package:integration_test/integration_test.dart';
    import 'package:web/web.dart' as web;
    
    void main() {
      IntegrationTestWidgetsFlutterBinding.ensureInitialized();
    
      testWidgets('testing testing one two testing', (tester) async {
        // TODO(?): show some UI
        final performance = web.window.performance;
        final memory = performance.getProperty("memory".toJS) as JSObject;
        final jsHeapSizeLimit = memory.getProperty("jsHeapSizeLimit".toJS);
        final totalJSHeapSize = memory.getProperty("totalJSHeapSize".toJS);
        final usedJSHeapSize = memory.getProperty("usedJSHeapSize".toJS);
    
        print("jsHeapSizeLimit: $jsHeapSizeLimit");
        print("totalJSHeapSize: $totalJSHeapSize");
        print("usedJSHeapSize: $usedJSHeapSize");
      });
    }

    Although I'm kinda lost in the fog. I'm not sure this is idiomatic or if it'll work at least decently to benchmark my application.

    Have you considered writing a FlutterDriver test instead of the integration test?

    yes, that's the above snippet; the point is that:

    1. it's undocumented, I came with this by reverse engineering the devtools
    2. I have no clue if it'll work, if there's anything to be aware of, and how to move forward
    3. everything seems "gelatinous" and "uncertain" (I have no idea what I'm doing)
  8. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 14, 2026
  9. lucavenir commented on Jan 16, 2026

    @lucavenir
    Author

    UPDATE; RE; memory usage. commenting here since "performance" (imho) also includes memory usage, and it could be useful to some.

    turns out window.performance.memory, while fully adopted by all browsers, is deprecated and might be unreliable.

    therefore, as mentioned by the mdn docs, we should use this API; however, it is marked as experimental and it requires cross-origin isolation (that's been fixed in master, see #180690 (comment)).

    by the way, this is exactly what the devtools are doing, I'd just love to do this programmatically in my own code - I guess borrowing a few LoC from the devtools is not that big of a deal.

  10. mdebbar commented on Jan 21, 2026

    @mdebbar
    Contributor

    Thanks for the proposal!

    I did some research online and found the same info that you found: the deprecated performance.memory and the new measureUserAgentSpecificMemory API. The latter has limited availability, but that may not matter if you run your tests in Chrome/Firefox (both have supported this API for a while).

    Unfortunately, we currently don't have plans to work on this, but I'll leave this issue open for tracking in case our plans change in the future.

  11. added
    P3Issues that are less important to the Flutter project
    triaged-webTriaged by Web platform team
    on Jan 21, 2026
  12. lucavenir commented on Jan 21, 2026

    @lucavenir
    Author

    I want to remark - Iin case anyone needs this: invoking .measureUserAgentSpecificMemory is totally doable on a cross-origin isolated chrome session, that works with flutter driver and that's reliable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projectc: new featureNothing broken; request for a new capabilityc: proposalA detailed proposal for a change to Flutterd: api docsIssues with https://api.flutter.dev/d: examplesSample code and demosf: integration_testThe flutter/packages/integration_test pluginframeworkflutter/packages/flutter repository. See also f: labels.platform-webWeb applications specificallyteam-webOwned by Web platform teamtriaged-webTriaged by Web platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions