Running Flutter Tests: A Step-by-Step Guide for White Box Test Automation

Pradap Pandiyan
4 min readFeb 6, 2024

--

Flutter provides a powerful testing framework to validate the functionality and user interactions within your applications. In this article, I’ll guide you through the process of running Flutter tests using a sample test suite.

Prerequisites

Before getting started, make sure you have the following installed:

  • Flutter SDK
  • Dart SDK

Ensure that your Flutter project is set up correctly and has the necessary dependencies.

Application code

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Random Things App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: RandomThingsPage(),
);
}
}

class RandomThingsPage extends StatefulWidget {
@override
_RandomThingsPageState createState() => _RandomThingsPageState();
}

class _RandomThingsPageState extends State<RandomThingsPage> {
final Random _random = Random();
List<String> months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];

List<String> countries = [
'USA',
'Canada',
'India',
'Brazil',
'Australia',
'France',
'Japan',
'Germany',
'South Africa',
'Mexico',
];

String randomMonth = '';
String randomCountry = '';
String randomFancyNumber = '';
String randomFullName = '';

void generateRandomMonth() {
final int randomIndex = _random.nextInt(months.length);
setState(() {
randomMonth = months[randomIndex];
});
}

void generateRandomCountry() {
final int randomIndex = _random.nextInt(countries.length);
setState(() {
randomCountry = countries[randomIndex];
});
}

void generateRandomFancyNumber() {
setState(() {
randomFancyNumber = _generateRandomFancyNumber();
});
}

String _generateRandomFancyNumber() {
return (_random.nextInt(90000) + 10000).toString(); // Generates a random 5-digit number
}

void generateRandomFullName() {
setState(() {
randomFullName = _generateRandomFullName();
});
}

String _generateRandomFullName() {
final List<String> firstNames = ['John', 'Alice', 'Bob', 'Emma', 'David'];
final List<String> lastNames = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown'];

final String randomFirstName = firstNames[_random.nextInt(firstNames.length)];
final String randomLastName = lastNames[_random.nextInt(lastNames.length)];

return '$randomFirstName $randomLastName';
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Random Things'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Random Month:',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Text(
randomMonth,
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
SizedBox(height: 40),
Text(
'Random Country:',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Text(
randomCountry,
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
SizedBox(height: 40),
Text(
'Random Fancy Number:',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Text(
randomFancyNumber,
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
SizedBox(height: 40),
Text(
'Random Full Name:',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Text(
randomFullName,
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
],
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: generateRandomMonth,
tooltip: 'Generate Random Month',
child: Icon(Icons.calendar_today),
),
SizedBox(height: 16),
FloatingActionButton(
onPressed: generateRandomCountry,
tooltip: 'Generate Random Country',
child: Icon(Icons.public),
),
SizedBox(height: 16),
FloatingActionButton(
onPressed: generateRandomFancyNumber,
tooltip: 'Generate Random Fancy Number',
child: Icon(Icons.confirmation_number),
),
SizedBox(height: 16),
FloatingActionButton(
onPressed: generateRandomFullName,
tooltip: 'Generate Random Full Name',
child: Icon(Icons.person),
),
],
),
);
}
}

The application looks like below. The application has multiple buttons which have different actions when the button is pressed.

Writing Tests

For this guide, we’ll use a simple Flutter project with a sample test suite. The test suite includes tests for a basic counter increment and additional tests to validate calendar, animation, and person-related functionality. Below is the sample test code:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:fluttertest/main.dart';

void main() {
testWidgets('Generate Random Month Test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());


var calendarTodayIcon = find.byIcon(Icons.calendar_today);
expect(calendarTodayIcon, findsOneWidget);

await tester.tap(find.byIcon(Icons.calendar_today));
await tester.pump();
expect(find.text("Random Month:"), findsOneWidget);


});

testWidgets('Generate Random Country Test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());

expect(find.text('Random Country:'), findsOneWidget);

var publicIcon = find.byIcon(Icons.public);
expect(publicIcon, findsOneWidget);
await tester.tap(find.byIcon(Icons.public));
await tester.pump();

expect(find.textContaining('Random Country:'), findsOneWidget);

});

testWidgets('Generate Random Fancy Number Test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());

expect(find.text('Random Fancy Number:'), findsOneWidget);
var confirmationNumberIcon = find.byIcon(Icons.confirmation_number);
expect(confirmationNumberIcon, findsOneWidget);
await tester.tap(find.byIcon(Icons.confirmation_number));
await tester.pump();

expect(find.textContaining('Random Fancy Number:'), findsOneWidget);
});

testWidgets('Generate Random Full Name Test', (WidgetTester tester) async {
await tester.pumpWidget(MyApp());

expect(find.text('Random Full Name:'), findsOneWidget);
var personIcon = find.byIcon(Icons.person);
expect(personIcon, findsOneWidget);
await tester.tap(find.byIcon(Icons.person));
await tester.pump();

expect(find.textContaining('Random Full Name:'), findsOneWidget);
});
}

Running Tests

Now, let’s run the tests using the following steps:

  1. Open a terminal in the root directory of your Flutter project.
  2. Execute the following command to run all tests:
flutter test

3. This command will execute all test files in the test directory.

4. Observe the output in the terminal. If all tests pass, you should see a success message.

Interpreting Test Results

As the tests run, you’ll see output in the terminal indicating whether each test has passed or failed. A successful test run will display a message similar to:

All tests passed!

In case of failures, the terminal output will provide details on which tests failed and why. Review any error messages or assertions to identify and fix the issues.

Commands to run the test on multiple platforms

We can run the test on multiple platforms based on the code compilation done on the platform.

To see the connected

flutter devices

To run the app on the device

flutter run -d "device name or id"

To run the test on the device

flutter test -d "device name or id"

Conclusion

The flutter test is a great framework to run a lightweight test automation on the flutter apps and it has great support on all the supported platforms. However in reality, if you're looking for a framework to use on a heavy application it's not a great tool to go to. For devs, this might be a great way to write tests on the test automation.

That’s a wrap, this could help you guys build the first flutter tests.

I have created a project on GitLab and added the code here.

Feel free to hit clap if you like the content. Happy Automation Testing :) Cheers. 👏

--

--

Pradap Pandiyan

I’m a passionate QA Engineer. I’m a motovlogger, content creator, off-roader and freelancer. Buy me a coffee here https://www.buymeacoffee.com/pradappandiyan