The 3A's: Simple Steps For Clean Unit Tests
Tags: unittest, tdd, programming, softwareengineering
Published: 2023-07-08 06:51:24

> "I find that writing unit tests actually increases my programming speed" - Martin Fowler (Software Engineer)

A couple of days ago, I was developing a feature at my work. I was wondering why my Pull Request doesn't have clearance for merge. After I check, there was a failed unit test in my module. It turns out that after I rebase my branch to the latest master, my changes break functionality in a component. Imagine if there was no unit test to assess the functionality of the component, my changes could've been deployed to production. Then thousands of users will get a broken component. It will be catastrophic. That's how important a unit test is.

Besides code implementations, software developers are also responsible for creating unit tests for their applications. Unit tests could prevent unexpected changes made by developers that might raise an issue in the production environment. Good unit tests will improve code stability and reliability within your repository. In my journey creating unit tests, I usually follow these simple three steps to achieve good reliable unit tests. The 3A's: arrange, action, and assert.

## Arrange

The first step is to prepare what is needed for the test. Decide a test name, and make it as human-friendly as possible. Think about what are the test cases we would like to test. For example like `'it should created user with the correct name and id'` or `'it should render successfully'`. 

Prepare your mock environment if you need it. Create your mock data, API, component, function, or whatever they are to support your test to run smoothly. You can mock anything that you deemed unnecessary for your specific test case.

```typescript
describe("Add Function", () => {
  it("should add successfully", () => {
    // Arrange
    const input = [2, 3];
  });
});
```

## Act

Act steps should cover the main thing to be tested. This could be calling a function or method. Act means running the operation or method that you want to test. In UI testing, it can also stand for user actions that are possible to do. Such as clicking a button, hovering over an area, etc. Act steps usually produce a result.

```typescript
describe("Add Function", () => {
  it("should add successfully", () => {
    // Arrange
    const input = [2, 3];

    // Act
    const result = add(...input);
  });
});
```

## Assert

Assert is the step where you check the result in the act step. It's to check whether the result is already expected like you want it to be. Given the input, is the function already produce the correct output? Or is the modal  already shown if the button is clicked? Assertions will ultimately be the end goal of a test case. It also determines whether a test case passes or fails.

```typescript
describe("Add Function", () => {
  it("should add successfully", () => {
    // Arrange
    const input = [2, 3];

    // Act
    const result = add(...input);

    // Assert
    expect(result).toBe(5);
  });
});
```

------------------------------------------------------------

By following these 3 simple steps: arrange, act, and assert, we can write clean unit tests that are reliable and maintainable. It shapes our framework of mind when we wrote a test so that our tests aren't all over the place. A good unit test will also increase the confidence of developers when they do iteration changes. Cause they knew that there is a guard to catch those anomalies should anything goes wrong.