3 Practical Steps for Fixing Software Bugs

Software is complex and often doesn’t work exactly as intended. As software developers, we tend to spend as much time fixing bugs as we do creating new features. There are many strategies for limiting the number of bugs that a software system has, but no process is perfect.

What steps should you take to ensure that a bug gets fixed? How do you ensure that the same bug isn’t reintroduced at a later date? The answer to these questions inherently depends on the severity of the bug and whether it’s easy to fix. But there are some common steps you can take to make sure it’s fixed properly — and stays fixed.

1. Triage/Investigation 🔎

The first step toward fixing any problem is to gain a clear understanding of what’s causing it. If you have a puddle of water in your basement, it’s important to figure out where that water came from before cleaning up the puddle and calling the problem “fixed.” You have to determine the source of the issue.

If this bug was reported in a backlog management system, make sure that it has all of the valuable information that you need to diagnose the issue:

  • Repro-steps
  • Screenshots (if applicable)
  • Error messages

Once the bug report has all of the necessary information, review the reported behavior and compare it with the requirements for how the software is intended to work. There’s always the chance that the source of the bug is a miscommunication in requirements for those that are testing them. If the bug report is accurate and you are able to reliably reproduce the problem, it’s time to move on to the next step.

2. Write New Test Cases 🧪

The bug report likely specifies an example that can be reproduced, whether it involves logging in as a specific user role or submitting a collection of data in a form. These user actions translate into data flowing through the system — a series of input values that we can test against the expected output values. Use this data to write new test cases.

At this point, the tests should be failing. The actual behavior isn’t matching the expected behavior. Once the tests are written, we can quickly iterate on the solution to the problem. The rapid feedback from the tests saves us time (compared to testing each attempted fix manually).

Eventually, you’ll find the source of the issue and fix it. The tests will now succeed, and you’ll be able to verify that the reported issue has been taken care of. These automated tests act as proof that the cause of the issue was fixed, and they’ll be a safeguard against a possible regression.

3. Review the Changes 🤝

If you work with a team of other software developers, have someone else review your changes before merging/deploying them. Whether this is pair-programming while trying to fix the bug or a more formal Pull Request process, having someone else review the changes provides several benefits:

  • It forces you to summarize the reported problem and indicate how your changes fixed it.
  • It gives another person the opportunity to provide feedback on the changes you made and offer suggestions on how to improve them.
  • It allows you to share knowledge with other team members, which will hopefully help mitigate similar bugs in the future.

If you don’t have anyone to review your changes, review them yourself. Review the git diff between your branch and develop (or whatever base branch you’re merging into), and critique the changes that were made to each file.

Make sure to test it again once it’s merged into the base branch. There’s always the chance that upstream changes or a botched merge conflict resolution are causing failures.

Software developers are great at fixing issues, but we often find ourselves needing to fix issues that we unknowingly introduced. Having a process for diagnosing and resolving these issues in a quick and efficient manner makes it easier to deal with them.