Why We Call Saving the Magical Feature
Tags: welltested, testing, flutter, ai
Published: 2023-10-19 08:42:23

Recently, the entire team at Welltested AI engaged in a discussion to understand what according to us is the most notable feature of Welltested at the moment. And, everyone agreed upon `welltested save unit` which we also call the magic command :)

While we internally love it, quick analytics into our database showed us that most of our users are not yet using it!  This led to the question: are we talking about it enough? haha.

So, we decided to write this blog to share with our users what is so special about Welltested's **save** feature and how to use it effectively. Let's dive into it.


### Setup Your Project

For starters, download the [flutter twitter clone](https://github.com/TheAlphamerc/flutter_twitter_clone) project that we will be using. You can also use your project or download any other open-source project of your choice to follow along. The steps that we will follow will mostly remain the same. 

Next, open the project in the IDE. After opening the project, we will need to head to [Welltested](https://pub.dev/packages/welltested) on pub.dev. Then, follow the instructions available on the page to set up Welltested. Since the setup process is fairly straightforward and well-documented, you will not face any issues following along. The general steps include:

1. Getting the API key and adding it to the project
2. Adding the Welltested packages
3. Activating Welltested CLI in your terminal

Once done we are ready to generate and save the tests :)


### Generate Unit Tests

To generate the tests. We'll need to add the `@Welltested` annotation to the methods or classes for which we need to generate tests. This will help Welltested pick methods for whom test generation is requested. 

Open **lib/helper/utility.dart** file in the project. We will find `Utility` class with a bunch of static methods declared inside it:


![Utility Class Definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pox9k2p4joe1igeqqfcf.png)

For this blog, we will generate tests for the methods present in the Utility class only. Add the Welltested annotation at the top of the `Utility` class:

```dart
@Welltested()
```

This annotation above the `Utility` class enables Welltested to know that we're interested in generating tests for the methods defined in this class.

Next, we will generate the tests by running the following chain of commands in the terminal:

```bash
welltested generate unit -m getPostTime2 && 
welltested generate unit -m getDob && 
welltested generate unit -m getJoiningDate && 
welltested generate unit -m getUserName
```

Upon execution of the above commands, Welltested will start generating the tests for the methods mentioned after the `-m` parameter that have the `@welltested` annotation too - either directly or on the class containing the methods.

Open the generated tests located in the **tests/helper/utility** directory after the execution of the generate commands is finished. Take a look at the generated files. Congratulations! You have successfully generated tests for your code in less than 5 minutes. Isn't it great :)

Looking at the generated tests. You will see that some of the tests have errors:


![Fig. 2 — Generated Tests Errors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1kisupcx0iipth6iohw.png)

But don't worry, Welltested has got you covered here. And this is where the Welltested's **save** command shines 😎

### Welltested's Save Command

Welltested AI has the ability to constantly learn and improve as you interact with it. Since this is our first interaction with the AI, it may make mistakes in the initial tests as it hasn't yet learned about your project and your coding style. However, fixing this is simple.

You can just simply fix the broken generated tests and save the tests using Welltested's `save` command. Welltested will automatically learn from them and provide much smarter and error-free test cases in the future.

To understand this in more detail. Let's look at an example by updating and saving one of the earlier generated unit tests. Afterwards, we will use Welltested's `generate` command to generate the remaining tests again.

Open **test/helper/utility/getPostTime2.welltested_test.dart** file and update it with the following:

```dart
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_twitter_clone/helper/utility.dart';

void main() {
  group('Utility getPostTime2', () {

    // 1.
    // Older version
    // test('When date is null, should return empty string', () {
    //   final mockUtility = MockUtility();
    //   when(mockUtility.getPostTime2(null)).thenReturn('');
    //   expect(mockUtility.getPostTime2(null), '');
    // });
    test('When date is null, should return empty string', () {
      expect(Utility.getPostTime2(null), equals(''));
    });

    test('When date is empty, should return empty string', () {
      expect(Utility.getPostTime2(''), equals(''));
    });

    test('When date is not in correct format, should throw FormatException',
        () {
      expect(() => Utility.getPostTime2('invalid date'), throwsFormatException);
    });

    test('When date is in correct format, should return formatted date', () {
      String date = '2022-12-01T20:18:04';
      String expectedDate = '08:18 PM - 01 Dec 22';
      expect(Utility.getPostTime2(date), equals(expectedDate));
    });

    // 2.
    // Older version
    // test('When date is in correct format but in different timezone, should return formatted date in local timezone', () {
    //   final mockUtility = MockUtility();
    //   String date = '2022-12-01T13:18:04Z'; // This is 20:18 in GMT+7
    //   String expectedDate = '08:18 PM - 01 Dec 22';
    //   when(mockUtility.getPostTime2(date)).thenReturn(expectedDate);
    //   expect(mockUtility.getPostTime2(date), equals(expectedDate));
    // });
    test(
        'When date is in correct format but in different timezone, should return formatted date in local timezone',
        () {
      String date = '2022-12-01T14:48:04Z'; // This is 20:18 in IST
      String expectedDate = '08:18 PM - 01 Dec 22';
      expect(Utility.getPostTime2(date), equals(expectedDate));
    });
  });
}
```

On comparing the updated code with the previously generated test code. You will find two major differences here:

1. The generated code utilizes `MockUtility`, which is a mock version of the `Utility` class. However, the updated code directly employs the `Utility` class. This is because our objective is to test the methods that are encapsulated within this class.
2. The final test case aims to verify that the `getPostTime2` function accurately converts a date from a different time zone into the local time zone. Initially, the AI assumed GMT+7 was the local time zone, but this led to a failure because my actual local time zone is IST. Consequently, the code was adjusted to employ a date that, when processed by `getPostTime2`, would align with the date stored in the expectedDate variable for Indian Standard Time (IST).

Now, since we have only updated one test, we will delete all other generated tests. This is because when we execute the `save` test command, Welltested saves all the tests it has generated and that are present in the test directory. We want to ensure that our AI doesn't learn from code with errors. Don't you agree?

After deleting all the test files except **/getPostTime2.welltested_test.dart**, run the following command in the terminal:

```bash
welltested save unit
```

After a successful save, you'll receive the following message in the terminal:

```bash
✅ Succeeded. 1 were saved.
```

Now, add the following command on the terminal to generate tests again:

```bash
welltested generate unit -m getDob && 
welltested generate unit -m getJoiningDate && 
welltested generate unit -m getUserName
```

After the test generation is completed. Revisit the generated tests:


![Fig. 3 — Updated Tests using Welletested](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9kduzq1zrkfvqx10c34s.png)

This time, the tests adhere to our coding style. Also, the generated code correctly uses the local time zone for my case based on the saved code which is fantastic. Don't you agree? I certainly do.

### Conclusion

By now, I hope you can appreciate the power of saving tests in Welltested and how it can assist you in crafting more efficient tests tailored to your specific needs and coding style.

I encourage you to generate tests using Welltested and to save all of them. This will not only speed up the test generation process but also enhance the quality of your tests over time. Happy Testing :)