Even though Debugging and Testing might look to be a similar thing, they have a totally different meaning. Recently I attended to a meet-up, and one of the talks was about debugging in node and how easily you can find issues in your code by debugging it line by line. For me, it’s been a while since I used last time a debugger tool and this is because mainly I focus on writing tests.
What does debugging tools have to do with code tests if debugging is just a different stage of developing?
To understand the differences between testing and code debugging I will do a shortly description which will allow us understanding both of them.
To ensure the quality of a software program, this needs to be tested before being delivered to the client or launched in production. It involves the execution of a software/system component to evaluate one or more points of interest. Usually, these points of interest would define the range of behaviours under test, proving whether it:
- meets the requirements
- responds correctly to the expected inputs
- provides an output within a reasonable amount of time
- can run on its intended environments
Here are some of Software Testing types that I used to replace debugging:
- Unit Testing – focuses on a small unit of functionality
- Integration Testing – testing a group of components that combined, are producing an output
- System Testing – testing if the software can run in different environments
- Stress Testing – Provides a feedback about how the system behaves in difficult conditions
Debugging is a step by step inspection through your running code. It doesn’t magically show the bugs but you can find them by running the code step by step and find the exactly point where you have made a mistake.
All modern code debuggers offers a list of features that includes:
- breakpoints – allows you to set a breakpoint in your code
- watchers – watch for an expression or variable values
- stepping – step over, step into if the current line is a function and step out to return where the current function was called
- informations of the current state – being able to get informations about the current scope’s variables, backtrace, watchers
- execution control – provides the way to evaluate expressions
The most basic debugging approach is to print the variable values and check for correctness. Usually, developers put prints in the code and check the values after the execution which might become annoying if your program takes seconds to be executed or your application is verbose and it’s hard to find the logs. Here is where a debugging tool becomes handy as you can stop your code execution wherever you want and inspect.
Debugging Tools vs Code Testing
I used to use debugging tools in Ruby (pry / byebug) and C# (Visual Studio). Actually, 7 – 8 years ago when I first played with a debugger tool I thought that programming with a debugger was the future. Almost a decade later I am almost not using debuggers anymore. Even though they were great tools, I realised that even with debugging you can still spend a lot of time, the process is unstructured, unreliable and is very easy to lose the context. I say almost because sometimes the debugger is still the right choice for debugging.
When you are trying to fix a bug using debugger you will often get trapped into solving your local issue and miss a higher-level problem and recently I found a similar conclusion from Rob Pike (co-author of the Go Programming Language).
If you dive into the bug, you tend to fix the local issue in the code, but if you think about the bug first, how the bug came to be, you often find and correct a higher-level problem in the code that will improve the design and prevent further bugs.Rob Pike (Software Engineer @ Google) – Source
Anyway, how did I stopped using debuggers and find more useful to write tests?
I only start writing tests for my code 5 years ago, before I was more like debugging or print variables kind of developer, which is fine but it doesn’t guarantee that your code is safe after even if you fix the problem.
I even remember when one of my previous team leaders was saying that if you get to use debuggers you are in a desperate situation, you should not feel the need to use them if your code if 100% tested.
What I realised after start writing tests is that:
- it forces you to break your code in small pieces that can be tested easily
- testing is a good way of debugging by providing different inputs and test the expected
- your code is still tested even if you fix the bug or make changes
- if you don’t have tests you don’t have a guarantee that if you’re changing something it doesn’t break other part of the application
- I don’t need a debugger, my code is tested from many perspectives where I’m trying to cover all the unexpected cases