Test-driven development seems overwhelming, but really there are only three core steps to it.
They are known as Red, Green, and Refactor.

Step 1: Red
The first step is to write a minimal failing test.
Suppose we want a function `countUp` that prints the numbers from 1 ton.
If n is 3, then the output would be this
1
2
3
The test could look like this.
it('prints the numbers from 1 through n', () => {
const logSpy = vi.spyOn(console, 'log');
countUp(3);
expect(logSpy.mock.calls).toEqual([[1], [2], [3]]);
});
It makes sure console log is called, and the output when n equals three is correct.
Now write the minimal code that makes the test fail:
function countUp(n: number) {
}
Step 2: Green
Step two is to write just enough code to make the test pass.
function countUp(n: number) {
for (let i=1; i<=n; i++) {
console.log(i)
}
}
This code goes from 1 to n and prints all the numbers.
Step 3: Refactor
The last step is to refactor and improve the code quality.
With the test, you can refactor without worrying about breaking things.

Since this is a small function, there's not much to improve here.
Let's rename the function to make it more descriptive:
function printRange(n: number) {
for (let i=1; i<=n; i++) {
console.log(i)
}
}
And also the name in the test file:
it('prints the numbers from 1 through n', () => {
const logSpy = vi.spyOn(console, 'log');
printRange(3);
expect(logSpy.mock.calls).toEqual([[1], [2], [3]]);
});
These three simple steps make your code more robust and reliable.
- Fee from Anime Coders


