What the heck is Test-Driven Development anyway ?!
Tags: testing, javascript, react, webdev
Published: 2021-11-02 05:17:29

As the name suggests, in this METHOD of development, you write tests. A lot of them. But it comes with quite decent merits like **better reliability** & **maintainability** of the code and also lesser developers punching & lashing out at their laptops (that's a big one). Therefore, with this post, I'll teach you **_everything you need to know about testing web apps to get started!_**

### "Hey, but wouldn't I'll be slower at matching deadlines and writing ACTUAL CODE THAT WORKS"
Deciding when to practice it **IS THE REAL TASK**. While writing these tests, could cost you some time. You will be able **to know your code better** in **weird and most unexpected ways** And trust me, writing a test for your code is fun. (until the test has a bug itself because we don't write tests for tests to test our tests)
![what the what](https://media.giphy.com/media/xTiTnIilwuFFFpf2Cc/giphy.gif)
**Anyways!** What I here mean to say is **this practice has a very fine line of difference b/w being a lifesaver and a total waste of time**

## The Principles
The paradigm of test-driven development says that

> One should write a failing test, write some code to pass the test, and then write some more tests continuously refactoring the code alongside

![test driven development graph](https://cdn.hashnode.com/res/hashnode/image/upload/v1635698928851/FuAo1g9ep.png)

This philosophy is not always practical to implement like in cases where product requirements aren't stable and often changing. But fits ideal in situations that have very clear requirements, boosting productivity, code reliability & mental health significantly.

### "Sounds nice, but how can I write my tests?"
Before getting our hands dirty, we shall see some common types of tests

## Unit Tests
A unit test is a test written **to check the functionality of a unit of the software** like writing **tests for individual functions** can be called unit tests. Seeing what the functions return and how they interact with a given set of inputs.

## Integrations Tests
An integration test is written to **check/test interaction of several units of the software calling & referencing each other** to collectively produce a result.

![unit testing and integration testing](https://cdn.hashnode.com/res/hashnode/image/upload/v1635700895887/Lbema9j-4.png)

## End-to-End testing
There are many automated tools available in the market which ** run your app in a simulated environment in an attempt to emulate actual user behavior** checking on the orchestration of individual & collective blocks of code. [cypress](https://www.cypress.io) is a popular choice among other end-to-end testers.

Let's get started on TDD by writing out our first test

# Setup
So here I've got a React app. After clearing some unnecessary files, the file structure looks something like this. (Yes I deleted CSS files categorizing them unnecessary, what do you gonna call me? stylist?!)

![basic react js counter app file structure](https://cdn.hashnode.com/res/hashnode/image/upload/v1635765143219/zD-eD_CNH.png)

CRA (create-react-app) template already comes with some boilerplate code **including dependencies which are vital for testing** our full-fledged web app.
To get these libraries on independent web apps using React, check out the docs [here](https://nextjs.org/docs/testing#jest-and-react-testing-library). (**DOCS ARE ALWAYS RIGHT!**)

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1635765739652/M9VstWWyA.png)

Now, we're all set up, let's build the app!

# Code
So now, our motive is to build a fast, reliable, efficient, performant, ergonomic, economic, ecstatic, creative counter app. According to TDD's principles, we have to write a failing test then write the actual code which will pass the test.

Let us take a look at this test

```javascript
import { render, screen } from '@testing-library/react'

import App from './App'

test('Give some name to this test in order to see it written in red', () => {
	let counterCheck = 0
	
	render(<App />)
	
	// get the add button used to add counter
	const addButton = screen.getByText(/Add/)
	
	for (let i = 0; i < 3; i++) {
		// click the add button to increase the value of the counter
		addButton.click()
		
		// increment the value of our check alongside to compare counter and our check
		counterCheck += 1
	}
	
	// All operations on our element done lets now fetch and check the value of our element
	
	let linkElement = screen.getByText(/Counter Value: .+/)

	expect(linkElement.innerHTML === 'Counter Value: ' + String(counterCheck)).toBeTruthy()
	
})

```

Running the above test with **`npm run test`** will fail as we haven't defined the elements yet, Let's now create the counter app

![basic react js counter app](https://cdn.hashnode.com/res/hashnode/image/upload/v1635765279369/ZbYn1byih.png)

Now let's run the tests again...

![passing tests for the react counter app](https://cdn.hashnode.com/res/hashnode/image/upload/v1635770539766/UjQpybtTG.png)

![oh yeah!](https://media.giphy.com/media/26xBE8LbggMqwH1PW/giphy.gif)

-----------