๐Ÿ“ฑ 22 / 100 Days Of Flutter, Kate's edition โ€” writing my first unit test after 10 years in programming ๐Ÿ™€

๐Ÿ“ฑ 22 / 100 Days Of Flutter, Kate's edition โ€” writing my first unit test after 10 years in programming ๐Ÿ™€

Hi, Flutter community! ๐Ÿ‘‹ I'm back with an update on my Flutter challenge.

In the past weeks, I was learning a lot about unit testing in Dart as part of the Andrea's Flutter course.

Testing mindset

Developers are often criticised for not writing enough unit tests. After more than 10 years in web development, I've written very few unit tests. Of course, I was aware of the concept, but I couldn't remember any useful unit test I have ever created ๐Ÿคทโ€โ™€๏ธ

One reason is that modern development is often about connecting different components and libraries. Testing glue code with unit tests won't guarantee that the resulting application works. I mostly write end-to-end tests that run the app in a headless browser and perform actions like a real user (Flutter has end-to-end tests too, but I haven't tried them yet).

Another reason to skip unit tests is the learning curve. Thinking in tests requires practice and knowledge of dozens of testing patterns, such as faking, mocking, testing asynchronous code, assertions, exceptions, debugging, coverage and many more.

Having said that, I'm super excited to practice test writing in Andrea's course! Unit tests bring huge value to the code architecture by forcing developers to organise code in testable units.

Unit testing

Unit testing in Flutter effectively means unit testing in Dart. Below is an example of a trivial unit test from the docs:

test('.parse() fails on invalid input', () {
    expect(() => int.parse('X'), throwsFormatException);
  });

The standard testing framework is powerful and well-documented. In addition to that, I used mocktail for mocking dependencies.

Widget testing

On top of Dart unit tests, Flutter provides a lightweight widget testing solution.

testWidgets('Testing MyWidget', (WidgetTester tester) async {
  await tester.pumpWidget(MyWidget());
  await tester.tap(find.text('Save'));
  await tester.pump();
  expect(find.text('Success'), findsOneWidget);
});

WidgetTester provides an API to manipulate widgets programmatically, for example tester.tap(find.text('Save')) will simulate tapping on the "Save" button.

Testing widgets with WidgetTester and testWidgets requires learning and practice, too. Similar to normal unit tests, it requires some setup and mocking. If your app uses Riverpod, you will need to wrap the widget in ProviderScope and pass necessary overrides.

Summary

For me, writing tests is the most complicated part of my Flutter journey to date! It let me off the rails for a moment, but I'm back on track and excited about what's next!

ย