Test Harness
A package to help with the creation of test harnesses to allow better readability and composability of tests
Uses Given, When, then, but unlike a lot of other test frameworks there is a single callback.
based on the ebay given_when_then, but exposes setup in creation of hte harness which allows mixin or inheritance to reuse test setup/teardown code.
Installation 💻
Add test_harness
to your pubspec.yaml
:
dev_dependencies:
widget_test_harness: ^0.7.1
Install it:
flutter packages get
Harness setup
Harnesses are setup by subclassing an appropriate harness class widgetTestHarness
and unitTestHarness
.
Below is a basic example that has the included NetworkImageMixin
which is used to mock the network image requests.
import 'package:widget_test_harness/widget_test_harness.dart';
final class ExampleWidgetTestHarness extends WidgetTestHarness
with NetworkImageMixin, CounterHarnessMixin {
ExampleWidgetTestHarness(super.tester);
@override
List<int> bytesForUrlRequest(Uri url) {
final file = File('test/test_resources/sunflower.jpg');
final bytes = file.readAsBytesSync();
return bytes;
}
}
The harness is passed into Given
, When
, Then
and extensions off of each can define methods.
extension MyGivenForExample on Given<ExampleWidgetTestHarness> {
Future<void> setupWidget() async {...}
}
extension MyWhenForExample on When<ExampleWidgetTestHarness> {
Future<void> userPerformsSomeAction() {}
}
Writing Mixins
Using mixins different features can be reused throughout an application's test code.
base mixin CounterHarnessMixin on FlutterTestHarness {
CounterModel counter = CounterModel();
@override
Widget setupWidgetTree(Widget child) {
return super.setupWidgetTree(Provider.value(value: counter, child: child));
}
}
extension CounterHarnessGiven on Given<CounterHarnessMixin> {
void countIs(int value) {}
}
extension CounterHarnessThen on Then<CounterHarnessMixin> {
void countEquals(int value) => expect(value,harness.counter.value);
}
Writing Tests
Writing a test invokes a function that will create the harness and setup state for that individual test. You should never have to use setup(), or teardown() while using a test harness.
final uiHarness = HarnessSetup.setupWidgetHarness(ExampleWidgetTestHarness.new);
void main() {
testWidgets('test Counter', uiHarness((given, when, then) async {
given.countIs(1);
await given.setupWidget();
await when.userPerformsSomeAction();
await then.findsWidgetText();
then.countEquals(2);
}));
}
-- see example_test.dart for additional example of usage