DeepCode and Snyk joined forces. Find out more in our blog.

SummerAcademy on Debugging - 2.1.8 Unit Tests

Thursday, September 3rd, 2020

(source: https://twitter.com/ben_j_lindsay/status/1298333134958755841)

The term ‘Unit test’ describes a unit of work that should be tested: One lightweight test of one unit of work.

Lightweight means they are fast, easy to read and write, repeatable, and therefore consistent.

Note: Unit tests need to be independent of each other If Unit tests build on each other (aka need the certain sequence to run successfully), this is a recipe for disaster and chaos. Unit tests need to run independently.

Note: Unit tests need to be trustworthy A Unit test need to test what it says and fail reliably when outside of operational parameters.

Note: Unit tests are code They can be refactored and need to be read/maintainable.

We listed some very good further resources in the section below, from now on we will focus on Unit tests in Debugging especially. We also cover how to react when discovering bugs by unit tests in development in 3.2.

We suggest building a solution strategy first (see 2.2.1) - aka you experimented and you have a good idea how you gonna solve the issue at hand. Then check what is missing on a unit test side of things and add or change what is needed.

  1. In code-review, review the test code first.
  2. One major advantage of TDD is that you do not tend to test the internal implementation rather than the behavior (as obviously your code does not exist at the time of writing the test). Be sure to test the behavior and not the implementation.
  3. Check the code coverage of the code you are gonna change. Why was the bug not discovered by unit tests until now?
  4. You can apply TDD here, too. Just write the unit test(s) that replay your bug first, run them on the current code, and see them fail at first.
  5. Apply your patch and run the unit tests again. Make sure all unit tests (new ones and existing ones) are successful.
  6. Make use of snippet extensions to help you write your tests fast - personally I use Jest Snippets
  7. Also, think about Fuzz Testing (see JSFuzz by Github) - Fuzz Testing plays with parameters within certain ranges. They are really nice for business logic.

There are a variety of testing frameworks available and most of them do what you need them to do. We found the following criteria helpful:

  • Does the framework support your environment (React, Vue, Node…)?
  • Does it provide some reporting like code coverage?
  • Is it fast so it can easily run on a developer’s machine?
  • How much effort is it to configure and run?
  • Is the framework project alive and kicking?

What if my legacy code is not covered by Unit Test

This is a pretty common situation: Test coverage is next to or exactly zero. Now you need to make a guided decision whether to do something about it or just leave as is.

The first frog to swallow: You cannot reintroduce Test Driven Development after the fact. Decisions on the implementation have been made. In general, trying to write Unit Tests in bulk for legacy code does not make sense. You tend to test the code as it was written (instead of what was intended to be done). So aftermath unit tests seem to test the most obvious things returned by the code anyways.

On top, you can obviously use Test Driven Development for any new code. See our later article on this.

But Unit Tests can help you in debugging: You can add tests to reflect extreme cases or add fuzzing to already existing code you suspect to be wrong. It frees you from debugging the whole system just to inject a few data points. So, using unit tests (and mocking) might save you a lot of time (and even better), makes your debugging tests repeatable and packageable.

Key Take-Aways

Unit test are a valuable tool but reintroducing TDD after the fact is next to never a good idea. Rather, use them for all new code.

Resources

freecodecamp of Unit Testing with JavaScript codeacademy on JavaScript Unit Testing

js-unit-testing-guide

Node+JavaScript Testing Best Practices