live_test_view 0.2.1
live_test_view: ^0.2.1 copied to clipboard
Watch Flutter widget tests render live in your editor. Companion package for the Live Test View VS Code extension.
live_test_view #
Streams rendered frames from your Flutter widget tests so the Live Test View VS Code extension can replay them live in an editor panel. On its own — without the extension driving it — this package does nothing observable at all.

Install #
flutter pub add --dev live_test_view
dart run live_test_view:install
The installer writes test/flutter_test_config.dart for you. If that file already exists, it won't be overwritten — the installer instead prints the one-line change needed to wrap your existing testExecutable:
Future<void> testExecutable(FutureOr<void> Function() testMain) =>
liveTestView(() => yourExistingSetup(testMain));
What the config file does #
flutter_test_config.dart is a special file package:test looks for and, if present, uses to wrap every test in the directory. The generated file looks like this:
import 'dart:async';
import 'package:live_test_view/live_test_view.dart';
Future<void> testExecutable(FutureOr<void> Function() testMain) =>
liveTestView(testMain);
liveTestView checks the LIVE_TEST_VIEW environment variable. When it's unset (every normal flutter test run, including CI), it just calls testMain() and returns — see "the silence invariant" below. When the Live Test View extension runs a test, it sets LIVE_TEST_VIEW=1 in the child process's environment; liveTestView then attaches a persistent frame callback that snapshots the render tree after every paint, encodes each snapshot as PNG, and writes it to stdout as a single line prefixed with ##LTV## followed by JSON (v, seq, testTimeMs, w, h, png). The extension's test runner reads these lines back out; you never need to parse them yourself.
The silence invariant #
This package is designed so that adding it can never change your test suite's behavior or output under a plain flutter test run. With LIVE_TEST_VIEW unset, liveTestView is a pass-through: no frame callback is registered, nothing is written to stdout, and the only cost is one environment-variable check. This is covered by an end-to-end test that asserts a run without the flag is byte-for-byte identical, stdout included, to a run without the package wired in at all.
Companion extension #
This package only captures and streams frames — it has no UI of its own. Pair it with the "Live Test View" VS Code extension, which adds the "▶ Live View" CodeLens, runs your tests, and renders the captured frames in a scrubbable timeline panel.
Fonts #
flutter test renders all text with a placeholder font (every glyph a solid box) unless something loads real fonts in. When LIVE_TEST_VIEW=1, liveTestView does this for you before testMain runs, via loadRealFonts():
- Roboto — resolved from the running Flutter SDK's own cache (
bin/cache/artifacts/material_fonts), so it works with any SDK install without the project needing to bundle it. - Every family in the test build's
FontManifest.json— this covers project fonts declared underflutter: fonts:inpubspec.yaml, package-bundled fonts, andMaterialIcons. Each family is loaded independently; if one fails (bad asset, malformed manifest entry), a##LTV##warning line is emitted naming it and the rest of the manifest still loads.
google_fonts is not covered by either mechanism and can't be made to work here. It isn't in FontManifest.json — it fetches its .ttf over HTTP the first time GoogleFonts.xxx() is called, as a fire-and-forget Future the widget doesn't await. Two things make this unrecoverable inside flutter test:
flutter_testinstalls a globalHttpOverridesthat makes every HTTP request in the process return a fake 400, so the fetch always fails.- The fetch is initiated inside
flutter_test's FakeAsync-controlled zone (during widgetbuild()). Bypassing the HTTP mock and awaiting the request from a real zone afterward (binding.runAsync) doesn't help — it deadlocks, because the pending Future is entangled with a fake clock that nothing is advancing anymore. There's no sequencing trick around this from outsidegoogle_fonts.
If a project needs google_fonts text to render in Live Test View, bundle the actual .ttf files as assets and set GoogleFonts.config.allowRuntimeFetching = false in the app. That routes google_fonts through the local asset bundle instead of the network — the same FontManifest.json-backed path above, which already works. This is google_fonts' own recommended setup for golden/widget tests generally: https://pub.dev/packages/google_fonts#offline-support-and-cache
Requirements #
- Flutter >= 3.16
- Dart SDK >= 3.2
License #
MIT — see LICENSE.