Flutter

flutter pub add dev:tracera_flutter

Requires Dart ≥ 3.8 and Flutter ≥ 3.24 (see Autotest adapters). tracera_flutter on pub.dev.

Environment variables and run mode: Autotest adapters.

Call installTracera() once at the top of the main function, or in flutter_test_config.dart. Keep the stock flutter_test and integration_test imports; add only installTracera, the screenshot helpers, and the tracera calls:

import 'package:flutter_test/flutter_test.dart';
import 'package:tracera/tracera.dart' as tracera;
import 'package:tracera_flutter/tracera_flutter.dart';

void main() {
  installTracera();

  testWidgets('user can sign in', (tester) async {
    await tracera.step('pump login', () async {
      await tester.pumpWidget(/* ... */);
    });
  }, tags: ['tracera-id-42']);
}

Bind testCaseId and autotestName

Add the tag tracera-id-‹id› to a testWidgets, test, or group. Add tracera-name-‹name› to set autotestName. A name tag cannot contain spaces; to use spaces, bind inside the test with tracera.testCase. If the name tag is omitted, autotestName takes the value of the Flutter test name.

testWidgets('user can sign in', (tester) async {
  // ...
}, tags: ['tracera-id-42', 'tracera-name-e2e_sign_in']);

testWidgets('user can sign out', (tester) async {
  tracera.testCase(43, 'e2e/sign out');
});

To silence warnings about undefined tags, list the Tracera tags under tags: in dart_test.yaml.

Skip

Call markTestSkipped('reason') inside the test. The result is reported as Skipped, and the reason is added to the result as comment.

testWidgets('checkout', (tester) async {
  markTestSkipped('needs a seeded account');
}, tags: ['tracera-id-42']);

The skip: argument on testWidgets or group is not reported.

Steps

Use tracera.step('…', () { … }). A setUp callback maps to Setup, the test body to Test, and a tearDown callback to Teardown. Steps inside setUpAll / tearDownAll are not reported.

setUp(() {
  tracera.step('open shop', () {});
});

testWidgets('checkout', (tester) async {
  tracera.testCase(10);

  await tracera.step('add item', () async {
    await tester.pumpWidget(/* ... */);
    tracera.step('nested leaf', () {});
  });
});

tearDown(() {
  tracera.step('close shop', () {});
});

Comments, errors, and attachments

Limits and allowed MIME types: Autotest adapters.

tracera.comment, tracera.error, and attachments are added to the open step, or to the result when no step is open. tracera.attachmentFile takes a file path; tracera.attachmentBytes takes a name and bytes, with an optional mimeType. Attachments upload when the result is reported.

tracera.comment('result-level note');
tracera.error('result-level error');
tracera.attachmentFile('test/fixtures/screenshot.png');
tracera.step('open login', () {
  tracera.comment('step note');
  tracera.attachmentBytes(
    'body.json',
    utf8.encode('{"ok":true}'),
    mimeType: 'application/json',
  );
});

Screenshots

Screenshots are PNG attachments from a capture or from bytes you pass.

  • attachScreenshot(tester) captures the first RepaintBoundary in a widget test.
  • attachScreenshotBytes(bytes) attaches PNG bytes you already have.
  • attachIntegrationScreenshot(name: 'checkout') takes a device screenshot in integration_test.
testWidgets('checkout', (tester) async {
  await tester.pumpWidget(const RepaintBoundary(child: CheckoutPage()));
  await attachScreenshot(tester, fileName: 'checkout.png');
});

Parameterized

Create one testWidgets in a loop for each row. If the name is omitted, autotestName takes the value of the test name, so give each row a distinct title. To set a name per row, pass it to tracera.testCase:

for (final login in ['alice', 'bob']) {
  testWidgets('sign in as $login', (tester) async {
    tracera.testCase(7, 'login as $login');
  });
}

When a test is retried, only the final attempt is reported. The result Env tab then includes FLUTTER_RETRY (see Autotest adapters).