As I was graduating from the Flatiron School, I realized that I've gotten a good amount of practice writing code, but I have not had any practice with writing tests for said code..
We recently had a fireside chat on campus with Cassidy Williams, an engineer at CodePen and she mentioned the importance of writing tests for your code. She gave us an example of a coding challenge scenario you and X other people get the same take home code challenge. Let's say you flew through it but neglected to write tests whereas the other people did, and you inadvertently pulled yourself out of the race without knowing any better.
From what I've gathered online it's to your discretion when you think writing tests for your code would be necessary, worth it time wise, etc. but the underlying point remains: understand how to test your code so that you can prove your comprehension and demonstrate that your code works. Testing helps you write code with confidence.
Before we dive in I wanted to point out the three types of testing:
Unit testing: Tests small portions of code to establish code is optimal
Integration testing: Tests combinations of units and how they run together
Acceptance testing: Tests an application in the browser/on a device to analyze the overall performance as a whole
This blog post will focus exclusively on Unit Testing with a Test Driven Development(TDD). The main difference between TDD and BDD (Behavior Driven Development) is TDD being tested against a set of expectations with a pass/fail outcome, and BDD describing the behavior of the applied function, also with a pass/fail outcome. Both methods will demand tests to be written out prior to any implementation of the code.
A unit test will run a bit of code over a segment of the program you're working on while checking the input and output. Unit tests help developers control and audit different areas of their code and see where and why errors exist. Checking for errors and bugs can be extremely difficult to do when you don't know where to look, and this is where unit testing comes in.
Earlier I mentioned the importance of writing tests before implementing any code. The science of TDD can be broken down and supported (by the online community and their many blogs) in that TDD can help you reduce bug density in your code. It can encourage more modular designs- enhancing software agility and team velocity. And finally, it can reduce code complexity.
What TDD enables you to do is plan out what it is that you are wanting to achieve, how you want to achieve it, and what you expect to achieve so that when it fails you have a better understanding of where to go looking for bugs. So...
First, we need to understand how tests are used:
- Design aid: written during the design phase, prior to implementation.
- Feature documentation & test of developer understanding: The test should provide a clear description of the feature being tested.
- QA/Continuous Delivery: The tests should halt the delivery pipeline on failure and produce a good bug report when they fail.
Next, we need to look at the failing test and try to pinpoint where the error is coming from.
- What are you testing?
- What should it do?
- What is the actual output?
- What is the expected output?
- How can the test be reproduced?
Let's break it all the way down. At its core, your test name should be explicit, descriptive and concise. If you run into an error, this should be the first thing you check for.
The "describe" argument should have a clear description of the unit of work. The "it" argument should have a 'should[expected behavior] when [scenario/context].'
Unit tests provide great initial feedback from broken code. They focus on one thing at a time and help you, the coder understand where your errors and bugs are occurring. Implementing TDD to your projects and challenges will help you and your team better map out your task and reduce the likelihood of bugs. Its all about prevention and understanding your code on a micro level.