Mayowa Olufeko

Mayowa Olufeko

I design and develop
software applications



Test Driven Development And Jest

Test driven development is by far the best paradigm for creating concise, clear, test passing (it’s in the name) code. Test driven development in basics means that code is tested before it is written.

Usually when a software engineer writes code - it has the boring process of writing code then debugging any errors, writing code and debugging any errors, and following that cycle until they have this complex, repetitive code on their codebase. TDD changes all of this.

As I mentioned, TDD is all in the name. You create tests around the inputs, outputs and behaviours you want to see for each module you create in the program, fail these tests on purpose, then write code for the test to pass. You refactor the code after this.

The TDD Process

TDD starts with a description of what the code is testing, followed by an assertion of the code that runs the test. TDD has a 3 step process to writing code through its paradigm:

Step 1. Failing the test
Code is written to fail on purpose. This validates that the test is working correctly.

Step 2. Passing the test
The most minimal amount of code is written here

Step 3. Refactor (optional)
Once tests are passed, code is refactored. This step is up for debate, as there is 100 ways you can refactor code, and one engineers refactor could be another engineers verbose code, so I say as long as the program isn't overly complicated, this isn't needed. That being said, when looking to solve a problem as quickly as possible through TDD, all sorts can be written to pass the test cases, so refactoring is a necessary yet optional step to include.

Example Of TDD

Problem

Mayowa University has cohorts accepted into their university on a monthly basis. The list of all students is stored in one object. I need to check that all students are from the same cohort before sending information. So I will need to create program that will return true if all the students are in the same cohort, so we can go ahead and send them information, or false so we can adjust the list so each student is the sent the correct information.

Test 1: Should return a boolean

We want to first check that the function returns the correct data type: a boolen which evaluates to true or false

tdd-jest-test1

Once we have created our test, we create a function that fails

tdd-jest-test-fail tdd-jest-test-fail-terminal

Then, we write code that passes the test

tdd-jest-test-fail tdd-jest-test-fail-terminal

Test 2: Should return true if students are all in the same cohort

We know the function will return the correct data type. Now we test if it will return the right boolean evaluation when passed the parameters. So we write the test for this

tdd-jest-test-fail-terminal

First, we write the failing code

tdd-jest-test-fail-terminal tdd-jest-test-fail-terminal

Then we write passing code

tdd-jest-test-fail-terminal tdd-jest-test-fail-terminal

Test 3: Should return false if all students are not in the same cohort

This completes the true or false evaluation returns. We first write the test

tdd-jest-test-fail-terminal tdd-jest-test-fail-terminal

Then we write the code to pass the test

tdd-jest-test-fail-terminal tdd-jest-test-fail-terminal

Test 4: function does not mutate original array

This is when testing gets a bit interested. We want to make sure that the values in the array do not change after being used by the function. Here is the test for this

tdd-jest-test-fail-terminal

Code to fail the test

tdd-jest-test-fail-terminal tdd-jest-test-fail-terminal

Code to pass the test

tdd-jest-test-fail-terminal tdd-jest-test-fail-terminal

Why I Like Test Driven Development

Whoever said software engineering isn't creative is a liar. TDD means in most cases you are using your imagination to write code that will fail a test it passes through. Failing tests on purpose isn't in my vocabulary, but for SE I am happy to fail anytime of the week. Heres why I like TDD:

Higher Code Quality

Code quality has a sharp improvement through TDD, becase the modelling of expected inputs, outputs, and behaviours of a module. Modelling this gives a software engineer the chance to slowly build up their program with the full confidence it will do as expected. Each test written breaks down the whole program, allowing from unit, integration, and end-to-end testing. Each process increases the robustness of the design of the program. Building on top of each test ensures that previous code stays the same, and that any functionality added after does not break previous functionality.

Acts As Documentation For Design And Requirements

As mentioned above, the design of the program is thoroughly planned through TDD. Higher code quality is a natural consequence of TDD because running tests acts like documentation for the module, so if another engineer has to modify anything, they can look at the tests and understand what the functionality of the module is, and already have a structure to write additional code without breaking it, and not knowing why a object (for example) is not having a property changed.

Faster Debugging

Without TDD, a software engineer would write a program, and when it doesn't do what it was meant to as expected, they would need to go through the long debugging process (as I mentioned at the start). TDD reduces this drastically. The terminal provides information (as you can see from images above) as to wha tests have passed and failed, along with why. Sprinkling in some console.logs also helps this process.

Full Confidence Refactoring

After ensuring a module behaves in the way expected, refactoring beacome a slice of cake if need be. Focus on getting it working, then trim away whats needed. Sounds like a great paradigm to me.