testdrive 0.1.0 copy "testdrive: ^0.1.0" to clipboard
testdrive: ^0.1.0 copied to clipboard

Flutter SDK for TestDeck. Captures HTTP, logs, navigation, and exceptions from debug builds.

TestDrive

testdrive capybara mascot wearing a construction helmet and holding a steering wheel

Flutter SDK for TestDeck - stream HTTP, logs, navigation, and errors from your debug app.

pub package pub likes pub points tests license platforms

The SDK runs inside your debug build and reports to the TestDeck desktop. No HTTPS proxy, no CA on the device.

Features #

  • HTTP capture via HttpOverrides - every dart:io HttpClient is wrapped, including packages that use the default Dart IO client. Pre-TLS, so cert pinning is irrelevant.
  • Log capture - debugPrint is wrapped automatically; TestDrive.log() for explicit structured entries; TestDrive.developerLog() as a drop-in for dart:developer.log.
  • Navigation capture - a drop-in NavigatorObserver records push / pop / replace / remove with route names and JSON-safe arguments.
  • Error capture - FlutterError.onError and PlatformDispatcher.instance.onError are chained; your existing handlers still fire.
  • Zero third-party dependencies - only Dart SDK libraries plus Flutter.
  • Never blocks your app - non-blocking emit, a 128-event reconnect buffer, and full-jitter exponential backoff. If the desktop isn't running, events buffer and flush on reconnect.
  • Rate limited - a default 200 events/s cap keeps a debugPrint flood from swamping the transport.
  • Size-capped bodies - request/response bodies are tee'd into a 1 MB (configurable) buffer that never disturbs your app's own stream.
  • NDJSON-over-TCP wire protocol with a version field for forward compatibility.

Platform Support #

Platform Transport Status
Android adb reverse (TCP loopback) Supported
Web - Not supported (dart:io HttpOverrides unavailable)

Getting Started #

Installation #

dependencies:
  testdrive: ^0.1.0

Or run:

flutter pub add testdrive

Basic Usage #

import 'package:flutter/foundation.dart';
import 'package:testdrive/testdrive.dart';

void main() {
  // Guard with kDebugMode so the SDK never ships to production.
  if (kDebugMode) TestDrive.init(appName: 'My App');
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorObservers: [TestDrive.navigator()],
      home: const HomeScreen(),
    );
  }
}

appName is just the label shown in the TestDeck desktop. It defaults to 'unknown'; the SDK does not auto-detect the package name (that would add a platform-channel dependency).

Usage #

Signals #

Signal How it is captured
HTTP HttpOverrides.global wraps every HttpClient - method, URL, headers, bodies, status, duration.
Logs debugPrint wrapped + TestDrive.log() + TestDrive.developerLog().
Navigation TestDrive.navigator() added to MaterialApp.navigatorObservers.
Errors FlutterError.onError + PlatformDispatcher.instance.onError, chained.

Structured logs #

TestDrive.log(
  'submit pressed',
  level: LogLevel.info,
  tag: 'checkout',
  payload: {'items': 3, 'total': 42.99},
);

dart:developer.log #

Swap developer.log(...) for the drop-in so entries land in the TestDrive Logs tab. It forwards to the real developer.log, so DevTools and the console are unaffected.

// before:  developer.log('fetched user', name: 'auth', level: 900);
TestDrive.developerLog('fetched user', name: 'auth', level: 900);

Transparent interception of arbitrary developer.log() calls would require the VM Service (vm_service), which this zero-dependency package avoids. Use the drop-in.

Timeline markers, timing & lifecycle #

Drop named markers onto the timeline to correlate app milestones with HTTP / logs / navigation, and measure how long a block takes. Both route through the log stream with a dedicated tag (event / timing), so they're filterable in the Logs tab.

TestDrive.event('checkout_started', payload: {'items': 3, 'total': 42.99});

final user = await TestDrive.timed('load_user', () => api.fetchUser());

App lifecycle transitions (resumed / inactive / paused / hidden / detached) are captured automatically under the lifecycle tag - handy for seeing exactly when the app went to the background. Disable with TestDrive.init(captureLifecycle: false).

Transport #

Events stream over TCP to 127.0.0.1:9876 (configurable). The TestDeck desktop runs adb reverse tcp:9876 tcp:9876 automatically so the device's 127.0.0.1:9876 reaches the host's listener. If the desktop isn't running, the SDK buffers up to 128 events and reconnects with full-jitter exponential backoff - your app is never blocked.

API Reference #

Method Description
TestDrive.init() Install HTTP / log / error hooks. Call once in main(), guarded by kDebugMode. Idempotent.
TestDrive.navigator() Drop-in NavigatorObserver for MaterialApp.navigatorObservers.
TestDrive.log() Emit an explicit structured log entry.
TestDrive.event() Drop a named timeline marker (tag event) for milestone correlation.
TestDrive.timed() Measure a sync/async block and emit its duration (tag timing).
TestDrive.developerLog() Drop-in for dart:developer.log - forwards to the real call and captures it.
TestDrive.detach() Restore previous globals and close the transport (mostly for tests).
TestDrive.status Runtime diagnostics: connected, buffered, dropped, flushed.
TestDrive.isInitialized Whether init() has run.

Caveats #

  • Debug mode only. TestDrive.init() no-ops in release builds. Still guard your call with if (kDebugMode) so the intent is explicit and tree shaking can remove debug-only wiring.
  • No redaction. Captured payloads contain the literal request / response. Review before sharing exported sessions externally.

Limitations #

  • Native plugin HTTP that runs outside Dart is invisible to HttpOverrides.
  • HTTP from a background isolate is not captured - HttpOverrides.global and debugPrint are per-isolate.
  • WebSocket handshakes are captured; subsequent frames are not parsed in v1.
  • HTTP/2 multiplexing works, but each captured event is one request.

Contributing #

Contributions are welcome. Please open an issue before submitting a pull request.

License #

MIT License - Copyright (c) 2026 Ricky Irfandi. See LICENSE for details.

0
likes
160
points
72
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter SDK for TestDeck. Captures HTTP, logs, navigation, and exceptions from debug builds.

Repository (GitHub)
View/report issues

Topics

#debugging #networking #logging #devtools

License

MIT (license)

Dependencies

flutter

More

Packages that depend on testdrive