Testing topic

Flutter tests code

Right out of the box, Flutter offers the tools so you can test your app.
Automated testing can easily be performed on every aspect of your app.
Such tests fall into some particular categories:

  • A unit test tests a single function, method, or class.
  • A widget test (in other UI frameworks referred to as component test) tests a single widget.
  • An integration test tests a complete app or a large part of an app.
As always, the Flutter website has abundant documentation on the subject:
Contents
Assemble Size Integrate
Here, I'll introduce some of these tools and present how they're applied to this package. You'll get a real appreciation of the state_extended package if you review the testing it goes through before every release. All of what it can do is run in a series of tests to confirm their proper function. Review these tests, and you'll quickly learn what this package can do for you.

In the first screenshot below, the tests begin with the example app itself starting up. It renders its UI, and after it settles down, is ready to receive input. This is so to begin an integration test. The WidgetTester object, tester, allows the test environment to programmatically interact with the widgets being tested. tester.pumpWidget(app); actually calls the runApp() function to start up the example app.

The second screenshot continues down the widget_test.dart file highlighting those functions performing the integration and unit testing. Since in this example app, there is one and only one AppStateX object deemed the 'first' State object of the app (see AppStateX class), the function, tester.firstState, can reliably retrieve that instance to allow for more refined testing. For example, in the second screenshot below, attaining that State object allows access to its controller. As it happens, that controller has properties used to direct the testing.

widget_test.dart widget_test.dart

Assemble Your Test

As we progress, you can see further features available to you when testing. The reassembleApplication() function, for example, literally performs a hot reload (see first screenshot below). In this case, doing so allows some error handling to be tested when the app goes to 'Page 2.' In the second screenshot below, the Exception() function is explicitly called to invoke an error and test the error handling.

widget_test.dart my_app.dart

Size Your Test

Further along in the testing, there's a means to change the physical size of the text displayed when calling the testScalefactor() function highlighted in the first screenshot above. Specifically, you can change the scaling factor used when rendering text (see the second screenshot below). Do so at runtime, and the event handler, didChangeTextScaleFactor(), in the StateX object and its controllers will fire.

widget_test.dart test_event_handling.dart

In the first screenshot below, the testDidChangeMetrics() function actually changes the screen size of the device. The second screenshot displays how that is done in that very function. Doing so causes the didChangeMetrics() function of any State object and their controllers to fire. Granted, you may never ever need to consider such events... until one day you do.

widget_test.dart test_event_handling.dart

Integrate Your Test

Let's return back up the widget_test.dart file, and look inside the integrationTesting() function. An integration test (also called end-to-end testing or GUI testing) runs the full app. In the video below, we see the integration test putting the example app through its paces testing many aspects of the app in real time. The screenshot beside the video is the beginning of that function. There, you see the first activity is incrementing the count up to nine.

test_example_app.dart
widget_test.dart test_event_handling.dart

Again, I would suggest you examine the many test files that are downloaded with the state_extended package under the pub.dev folder and get a better idea how things work in this package and in Flutter.

Another advantage of factory constructors in your State object controllers, you simple instantiate a controller in your testing, and you have the direct means to perform unit or widget testing. A controller will have access to any number of State objects at some point in the testing.

widget_test.dart test_statex.dart

Classes

StateX<T extends StatefulWidget> Get started StateX class Using FutureBuilder Using InheritedWidget Error handling Testing Event handling
The extension of the State class.
StateXController Get started State Object Controller Testing Event handling
Your 'working' class most concerned with the app's functionality. Add it to a 'StateX' object to associate it with that State object.