The Challenges of Debugging without Unit Testing
Debugging code can be a frustrating and time-consuming process. Without the aid of a debugger or logging system, programmers often have to rely on running the code and thinking hard to identify and fix bugs. In a recent blog post on HackerNews, the author shares their experience of debugging a maze-drawing program and reflects on the potential benefits of unit testing in such situations.
The Bug Hunt
The author describes their maze-drawing program, which starts in the upper left corner and follows a set of rules to draw a maze. However, the program kept getting stuck, and the author had to spend a significant amount of time staring at the code to find the bug. Eventually, they discovered that the issue was a simple mistake that only required two lines of code to fix.
One of the challenges the author faced during debugging was the lack of a debugger or logging system. They had to rely solely on running the code and thinking hard to identify the bug. This made the process more time-consuming and frustrating.
The Role of Unit Testing
The author then raises the question of whether unit testing could have saved them time during the debugging process. They differentiate between regular testing, which they were already doing, and unit testing, which focuses on testing individual units of code.
They argue that the effectiveness of unit testing depends on the language and tooling available. In their case, they were working with an environment that did not have built-in support for unit testing. Any unit testing they would have done would have required writing additional code.
The author also reflects on their experience working with C and C++ at a previous job. They mention that these languages require a lot of upfront work to support unit testing effectively, and the lack of a unit testing framework made it even more challenging.
The Challenges of Testing in Assembly
In their current project, which involves writing code in 6809 Assembly, the author faces additional challenges when it comes to testing. The tooling does not support linking 6809 code, so they have to copy the routine they want to test into a separate test program. This introduces the possibility of bugs in the test program itself.
The author also questions the trust placed in programmers to write testing code without testing it. They argue that if programmers are not trusted to write code without testing, why should they be trusted to write testing code without testing it as well?
The Bug Discovery Process
Despite the challenges, the author eventually discovers the bug in their maze-drawing program. They explain that the bug was in the getpixel subroutine, which returns the color of a pixel at a given location on the screen. The bug was caused by a failure to check if a value was zero before decrementing it, resulting in the wrong value being returned for the last pixel in any byte.
The author admits that a unit test of the getpixel subroutine would have caught the bug. However, they question whether the time spent writing the test code would have been worth it, considering the need to write a testing framework from scratch.
The Importance of Language and Tooling
The author concludes by emphasizing the importance of considering the language and tooling involved in a project when deciding on the testing approach. They argue that the ease of testing depends on the language and tooling available, and that unit testing may not always be the most efficient or practical option.
While unit testing has become a popular approach in modern software development, the author highlights the limitations and challenges they have faced in their specific environment. They suggest that a more nuanced approach to testing, taking into account the specific requirements and constraints of each project, may be more effective in certain cases.
Overall, the blog post offers valuable insights into the challenges of debugging without unit testing and prompts readers to consider the role of language and tooling in the testing process.
Unit testing on an 8-bit CPU