How To TDD For Dummies
Tags: webdev, tutorial, java, javascript
Published: 2021-06-20 21:11:32

## What is Test Drive Development? 👀
- It's the process of letting tests lead our development.
- Write a test that fails and then write the production code that will make it pass.

## How To Name a Test? 🧠
- I like to follow the Given_When_Then format.
- We specify three things
	-The conditions predefined for the test (**Given**)
	-The action that will be tested (**When**)
	-The result we wait for (**Then**)

## TDD Rules ⚖️
According to Uncle Bob, TDD has three rules

You are not allowed to:
1. Write any production code unless it is to make a failing test pass.
2. Write any more production code than it is sufficient to pass the single failing test.
3. Write any more unit test code than it is sufficient to fail.
	-  Compilation failures are considered failures.

### Confession 🤭
- I don't follow those rules 100% of the time.
- Sometimes I write more production code than what makes the test pass, sometimes I write code without tests.
- It's human nature I think, we can't follow the rules all the time  


## Code Example For a Calculator 🧮

### Let's look at the requirements
- The method can take 0, 1 or 2 numbers as a string, and will return their sum (for an empty string it will return 0)

👉 First of all, let's write the code to handle the empty string case

```java
    @Test
    public void givenEmptyString_Return0(){
        CalculatorService calculatorService = new CalculatorService();
        int result = calculatorService.getSum("");
        assertEquals(0, result);
    }
```
When you write this code, it will give you a compilation error because `CalculatorService` and its `getSum` method don't exist.
So, we create the service and its method and write a simple logic to return 0 on empty strings

```java
public class CalculatorService {
    public int getSum(String s) {
        if (s.isEmpty())
            return 0;
        else
            return 1;
    }
}
```
Note that the 1 in the else statement is an arbitrary value used to avoid compiler error since we have to return a value from the method.

---
👉 Now, let's write a test to handle strings with 1 number
```java
    @Test
    public void givenAStringWith1Number_ReturnIt_WhenCalculateSum(){
        CalculatorService calculatorService = new CalculatorService();
        int result = calculatorService.getSum("5");
        assertEquals(5, result);
    }
```
When we first run this test, it will fail because the returned value is 1. So let's make it work

```java
    public int getSum(String s) {
        if (s.isEmpty())
            return 0;
        else if (s.length() == 1)
            return Integer.parseInt(s);
        else
            return 1;
    }
```
---
👉 Next, let's write a test to handle strings with 2 numbers
```java
    @Test
    public void givenAStringWith2Numbers_WhenCalculateSum_ThenReturnSum(){
        CalculatorService calculatorService = new CalculatorService();
        int result = calculatorService.getSum("69");
        assertEquals(15, result);
    }
```
This test will fail because 1 doesn't equal 15. duh!
Let's make it work
```java
    public int getSum(String s) {
        if (s.isEmpty())
            return 0;
        else if (s.length() == 1)
            return Integer.parseInt(s);
        else
            return getSumForMultipleNumbers(s);
    }

    private int getSumForMultipleNumbers(String s) {
        return Arrays.
                stream(s.split("")).
                mapToInt(Integer::parseInt).
                sum();
    }
```

## Celebration 🥳
### We've just applied TDD to program a really simple calculator.

## Further Readings 👨‍🏫
✅ [How To Unit Test Like a Pro](https://dev.to/jarjanazy/how-to-unit-test-like-a-pro-59kj)

✅ [5 TDD Most Common Mistakes](https://dev.to/jarjanazy/5-tdd-most-common-mistakes-2h0d)

##[Code On GitHub👩‍💻](https://github.com/Jarjanazy/java-tutorial/tree/main/src/main/java/TDDTutorial)