Leonardo Rosa
Posted on March 27, 2023
A good programmer writes tests to find errors and maintain the code. Tests are part of a programmer guy daily, but many programmers ignore an important kind of test, the user interface test. Can you think how hard to ensure the widget's appearance or don’t introduce a bug for a project with thousands of widgets? That’s much hard or maybe impossible to maintain this without tests. However, The Flutter Golden Test provides an easy way to help us ensure that widgets have the correct appearance.
In this article, you'll learn about improving your user interface testing experience with the Alchemist tool and any concepts of the Golden Test.
The maintainable code is a testable code. - Unknown
What’s a Golden Test?
Remembering a little of any concepts of unit tests, the Golden Test provides a way to test the appearance of one single widget using a master image called Golden File which is considered the correct rendering of a widget.
Setting up the Alchemist package
The tool configuration is pretty simple and easy. Let’s start installing the Alchemist package into the project with the command below:
flutter pub add alchemist --dev
Create a file to prepare some configurations before a test is executed called flutter_test_config.dart
in the test/
directory after installing the Alchemist tool successfully. In this file, we’ll prepare some configurations like render widget shadows and allow the display of raw text rather than obscure them.
import 'dart:async';
import 'package:alchemist/alchemist.dart';
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
return prepareGoldenTests(testMain);
}
void prepareGoldenTests(FutureOr<void> Function() testMain) {
return AlchemistConfig.runWithConfig(
config: const AlchemistConfig(
platformGoldensConfig: PlatformGoldensConfig(
renderShadows: true,
obscureText: false,
),
),
run: testMain,
);
}
Writing a Golden Test
Let’s write one widget to test before we start to write the Golden Test. We created a widget for this section displaying an NBA game schedule.
import 'package:flutter/material.dart';
class GameItem extends StatelessWidget {
const GameItem({super.key});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 20,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Boston Celtics',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w400,
),
),
SizedBox(height: 15),
Text(
'Chicago Bulls',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w400,
),
),
],
),
),
const Expanded(
child: Center(
child: Text(
'08:00 PM',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
),
],
),
);
}
}
Create a testGoldens test
With a widget to test the appearance, becomes easy to write a test. Use the goldenTest()
function from the alchemist
package to define one test, this function allows you to define a widget to test the appearance and the file name to generate the Golden File.
goldenTest(
'displayed the basketball game',
fileName: 'baskteball_game_widget',
constraints: const BoxConstraints(
maxWidth: 300,
),
builder: () => const GameItem(),
);
Generating the Golden File
It's time to generate the Golden File after writing the test using the goldenTest()
function. You can execute the command below to generate the Golden File.
flutter test --update-goldens
You may notice that the test
directory has been updated with a new directory called goldens
containing the Golden Files generated by the Golden Test, for example:
test/
goldens/
ci/
- baskteball_game_widget.png
macos/
- baskteball_game_widget.png
The golden tests generate the macos/
subdirectory because while I'm writing this article I'm using a MacOS operation system. Whether you are using Linux or Windows your golden tests will generate the subdirectory dealing with your operating system with subtle differences between the platforms.
Golden Test in continuous integration workflow
You may notice that the goldens/
directory also has the ci/
subdirectory. The ci/
subdirectory is generated to deal with the subtle differences in rendering between MacOS, Linux, and Windows platforms.
Enabling the continuous integration using —dart-define
To enable continuous integration environment is necessary to disable the tests locally. We can use the IS_CONTINUOUS_INTEGRATION
environment declaration to identify when the tests are running on the continuous integration environment and obtain this value using the bool.fromEnvironment
.
Go back to the flutter_test_config.dart
in the test/
directory and update the prepareGoldenTests
to obtain the IS_CONTINUOUS_INTEGRATION
declaration and disables the tests locally when this value is true.
void prepareGoldenTests(FutureOr<void> Function() testMain) {
const isContinuosIntegration = bool.fromEnvironment('IS_CONTINUOUS_INTEGRATION');
return AlchemistConfig.runWithConfig(
config: const AlchemistConfig(
platformGoldensConfig: PlatformGoldensConfig(
renderShadows: true,
obscureText: false,
enabled: isContinuosIntegration
),
),
run: testMain,
);
}
Running tests using the —dart-define
Running the tests using the —-dart-define
environment declaration is pretty simple. See the command below to run the tests for a continuous integration environment.
flutter test --dart-define=IS_CONTINUOUS_INTEGRATION=true
Conclusion
The Golden Test is important for maintaining the code and the project's health. Sometimes, the standard Golden Test tool is insufficient to cover all cases possible; therefore, using the Alchemist tool gives developers a powerful tool to develop the appearance test and a way to use it in their continuous integration environments.
Posted on March 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.