flutter-testing-apps

Comprehensive testing framework for Flutter apps across unit, widget, and integration test layers. Covers three test categories: unit tests for isolated logic, widget tests for UI components, and integration tests for end-to-end flows on real devices or emulators Provides architectural testing patterns for ViewModels, Repositories, Services, and Views, with emphasis on Fake implementations over mocks for cleaner test design Includes plugin testing guidelines combining Dart tests with native platform tests (JUnit, XCTest, GoogleTest, Espresso, XCUITest) to validate method channel communication Offers platform-specific workflows for running integration tests on mobile, web, Linux, and Firebase Test Lab with conditional execution logic

INSTALLATION
npx skills add https://github.com/flutter/skills --skill flutter-testing-apps
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$2a

Widget Tests

Use widget tests (component tests) to ensure a single widget's UI looks and interacts as expected.

  • Provide the appropriate widget lifecycle context using WidgetTester.
  • Use Finder classes to locate widgets and Matcher constants to verify their existence and state.
  • Test views and UI interactions without spinning up the full application.

Integration Tests

Use integration tests (end-to-end or GUI testing) to validate how individual pieces of an app work together and to capture performance metrics on real devices.

  • Add the integration_test package as a dependency.
  • Run on physical devices, OS emulators, or Firebase Test Lab.
  • Prioritize integration tests for routing, dependency injection, and critical user flows.

Architectural Testing Guidelines

Design your application for observability and testability. Ensure all components can be tested both in isolation and together.

  • ViewModels: Write unit tests for every ViewModel class. Test the UI logic without relying on Flutter libraries or testing frameworks.
  • Repositories & Services: Write unit tests for every service and repository. Mock the underlying data sources (e.g., HTTP clients, local databases).
  • Views: Write widget tests for all views. Pass faked or mocked ViewModels and Repositories into the widget tree to isolate the UI.
  • Fakes over Mocks: Prefer creating Fake implementations of your repositories (e.g., FakeUserRepository) over using mocking libraries when testing ViewModels and Views to ensure well-defined inputs and outputs.

Plugin Testing Guidelines

When testing plugins, combine Dart tests with native platform tests to ensure full coverage across the method channel.

  • Dart Tests: Use Dart unit and widget tests for the Dart-facing API. Mock the platform channel to validate Dart logic.
  • Native Unit Tests: Implement native unit tests for isolated platform logic.
  • Android: Configure JUnit tests in android/src/test/.
  • iOS/macOS: Configure XCTest tests in example/ios/RunnerTests/ and example/macos/RunnerTests/.
  • Linux/Windows: Configure GoogleTest tests in linux/test/ and windows/test/.
  • Native UI Tests: Use Espresso (Android) or XCUITest (iOS) if the plugin requires native UI interactions.
  • Integration Tests: Write at least one integration test for each platform channel call to verify Dart-to-Native communication.
  • End-to-End Fallback: If integration tests cannot cover a flow (e.g., mocking device state), synthesize calls to the method channel entry point using native unit tests, and test the Dart public API using Dart unit tests.

Workflows

Workflow: Implementing a Component Test Suite

Copy and track this checklist when implementing tests for a new architectural feature.

  • Task Progress
  • Create Fake implementations for any new Repositories or Services.
  • Write Unit Tests for the Repository (mocking the API/Database).
  • Write Unit Tests for the ViewModel (injecting the Fake Repositories).
  • Write Widget Tests for the View (injecting the ViewModel and Fake Repositories).
  • Write an Integration Test for the critical path involving this feature.
  • Run validator -> review coverage -> fix missing edge cases.

Workflow: Running Integration Tests

Follow conditional logic based on the target platform when executing integration tests.

  • If testing on Mobile (Local):
  • Connect the Android/iOS device or emulator.
  • Run: flutter test integration_test/app_test.dart
  • If testing on Web:
  • Install and launch ChromeDriver: chromedriver --port=4444
  • Run: flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart -d chrome
  • If testing on Linux (CI System):
  • Invoke an X server using xvfb-run to provide a display environment.
  • Run: xvfb-run flutter test integration_test/app_test.dart -d linux
  • If testing via Firebase Test Lab:
  • Build the Android test APKs: flutter build apk --debug and ./gradlew app:assembleAndroidTest
  • Upload the App APK and Test APK to the Firebase Console.

Examples

Example: ViewModel Unit Test

Demonstrates testing a ViewModel using a Fake Repository.

import 'package:flutter_test/flutter_test.dart';

void main() {

  group('HomeViewModel tests', () {

    test('Load bookings successfully', () {

      // Inject fake dependencies

      final viewModel = HomeViewModel(

        bookingRepository: FakeBookingRepository()..createBooking(kBooking),

        userRepository: FakeUserRepository(),

      );

      // Verify state

      expect(viewModel.bookings.isNotEmpty, true);

    });

  });

}

Example: View Widget Test

Demonstrates testing a View by pumping a localized widget tree with fake dependencies.

import 'package:flutter/material.dart';

import 'package:flutter_test/flutter_test.dart';

void main() {

  group('HomeScreen tests', () {

    late HomeViewModel viewModel;

    late FakeBookingRepository bookingRepository;

    setUp(() {

      bookingRepository = FakeBookingRepository()..createBooking(kBooking);

      viewModel = HomeViewModel(

        bookingRepository: bookingRepository,

        userRepository: FakeUserRepository(),

      );

    });

    testWidgets('renders bookings list', (WidgetTester tester) async {

      await tester.pumpWidget(

        MaterialApp(

          home: HomeScreen(viewModel: viewModel),

        ),

      );

      // Verify UI state

      expect(find.byType(ListView), findsOneWidget);

      expect(find.text('Booking 1'), findsOneWidget);

    });

  });

}

Example: Integration Test

Demonstrates a full end-to-end test using the integration_test package.

import 'package:flutter/material.dart';

import 'package:flutter_test/flutter_test.dart';

import 'package:integration_test/integration_test.dart';

import 'package:my_app/main.dart';

void main() {

  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('end-to-end test', () {

    testWidgets('tap on the floating action button, verify counter', (tester) async {

      // Load app widget

      await tester.pumpWidget(const MyApp());

      // Verify initial state

      expect(find.text('0'), findsOneWidget);

      // Find and tap the button

      final fab = find.byKey(const ValueKey('increment'));

      await tester.tap(fab);

      // Trigger a frame to allow animations/state to settle

      await tester.pumpAndSettle();

      // Verify updated state

      expect(find.text('1'), findsOneWidget);

    });

  });

}
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card