what i learned last week: intro to test driven development
Tags: angular, tdd
Published: 2022-03-14 16:29:42

_Prerequisite: Angular.js_

Throughout the past several years, as I've launched my developer career, the one practice that has seemed daunting to me is Test Driven Development. It mostly stems from the fact that up until my time at General Assembly I never implemented it into my codebase. That has all changed as I prep for an upcoming interview that will go over TDD. So to practice I've decided to dedicate this weeks entry to this feared and misunderstood practice. 
 

<img width="100%" style="width:100%" src="https://media.giphy.com/media/IzRWsOco0Zp7woExht/giphy.gif">

**WHAT?**

So what is Test Driven Development?

Per [Wikipedia](https://en.wikipedia.org/wiki/Test-driven_development), Test-driven development (TDD) is a software development process relying on software requirements being converted to test cases before software is fully developed, and tracking all software development by repeatedly testing the software against all test cases. This is as opposed to software being developed first and test cases created later.

Okay, but what does that mean?

In other [words](https://www.guru99.com/test-driven-development.html), test cases for each functionality, of a program, are created and tested first and if the test fails then the new code is written in order to pass the test and making code simple and bug-free.

![tdd flow graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2h6afzaf3lb9t6pcbi4j.jpg)

**HOW?**

![tdd steps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t42n3tws3xe1dx7iazzt.png)

So how exactly does test driven development [work](https://developer.ibm.com/articles/5-steps-of-test-driven-development/)? 

1. Read, understand, and process the feature or bug request.
2. Translate the requirement by writing a unit test. If you have hot reloading set up, the unit test will run and fail as no code is implemented yet.
3. Write and implement the code that fulfills the requirement. Run all tests and they should pass, if not repeat this step.
4. Clean up your code by refactoring.
5. Rinse, lather and repeat.

_Note: In Angular, there are two main types of tests._

_A [unit test](https://smartbear.com/learn/automated-testing/what-is-unit-testing/#:~:text=A%20unit%20test%20is%20a,of%20the%20definition%20is%20important.) is a way of testing a unit - the smallest piece of code that can be logically isolated in a system. In most programming languages, that is a function, a subroutine, a method or property._

_[End to end](https://medium.com/swlh/angular-end-to-end-testing-with-protractor-55897de591be) testing is the process of validating an application’s workflow from the beginning to the end. This testing methodology is aimed at replicating real user scenarios, so that the system can be validated for overall functionality._

TDD EXAMPLE: 

_Note: I'm going to being using Jasmine to test out my code. [Jasmine](https://www.digitalocean.com/community/tutorials/testing-angular-with-jasmine-and-karma-part-1) is a behavior-driven development framework for testing JavaScript code that plays very well with Karma. Similar to Karma, it’s also the recommended testing framework within the Angular documentation as it’s setup for you with the Angular CLI. Jasmine is also dependency free and doesn’t require a DOM._

Lets get to it, in the terminal I'm going to create a new Angular project by running the following command. 

`ng new zoo`

Next, I'm going to create a new component named "zoo".

`ng generate component zoo`

![test4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71zdevt169683b4np3d0.png)
 
Now that my new Angular project has been created I'm going to head over to my terminal again and run the following command.

`ng test`

The terminal output will look like the below screenshot. 
![test2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl2q2tzf2nws8hhtkpu6.png)

Also, a browser window will open up letting you know all of the initial tests are passing. Neat, huh?

![test5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1vvm5ku6cpksjtin9vbi.png)
 
 
Per the **first step**, I need to figure out what new feature I want to build out. In this case, I want my zoo component to have a name.

**Second**, I need to translate the requirement by writing a unit test.

In `zoo.component.spec.ts` write the following test. 

```
 it('should have a name', () => {
    expect(component.zooName).toBeTruthy();
  });
```

You'll notice that the test fails because no code has been implemented.
![test6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ooqwa8ha1yych1akhrq.png)
 
**Step three** states that I need to now implement code that makes the test pass. How would I do that in this example? I simply need to create a new property in the zoo component called "named" and add a value to it. 

![test7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gnoil81pt7zmghug7175.png)

Sweet! All of our tests are now passing!

This was a simple example and don't need to refactor but next we would usually want to move onto **step four** and refactor. 

_Voila! You've implemented your first application feature utilizing TDD!_

**WHY?**

Test Driven Development gives developers the confidence that our code will work 100% of the time in the expected conditions. 

TDD provides several [benefits](https://www.ibm.com/garage/method/practices/code/practice_test_driven_development/):

It can enable faster innovation and continuous delivery because the code is robust.

It makes your code flexible and extensible. The code can be refactored or moved with minimal risk of breaking code.

The tests themselves were tested. A key characteristic of a test is that it can fail, and the development team verifies that each new test fails.

The code that is produced is, by design, easy to test.

The requirements are implemented with little to no wasted effort because only the function that is needed is written.