Quick Introduction to Tests in Flutter

Alperen Yalçn
6 min readJan 26, 2022

Hey, are you looking for how to write test in Flutter ? This is the right place. First we will start with test types and cover pros/cons over each other. At the end we will write test for each but before all of this why do we need tests ?

As the application grows you get more features, therefore you may want to make sure that all functions and ui components works perfectly and the best way to be sure is writing tests.

Environment Setup

In this article i will use flutter_test package because this package has extra features from the core test package. You need to add the above code to pubspec.yaml file and dont forget to get packages.

dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter

Folder Structure

According to the Flutter official documentation:

In general, test files should reside inside a test folder located at the root of your Flutter application or package. Test files should always end with _test.dart, this is the convention used by the test runner when searching for tests.

It means that your folder structure should look like to below and i will use this structure in this article.

my_app/
lib/
main.dart
test/
unit_test.dart
widget_test.dart
integration_test/
integration_test.dart

Test Types

There are 3.5 types tests exist in Flutter.

Unit Test

This is for testing functions,methods and classes independently. The goal is make sure that function is working under a variety of conditions.

Widget Test

The goal of widget tests is to verify that widget is receive/respond to user action and UI looks as expected. In this part we will use extra features comes with flutter_test package(eg. WidgetTester, Finder).

Integration Test

This is for testing complete or larger part of app. The goal is to verify that all the widgets and services working together as expected. Generally, an integration test runs on a real device or an OS emulator.

Golden Test

I wrote 3.5 in the headline because golden tests is basically a widget test. This test is takes a snapshot of a widget to be tested and compare with the older/newer version. I will not cover how to implement golden test in this article but you can find a documentation in here

The table below shows tests Pros/Cons over each other.

Photo : Official Flutter documentation

This was a brief summary about test types and why they are exist. Next step is implementing these tests in an app.

Implementing Unit Test

1- First create a unit what you want to test under the lib folder. “unit” is another name for a function, method, or class. For simplicity i choosed the below.

class PrintTest{ String test  = ‘Test’;
String test2 = ‘Test2’;
String printTest(){ return test;
}
String printTest2(){ return test;
}
}

2- Secondly you need to create a test file inside test folder. I choosed the file name unit_test.dart .

3- Then we need to create our main function because we will write our unit tests into this function. Test() and expect() are two functions used in unit tests. In this case, their usage is as follows.

import ‘package:app/printTest.dart’;import ‘package:flutter_test/flutter_test.dart’;void main(){ test(‘test variable should be printed’,(){   final PrintTest printTest = PrintTest();   expect(printTest.printTest(), ‘test’); });}

NOTE: You can run the following code inside the terminal from the root of the project to run the tests:

flutter test test/{file name}.dart

4- After running the test file you will see the green mark as expected.

Implementing Widget Test

1- First lets create a widget to test under lib folder. For the widget test i will use the code below.

class CustomWidget extends StatelessWidget {
const CustomWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(‘Test Widget’),
leading: IconButton(
icon: Icon(Icons.play_arrow),
onPressed: () {
print(‘Pressed Icon’);
},
),
),
body: Container(),
);
}
}

2- I assume that you created a widget or copied the above :) Next step is creating the test file under test folder. I will call it widget_test.dart .

3- We have some special functions and terms for widget tests.

testWidgets() =This function allows you to define a widget test and creates a WidgetTester to work with. You can think this function like the unit tests test() function but for the interacting with widgets.

WidgetTester Class = Class that programmatically interacts with widgets and the test environment.

pumpWidget() = This function is provided by WidgetTester class and used for building provided widget.

pump(Duration duration) = This function schedules a frame and triggers a rebuild of the widget

pumpAndSettle() = If you have animations in the screen pumpWidget wont help you about that so you need to use pumpAndSettle(). This function is repeatedly calls pump() function with the given duration until there are no longer any frames scheduled which means it will wait for your animations to finish.

Finder Class = This class searches widgets in the tree and returns nodes that match a particular pattern.

find constant = This is provided by flutter_test package and used for finding widget in a test environment. There are lot of methods for finding widgets you can check them from here.

find.text('{type the text you are looking for}’) = If you want to find a text widget in the test environment you can use this function.
find.byWidget(widget instance name) = This function finds a specific instance of a widget

Matcher constant = This constants verify a given value meets given matchers expectations. I have listed a few common matcher above for you to understand.

findsOneWidget : This matcher locates only one widget in the tree. findsNothing : Verifies that no widgets are found.

4- Last step is implenting widget test.

void main() {  testWidgets(‘CustomWidget is working expected’, (WidgetTester 
tester) async {
// Build our app and trigger a frame. await tester.pumpWidget(const MyApp());
// Verify that our appbar has ‘Test Widget’ text. expect(find.text(‘Test Widget’), findsOneWidget);
// Tap the icon await tester.tap(find.byIcon(Icons.play_arrow));
//trigger a frame. await tester.pump(); });}

5- And one more thing before finish the widget test. What about scrollable widgets or contents? In this example we will verify that a particular item exists in the list. For this we will use tester.scrollUntilVisible() method. The following code looks for a specific key in a scrollable list.

void main() {
testWidgets(‘Counter increments smoke test’, (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp(
items: List<String>.generate(10000, (i) => “Item $i”),
));
final listFinder = find.byType(Scrollable);
final itemFinder = find.byKey(const ValueKey(‘item_50_text’));
// Scroll until the item to be found appears.
await tester.scrollUntilVisible(
itemFinder,
500.0,
scrollable: listFinder,
);
// Verify that the item contains the correct text.
expect(itemFinder, findsOneWidget);
});
}

Implementing Integration Test

1- Firstly we need to create a folder under lib folder for keeping our integration test called integration_test.

2- We need an app to test and for this purpose i will use counter_app which comes default when you create a new Flutter peoject

counter_app

3- The test below is finds ‘0’ text , clicks the increment button and verify that text is increased to ‘1’.

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group(‘end-to-end test’, () {
testWidgets(‘tap on the floating action button, verify counter’,
(WidgetTester tester) async {
app.main();
await tester.pumpAndSettle();
// Verify the counter starts at 0.
expect(find.text(‘0’), findsOneWidget);
// Finds the floating action button to tap on.
final Finder fab = find.byTooltip(‘Increment’);
// Emulate a tap on the floating action button.
await tester.tap(fab);
// Trigger a frame.
await tester.pumpAndSettle();
// Verify the counter increments by 1.
expect(find.text(‘1’), findsOneWidget);
});
});
}

We covered three types of tests in this article and i hope it was helpful. See you in the next article 👊.

--

--