Yelaman Yelmuratov
Posted on July 3, 2024
Hi there, I already wrote an article about ApprovalTests for unit tests.
In this article we will touch on Widget tests and how this package can be useful for us.
Let's briefly go through again what exactly are ApprovalTests?
In manual code testing, developers usually write automated tests to guard against regressions, specifying the expected outcomes directly in the code. ApprovalTests
uses a similar method but stores the expected outcomes in a file instead. This file is generated by the test library rather than the developer, making the process of writing and maintaining tests more efficient. As a result, developers can spend more time on the functional code rather than the test code.
📋 How it works step by step
- The first run of the test automatically creates an
approved
file if there is no such file. - If the changed results match the
approved
file perfectly, the test passes. - If there's a difference, a
reporter
tool will highlight the mismatch and the test fails. - If the test is passed, the
received
file is deleted automatically. You can change this by changing thedeleteReceivedFile
value inoptions
. If the test fails, the received file remains for analysis.
Instead of writing:
testWidgets('home page', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
await tester.pumpAndSettle();
expect(find.text('You have pushed the button this many times:'), findsOneWidget);
expect(find.text('0'), findsOneWidget);
expect(find.byWidgetPredicate(
(Widget widget) => widget is Text && widget.data == 'hello' &&
widget.key == ValueKey('myKey'),
), findsOneWidget);
expect(find.text('Approved Example'), findsOneWidget);
});
Write this:
testWidgets('home page', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
await tester.pumpAndSettle();
await tester.approvalTest();
});
To include your project's custom widget types in your test, and to perform post-test checks, add calls to Approved.setUpAll()
to your tests' setUpAll
calls, like so:
main() {
setUpAll(() {
Approved.setUpAll();
});
}
And the result will be something like this:
But if we for example change something and run the text, it will show us the difference, where it differs. There are several types of Reporter
in the project, but the standard is CommandLineReporter
, which gives the difference on the command line. Other reporters can be found in the project's Github repository.
Approving Results
Approving results just means saving the .approved.txt
file with your desired results.
We’ll provide more explanation in due course, but, briefly, here are the most common approaches to do this.
• Via Diff Tool
Most diff tools have the ability to move text from left to right, and save the result.
How to use diff tools is just below, there is a Comparator
class for that.
• Via CLI command
You can run the command in a terminal to review your files:
dart run approval_tests:review
After running the command, the files will be analyzed and you will be asked to choose one of the options:
-
y
- Approve the received file. -
n
- Reject the received file. -
v
iew - View the differences between the received and approved files. After selectingv
you will be asked which IDE you want to use to view the differences.
The command dart run approval_tests:review
has additional options, including listing files, selecting
files to review from this list by index, and more. For its current capabilities, run
dart run approval_tests:review --help
• Via approveResult property
If you want the result to be automatically saved after running the test, you need to use the approveResult
property in Options
:
void main() {
test('test JSON object', () {
final complexObject = {
'name': 'JsonTest',
'features': ['Testing', 'JSON'],
'version': 0.1,
};
Approvals.verifyAsJson(
complexObject,
options: const Options(
approveResult: true,
),
);
});
}
this will result in the following file
example_test.test_JSON_object.approved.txt
{
"name": "JsonTest",
"features": [
"Testing",
"JSON"
],
"version": 0.1
}
• Via file rename
You can just rename the .received
file to .approved
.
❓ Which File Artifacts to Exclude from Source Control
You must add any approved
files to your source control system. But received
files can change with any run and should be ignored. For Git, add this to your .gitignore
:
*.received.*
Show some 💙 and star the repo to support the project! 🫰
For any questions, feel free to reach out via Telegram or email at yelaman.yelmuratov@gmail.com.
Posted on July 3, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.