easy_test_variants 0.0.1 copy "easy_test_variants: ^0.0.1" to clipboard
easy_test_variants: ^0.0.1 copied to clipboard

Predefined device & platform variants to eliminate testing boilerplate. Build your own custom TestVariants and combine them all into a powerful matrix via MatrixVariant.

Star on GitHub

Easy Test Variants 🚀 #

A flexible, fluent, and zero-boilerplate matrix testing engine for Flutter widgets. This package allows you to scale visual and behavioral validation across multiple dimensions (devices, platforms, and custom business workflows) simultaneously using a single test block.


💡 Why Easy Test Variants? #

When writing comprehensive responsive or multi-platform widget tests in Flutter, developers often fall into two traps:

  1. The Nesting Hell: Writing massive, nested for loops inside a single test to cycle through screen sizes and user roles.
  2. Code Duplication: Copy-pasting the exact same test file 10 times just to change the simulated target device or scenario.

easy_test_variants solves this by introducing a clean, composable testing matrix. By wrapping your permutations inside native TestVariant abstractions, the framework calculates the Cartesian Product under the hood, managing the setUp and tearDown lifecycles of all variants automatically.

Key Benefits & Advantages #

  • 📉 Eliminate Testing Boilerplate: Write the UI interactions and assertion rules exactly once. Let the engine multiply the execution seamlessly.
  • 📱 Predefined Presets: Out-of-the-box configurations for modern smartdevices (Smartphones, Tablets, Desktops).
  • 💻 Platform Swapping: Effortlessly override native OS behaviors (Android, iOS, macOS, Windows, Linux) mid-test runner.
  • 🧩 100% Extensible: Seamlessly plugs into your own customized testing schemas (e.g., Feature Flags, AB testing branches, User authentication roles).

🛠️ Provided Variants #

The package exposes strongly-typed variations built on top of the native Flutter testing harness:

1. TestDeviceVariant #

Automates responsive rendering testing by overriding physical dimensions and device pixel ratios in the setUp pipeline.
Use all availables devices

  • TestDeviceVariant({required String description}) Use specify device type
  • TestDeviceVariant.mobile({required String description})
  • TestDeviceVariant.tablets({required String description})
  • TestDeviceVariant.desktop({required String description}) Custom devices
  • TestDeviceVariant({required String description, DeviceConfigVariant values})
final myDevices = TestDevicecVariant(description: 'teste', values {DeviceConfigVariant(platform: Platform.android, info: 'Android Gslaxy s24', size: Size(360.0, 420.0))})

final allFevices = TesteDeviceVariant(description: 'teste');
final mobileDevices = TesteDeviceVariant.mobile(description: 'teste');

2. TestPlatformVariant #

Handles operating system abstraction layers by dynamically toggling debugDefaultTargetPlatformOverride.

  • TestPlatformVariant.all({required String description})
  • TestPlatformVariant.mobile({required String description})
  • TestPlatformVariant.desktop({required String description})

📦 Practical Implementation Guide #

Below is a complete, realistic scenario demonstrating how to use isolated variants and how to merge them into a multi-dimensional permutation engine using MatrixVariant.

Step 1: Define Your Business Scenarios (Enhanced Enum) #

Use an enhanced enum to encapsulate different business rules for your layouts.

enum ProfileScenario {
  admin(
    name: 'Administrator View',
    showDeleteButton: true,
    canEditBio: true,
  ),
  premium(
    name: 'Premium Member View',
    showDeleteButton: false,
    canEditBio: true,
  ),
  guest(
    name: 'Guest Visitor View',
    showDeleteButton: false,
    canEditBio: false,
  );

  final String name;
  final bool showDeleteButton;
  final bool canEditBio;

  const ProfileScenario({
    required this.name,
    required this.showDeleteButton,
    required this.canEditBio,
  });
}

Step 2: Write Your Unified Test Matrix #

Place this code inside your test/ directory. This single setup registers isolated validation blocks and a combined execution grid.

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

void main() {
  // --- Initialize Isolated Variants ---
  final allDevicesVariant = TestDeviceVariant(description: 'All Devices Isolation');
  final allPlatformsVariant = TestPlatformVariant.all(description: 'All Platforms Isolation');
  
  // Wrap your custom business model inside TendaScenarioVariant
  final scenarioVariant = TendaScenarioVariant<ProfileScenario>({
    const TestScenario(description: 'Scenario: Admin', variant: ProfileScenario.admin),
    const TestScenario(description: 'Scenario: Premium', variant: ProfileScenario.premium),
    const TestScenario(description: 'Scenario: Guest', variant: ProfileScenario.guest),
  });

  // ===========================================================================
  // TEST 1: ISOLATED DEVICE TESTING (Runs against all pre-configured devices)
  // ===========================================================================
  testWidgets(
    'Should render properly on ALL simulated devices independently',
    variant: allDevicesVariant,
    (WidgetTester tester) async {
      final currentDevice = allDevicesVariant.current;
      
      await tester.pumpWidget(UserProfileScreen(scenario: ProfileScenario.premium));
      await tester.pumpAndSettle();

      expect(find.byType(UserProfileScreen), findsOneWidget);
      print('-> Device Isolation OK: [\${currentDevice.info}]');
    },
  );

  // ===========================================================================
  // TEST 2: ISOLATED PLATFORM TESTING (Toggles Android/iOS/Desktop behaviors)
  // ===========================================================================
  testWidgets(
    'Should apply correct system styling constraints across ALL operating systems',
    variant: allPlatformsVariant,
    (WidgetTester tester) async {
      final currentPlatform = allPlatformsVariant.current;

      await tester.pumpWidget(UserProfileScreen(scenario: ProfileScenario.admin));
      await tester.pumpAndSettle();

      expect(debugDefaultTargetPlatformOverride, equals(currentPlatform));
      print('-> Platform Isolation OK: [\${currentPlatform.name.toUpperCase()}]');
    },
  );

  // ===========================================================================
  // TEST 3: MATRIX PERMUTATION (Combines Devices X Business Scenarios)
  // ===========================================================================
  
  // Combine multiple independent TestVariants into a powerful Cartesian grid
  final matrixCombiner = MatrixVariant({allDevicesVariant, scenarioVariant});

  testWidgets(
    'MATRIX: Multiplies all devices against all profile scenarios simultaneously',
    variant: matrixCombiner,
    (WidgetTester tester) async {
      // Safely extract type-safe active slices using variant instance lookups
      final deviceConfig = matrixCombiner.get(allDevicesVariant);
      final scenarioConfig = matrixCombiner.get(scenarioVariant);
      final scenario = scenarioConfig.variant;

      // 1. Build & render your UI component
      await tester.pumpWidget(UserProfileScreen(scenario: scenario));
      await tester.pumpAndSettle();

      // 2. Assert multi-dimensional rules (Checks Layout responsiveness + Data privileges)
      expect(find.text(scenario.name), findsOneWidget);

      final deleteButton = find.widgetWithText(ElevatedButton, 'Delete Account');
      if (scenario.showDeleteButton) {
        expect(deleteButton, findsOneWidget);
      } else {
        expect(deleteButton, findsNothing);
      }

      print('-> Matrix Step Success: [\({deviceConfig.info}] x [\){scenario.name}]');
    },
  );
}

🏃‍♂️ Running Your Matrix Tests #

To execute the test matrix pipeline and inspect outputs, open your terminal inside the root directory and run:

flutter test test/profile_matrix_test.dart

To output detailed, step-by-step console logs explaining exactly which device coupled with which business state is currently evaluating, attach the --verbose flag:

flutter test test/profile_matrix_test.dart --verbose

You can see a complete example in /example folder, clone the projet and just run tests.

📄 License #

This project is licensed under the MIT License - see the LICENSE file for details.

0
likes
150
points
114
downloads

Documentation

API reference

Publisher

verified publisherdeebx.tech

Weekly Downloads

Predefined device & platform variants to eliminate testing boilerplate. Build your own custom TestVariants and combine them all into a powerful matrix via MatrixVariant.

License

MIT (license)

Dependencies

flutter, flutter_test

More

Packages that depend on easy_test_variants