Testing in Flutter

Sep 19 2023 · Dart 2.19.3, Flutter 3.7.6, Android Studio 2021.3.1, Visual Studio Code 1.7.4

Part 3: Write Widget Tests

10. Find & Pump Widget

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 09. Write Login Widget Test Next episode: 11. Test Different Login Scenarios

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 10. Find & Pump Widget

Now that we know how to test a text widget. Let’s find other ways to find a widget in the Widget tree.

There are many ways to find a widget in the widget tree. The most common way is to find a widget by its type. For example, if you want to find a widget of type Text, you can use find.byType function. This function takes a type 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.

testWidgets('Login Widget Test', (WidgetTester tester) async {
  await tester.pumpWidget(MaterialApp(home: LoginScreen()));
  expect(find.byType(Text), findsOneWidget);
});

The problem with this approach is that if you have multiple widgets of the same type in the widget tree, this function will return the first widget it finds. So if you want to find a specific widget, you can use findsNWidgets matcher. This function takes a type and an integer as an argument. The integer is the number of widgets you want to find. If the number of widgets found is equal to the integer, it will pass the test else, it will fail the test.

testWidgets('Login Widget Test', (WidgetTester tester) async {
  await tester.pumpWidget(MaterialApp(home: LoginScreen()));
  expect(find.byType(Text), findsNWidgets(4));
});

Another way to find a widget is by using find.byKey function. This function takes a key 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 else it will fail the test.

testWidgets('Login Widget Test', (WidgetTester tester) async {
  await tester.pumpWidget(MaterialApp(home: LoginScreen()));
  expect(find.byKey(ValueKey('loginScreenTextKey')), findsOneWidget);
});

I personally prefer using find.byKey function because it is more reliable and easy to find a widget by its key.

If you head to key_contants.dart file, you will find that we have created a key for each widget. So that we can find the widget by its key.

const loginScreenTextKey = ValueKey('loginScreenTextKey');
const emailTextFormKey = ValueKey('emailTextFormKey');
const passwordTextFormKey = ValueKey('passwordTextFormKey');
const loginButtonKey = ValueKey('loginButtonKey');
const loginCircularProgressKey = ValueKey('loginCircularProgressKey');
const loginButtonTextKey = ValueKey('loginButtonTextKey');
const quotesCircularProgressKey = ValueKey('quotesCircularProgressKey');

const kEmailErrorText = 'Please enter a valid email';
const kPasswordErrorText = 'Password must be at least 6 characters';

Also, I have already passed the key values to the widgets on the login screen. So that we can find the widget by its key. Head to login_screen.dart file, and you will find that we have passed the key values to the widgets.

  Padding(
    padding: const EdgeInsets.all(10.0),
    child: Text(
      'Login Screen',
      key: loginScreenTextKey,
      style: TextStyle(color: Colors.black, fontSize: 20),
      ),
    ),

Now that we know how to find a widget in the widget tree. Let’s find out how to pump a widget. Putting it simply, pumping a widget means building a widget. When you call pumpWidget function, it builds the widget and returns a Future.

pumpAndSettle function is used to pump a widget and wait for all animations to finish. This function takes a widget tester and a duration as an argument. The duration is the time to wait for the animations to complete.

Let’s check if all the widgets present in the login screen are rendered properly and write a test to check that. I will be using find.byKey function to find the widgets.


testWidgets('Login Widget Test', (WidgetTester tester) async {
  await tester.pumpWidget(MaterialApp(home: LoginScreen()));
  final loginText = find.byKey(loginScreenTextKey);
  expect(loginText, findsOneWidget);
});

Run this test to check if our widget is rendered correctly and also to test if find.byKey function works properly. And the test passes.

Okay, Here is a Cool Widget test challenge for you. I want you to write a test to check if the emailTextField, passwordTextField and login button are correctly rendered. Pause the video and try to write the test. I will be waiting for you here.

I hope you were able to write the test. If not, please rewind the video and see how we check the Login screen widget presence.

Let me show you how to write the test to check if the emailTextField, passwordTextField and login button are appropriately rendered.

testWidgets('Login Widget Test', (WidgetTester tester) async {
  await tester.pumpWidget(MaterialApp(home: LoginScreen()));
  final loginText = find.byKey(loginScreenTextKey);
  final emailTextField = find.byKey(emailTextFormKey);
  final passwordTextField = find.byKey(passwordTextFormKey);
  final loginButton = find.byKey(loginButtonKey);

  expect(loginText, findsOneWidget);
  expect(emailTextField, findsOneWidget);
  expect(passwordTextField, findsOneWidget);
  expect(loginButton, findsOneWidget);

});

Run the test, and this test should also pass. If it fails, please check the key values in the login screen and key_constants.dart file.

The initials widgets present is just one of the scenarios of the Widget test. There are many scenarios that we need to test. In the next episode, we will learn how to test the other scenarios.