hegeltest 0.5.0 copy "hegeltest: ^0.5.0" to clipboard
hegeltest: ^0.5.0 copied to clipboard

Property-based testing for Dart, powered by Hegel's native engine. Automatically finds edge cases by generating random inputs and shrinking failures to minimal counterexamples.

hegeltest — Property-based testing for Dart, powered by a native fuzzing engine. #

pub package CI license

What is property-based testing? #

Instead of writing individual test cases, you describe properties that should hold for all inputs. hegeltest generates random inputs, finds failures, and automatically shrinks them to the minimal counterexample. This allows you to find edge cases you might never have thought to write tests for.

Quick Start #

Add hegeltest to your pubspec.yaml under dev_dependencies:

dev_dependencies:
  hegeltest: ^0.5.0
  test: ^1.25.0

Then, write your property-based test:

import 'package:hegeltest/hegeltest.dart';
import 'package:test/test.dart';

void main() {
  hegelTest('reverse is involutory', (tc) {
    final xs = tc.draw(lists(integers()));
    expect(xs.reversed.toList().reversed.toList(), equals(xs));
  });
}

Available Generators #

Category Generators
Primitives integers(), doubles(), booleans(), bigIntegers()
Text text(), fromRegex(), emails(), urls(), domains(), uuids()
Collections lists(), sets(), maps()
Combinators oneOf(), nullable(), sampled(), frequency(), tuples2/3/4()
Temporal dates(), times(), dateTimes()
Network ipv4Addresses(), ipv6Addresses()
Bytes bytes()

Composing Generators #

You can build complex generators using combinators like map(), flatMap(), where(), and Generator.composite():

final evenIntegers = integers().where((i) => i.isEven);
final stringLengths = text().map((s) => s.length);
// Or build entirely new types
final userGen = Generator.composite<User>((tc) {
  final name = tc.draw(text(minSize: 1, maxSize: 50));
  final age = tc.draw(integers(min: 0, max: 150));
  return User(name: name, age: age);
});

Stateful Testing #

Test stateful systems by generating random sequences of operations and checking invariants after each step. Uses Swarm Testing to explore rule subsets and automatic shrinking to find minimal counterexamples.

class StackMachine extends StateMachine {
  final stack = <int>[];
  final model = <int>[];

  @override
  List<StateRule> get rules => [
    StateRule('push', execute: (tc) {
      final val = tc.draw(integers(min: -100, max: 100));
      stack.add(val);
      model.add(val);
    }),
    StateRule('pop',
      precondition: () => stack.isNotEmpty,
      execute: (tc) {
        expect(stack.removeLast(), equals(model.removeLast()));
      },
    ),
  ];

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

void main() {
  hegelStatefulTest('stack behaves like list', () => StackMachine());
}

Pools — tracking values across rules #

Use Pool<T> to share values between rules (like keys you've inserted into a database):

class KVStoreMachine extends StateMachine {
  final store = <String, int>{};
  late final Pool<String> keys;

  @override
  void setUp() { keys = createPool<String>(); }

  @override
  List<StateRule> get rules => [
    StateRule('put', execute: (tc) {
      final key = tc.draw(text(minSize: 1, maxSize: 5));
      final val = tc.draw(integers(min: 0, max: 999));
      store[key] = val;
      keys.add(key);                        // track the key
    }),
    StateRule('get',
      precondition: () => keys.isNotEmpty,
      execute: (tc) {
        final key = tc.draw(keys.reusable);  // draw without removing
        expect(store.containsKey(key), isTrue);
      },
    ),
    StateRule('delete',
      precondition: () => keys.isNotEmpty,
      execute: (tc) {
        final key = tc.draw(keys.consumed);  // draw and remove from pool
        store.remove(key);
      },
    ),
  ];
}

Configuration #

For reusable test configurations, you can use HegelConfig:

final thorough = HegelConfig(testCases: 100000);
hegelTest('check', (tc) { ... }, config: thorough);

Per-Iteration Isolation #

If your test mutates state, make sure to isolate iterations properly using setUpEach and tearDownEach instead of the standard package:test setup functions. package:test's setUp runs once per property, not per iteration.

hegelTest('stateful test', (tc) { ... },
  setUpEach: () => resetState(),
  tearDownEach: () => cleanupState(),
);

Reproducing Failures #

When a test fails, hegeltest provides a reproducible blob. You can use it to deterministically replay the exact failing scenario:

hegelTest('flaky test', (tc) { ... }, 
  reproduce: 'ABcdef123...', 
);

Flutter #

For Flutter apps, use hegeltest_flutter:

dev_dependencies:
  hegeltest_flutter: ^0.2.0
import 'package:hegeltest_flutter/hegeltest_flutter.dart';

void main() {
  hegelFlutterTest('addition is commutative', (tc) {
    final a = tc.draw(integers());
    final b = tc.draw(integers());
    expect(a + b, equals(b + a));
  });

  hegelFlutterStatefulTest('stack works', () => StackMachine());
}

Platform Support #

Platform Architecture Status
macOS Apple Silicon (arm64) ✅ Bundled
macOS Intel (x64) 🔜 Coming
Linux x64 ✅ Bundled
Linux arm64 ✅ Bundled
Windows x64 ✅ Bundled
Windows arm64 ✅ Bundled

All bundled binaries are verified via ABI version check at load time.

Set HEGEL_LIBHEGEL_PATH to use a custom-built binary on unsupported platforms.

Version Policy #

Branch Dart SDK Status
hegeltest ^0.5.0 >=3.10.0 Active — all new features
hegeltest ^0.4.0 >=3.4.0 Maintenance — security fixes only

CI/CD Notes #

hegeltest uses Dart's Build Hooks to register native binaries. The build hook runs automatically during dart test and flutter test — no extra CI configuration needed. No network access is required (binaries are bundled in the package).

License #

This package is licensed under the BSD-3-Clause license.

0
likes
0
points
531
downloads

Publisher

verified publisherletstesttools.dev

Weekly Downloads

Property-based testing for Dart, powered by Hegel's native engine. Automatically finds edge cases by generating random inputs and shrinking failures to minimal counterexamples.

Homepage
Repository (GitHub)
View/report issues

Topics

#testing #property-based-testing #fuzzing #test-generation

License

unknown (license)

Dependencies

code_assets, crypto, ffi, hooks, meta, test, test_api

More

Packages that depend on hegeltest