Now that we are done with unit tests let’s explore widget testing. The main goal of widget testing is to test the application’s UI and check if it’s getting rendered as intended. The main difference between a Widget Test and an Integration Test is that in Widget Test, you are testing the application’s UI, and in Integration Test you are testing the UI and the functionality of the application.
As I mentioned, Widget Tests run headlessly in the console, and Integration Tests run on the device. So Widget Tests are faster than Integration Tests.
Let us start with Widget Testing. We will be writing a Widget Test for the Login Screen.
Head over to the test folder and create a new file called login_widget_test.dart . You will be writing your widget test code inside this file.
We always start with the Main function. So let us write a main function.
void main() {
}
During Unit Tests, we called the test function to write the test. Similarly, in Widget Test, we will call a function named testWidgets. This function takes a string and a function as an argument. The string is the name of the test, and the function is the test function. To call this function, you need to import the flutter_test package.
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Login Widget Test', (WidgetTester tester) async {
});
}
WidgetTester is a class that provides a way to test widgets. You can use this class to find widgets in the widget tree, read and write the widget’s state, and verify that the widget has specific properties.
Let’s start writing our first widget test. When we begin the test, the first thing we should try is to expect a widget’s presence that is static and won’t change. Here we have a text widget that says Login Screen. Let us try to find this widget and check if it is present in the widget tree.
To find if a widget is rendered, we must first render the widget. It is done using the pumpWidget function. This function takes a widget as an argument and renders the widget.
So inside the testWidgets function, let’s pump the login screen.
testWidgets('Login Widget Test', (WidgetTester tester) async {
await tester.pumpWidget(LoginScreen());
expect(find.text('Login Screen'), findsOneWidget);
});
Like in unit tests, we have an expect function to check if the test is passing or failing. Similarly, in widget tests, we have an “expect” function to check if the widget is present in the widget tree. The “expect” function takes two arguments. The first argument is the widget, which you want to find, and the second is the matcher. The matcher is a function that checks if the widget is present in the widget tree.
Here we are finding the Widget by text. So we are using find.text function. This function takes a string as an argument and returns a widget. If the widget is present in the widget tree, it will return the widget; else, it will return null. And we are using findsOneWidget matcher, which checks if the widget is present in the widget tree. If the widget is present, it will pass the test; otherwise, it will fail.
Now let us run the test and see if it passes.
The test fails with errors No MediaQuery widget ancestor found and No Provider Scope Found So we need to add a MaterialApp and Provider Scope widget as a parent to the LoginScreen widget.
testWidgets('Login Widget Test', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(home: LoginScreen()));
expect(find.text('Login Screen'), findsOneWidget);
});
testWidgets('Login Widget Test', (WidgetTester tester) async {
await tester.pumpWidget(
ProviderScope(
child: MaterialApp(
home: LoginScreen(),
),
),
);
expect(find.text('Login Screen'), findsOneWidget);
});
Run the test and it should pass now.
Congratulations you have successfully written your first widget test. In the next episode, we will learn how to find widget and pump widget.