hegeltest_flutter 0.9.0 copy "hegeltest_flutter: ^0.9.0" to clipboard
hegeltest_flutter: ^0.9.0 copied to clipboard

Flutter integration for hegeltest — property-based testing powered by Hegel's native engine. Use with flutter_test instead of package:test.

example/main.dart

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

/// System under test (SUT) with internal business logic.
class Counter {
  int value = 0;
  void increment(int step) => value += step;
  void decrement(int step) => value -= step;
  void reset() => value = 0;
}

/// Model-based state machine that exercises [Counter] and asserts
/// its state against a simplified independent model.
class CounterMachine extends StateMachine {
  final counter = Counter();
  int model = 0;

  @override
  List<StateRule> get rules => [
    StateRule(
      'increment',
      execute: (tc) {
        final step = tc.draw(integers(min: 1, max: 10));
        counter.increment(step);
        model += step;
      },
    ),
    StateRule(
      'decrement',
      execute: (tc) {
        final step = tc.draw(integers(min: 1, max: 5));
        counter.decrement(step);
        model -= step;
      },
    ),
    StateRule(
      'reset',
      execute: (tc) {
        counter.reset();
        model = 0;
      },
    ),
  ];

  @override
  List<StateInvariant> get invariants => [
    StateInvariant(
      'counter value matches model',
      check: (tc) {
        expect(counter.value, equals(model));
      },
    ),
  ];
}

void main() {
  // 1. Unit property test with flutter_test and distribution statistics
  hegelFlutterTest('string reverse is involutory', (tc) {
    final s = tc.draw(text());
    tc.collect(
      s.isEmpty ? 'empty' : (s.length < 10 ? 'short' : 'long'),
      label: 'length',
    );
    expect(s.split('').reversed.join().split('').reversed.join(), equals(s));
  });

  // 2. Widget property testing: generate random text and verify rendering
  hegelFlutterWidgetTest('text renders correctly without throwing', (
    tc,
    tester,
  ) async {
    final label = tc.draw(text(minSize: 1, maxSize: 50));
    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(body: Center(child: Text(label))),
      ),
    );
    expect(find.text(label), findsOneWidget);
  });

  // 3. Widget property testing: padding configuration sweep with distribution tracking
  hegelFlutterWidgetTest('random padding does not overflow', (
    tc,
    tester,
  ) async {
    final left = tc.draw(integers(min: 0, max: 64)).toDouble();
    final top = tc.draw(integers(min: 0, max: 64)).toDouble();
    final right = tc.draw(integers(min: 0, max: 64)).toDouble();
    final bottom = tc.draw(integers(min: 0, max: 64)).toDouble();

    tc.collect(
      (left + right > 60 || top + bottom > 60)
          ? 'large padding'
          : 'compact padding',
      label: 'padding density',
    );

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Center(
            child: Padding(
              padding: EdgeInsets.fromLTRB(left, top, right, bottom),
              child: const SizedBox(width: 40, height: 40),
            ),
          ),
        ),
      ),
    );

    expect(find.byType(SizedBox), findsOneWidget);
  });

  // 4. Stateful model-based testing
  hegelFlutterStatefulTest('counter machine preserves model invariant', () {
    return CounterMachine();
  });

  // 5. Standalone property runner with statistics inspection
  test('standalone runner collects statistics programmatically', () async {
    final result = await runHegelFlutterTest((tc) {
      final n = tc.draw(integers(min: -20, max: 20));
      tc.collect(n < 0 ? 'negative' : (n == 0 ? 'zero' : 'positive'));
      expect(n + 0, equals(n));
    }, testCases: 50);

    expect(result.status, equals(RunStatus.passed));
    expect(result.statistics, isNotEmpty);
  });

  // 6. Accessibility / Semantics monkey fuzzing
  hegelFlutterMonkeyTest(
    'monkey fuzzer exercises counter UI without unhandled exceptions',
    createWidget: (tc) => const _CounterDemoApp(),
    steps: 15,
    testCases: 5,
    allowedActions: [SemanticsAction.tap, SemanticsAction.setText],
  );

  // 7. Screen size and layout invariant sweep
  hegelFlutterLayoutSweepTest(
    'responsive tag list never overflows across screen sizes and text scales',
    testCases: 5,
    sweepConfig: const LayoutSweepConfig(
      minWidth: 320,
      maxWidth: 1024,
      minHeight: 480,
      maxHeight: 1200,
      minTextScale: 0.8,
      maxTextScale: 2.0,
    ),
    builder: (tc, sample) {
      return Scaffold(
        appBar: AppBar(title: const Text('Tags')),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16),
          child: Wrap(
            spacing: 8,
            runSpacing: 8,
            children: List.generate(8, (i) => Chip(label: Text('Category $i'))),
          ),
        ),
      );
    },
  );
}

class _CounterDemoApp extends StatefulWidget {
  const _CounterDemoApp();

  @override
  State<_CounterDemoApp> createState() => _CounterDemoAppState();
}

class _CounterDemoAppState extends State<_CounterDemoApp> {
  int _count = 0;
  String _note = '';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Count: $_count')),
        body: Column(
          children: [
            ElevatedButton(
              onPressed: () => setState(() => _count++),
              child: const Text('Increment'),
            ),
            ElevatedButton(
              onPressed: () => setState(() => _count = 0),
              child: const Text('Reset'),
            ),
            TextField(onChanged: (v) => setState(() => _note = v)),
            Text('Note: $_note'),
          ],
        ),
      ),
    );
  }
}
0
likes
160
points
322
downloads

Documentation

API reference

Publisher

verified publisherletstesttools.dev

Weekly Downloads

Flutter integration for hegeltest — property-based testing powered by Hegel's native engine. Use with flutter_test instead of package:test.

Homepage
Repository (GitHub)
View/report issues
Contributing

Topics

#testing #property-based-testing #fuzzing #flutter

License

MIT (license)

Dependencies

flutter, flutter_test, hegeltest

More

Packages that depend on hegeltest_flutter