On successful culmination of software testing, debugging is performed. Debugging is defined as a process of analyzing and removing the error. It is considered necessary in most of the newly developed software or hardware and in commercial products/ personal application programs. For complex products, debugging is done at all the levels of the testing.
Debugging is considered to be a complex and time-consuming process since it attempts to remove errors at all the levels of testing. To perform debugging, debugger (debugging tool) is used to reproduce the conditions in which failure occurred, examine the program state, and locate the cause. With the help of debugger, programmers trace the program execution step by step (evaluating the value of variables) and halt the execution wherever required to reset the program variables. Note that some programming language packages include a debugger for checking the code for errors while it is being written.
Some guidelines that are followed while performing debugging are discussed here.
- Debugging is the process of solving a problem. Hence, individuals involved in debugging should understand all the causes of an error before starting with debugging.
- No experimentation should be done while performing debugging. The experimental changes instead of removing errors often increase the problem by adding new errors in it.
- When there is an error in one segment of a program, there is a high possibility that some other errors also exist in the program. Hence, if an error is found in one segment of a program, rest of the program should be properly examined for errors.
- It should be ensured that the new code added in a program to fix errors is correct and is not introducing any new error in it. Thus, to verify the correctness of a new code and to ensure that no new errors are introduced, regression testing should be performed.
The Debugging Process
During debugging, errors are encountered that range from less damaging (like input of an incorrect function) to catastrophic (like system failure, which lead to economic or physical damage). Note that with the increase in number of errors, the amount of effort to find their causes also increases.
Once errors are identified in a software system, to debug the problem, a number of steps are followed, which are listed below.
- Defect confirmation/identification: A problem is identified in a system and a defect report is created. A software engineer maintains and analyzes this error report and finds solutions to the following questions.
- Does a .defect exist in the system?
- Can the defect be reproduced?
- What is the expected/desired behavior of the system?
- What is the actual behavior?
- Defect analysis: If the defect is genuine, the next step is to understand the root cause of the problem. Generally, engineers debug by starting a debugging tool (debugger) and they try to understand the root cause of the problem by following a step-by-step execution of the program.
- Defect resolution: Once the root cause of a problem is identified, the error can be resolved by making an appropriate change to the system by fixing the problem.
When the debugging process ends, the software is retested to ensure that no errors are left undetected. Moreover, it checks that no new errors are introduced in the software while making some changes to it during the debugging process.
As debugging is a difficult and time-consuming task, it is essential to develop a proper debugging strategy. This strategy helps in performing the process of debugging easily and efficiently. The commonly-used debugging strategies are debugging by brute force, induction strategy, deduction strategy, backtracking strategy, and debugging by testing.
Brute force method of debugging is the most commonly used but least efficient method. It is generally used when all other available methods fail. Here, debugging is done by taking memory (or storage) dumps. Actually, the program is loaded with the output statements that produce a large amount of information including the intermediate values. Analyzing this information may help to identify the errors cause. However, using a memory dump for finding errors requires analyzing huge amount of information or irrelevant data leading to waste of time and effort.
This strategy is a 'disciplined thought process' where errors can be debugged by moving outwards from the particulars to the whole. This strategy assumes that once the symptoms of the errors are identified, and the relationships between them are established, the errors can be easily detected by just looking at the symptoms and the relationships. To perform induction strategy, a number of steps are followed, which are listed below.
1. Locating relevant data: All the information about a program is collected to identify the functions, which are executed correctly and incorrectly.
2. Organizing data: The collected data is organized according to importance. The data can consist of possible symptoms of errors, their location in the program, the time at which the symptoms occur during the execution of the program and the effect of these symptoms on the program.
3. Devising hypothesis: The relationships among the symptoms are studied and a hypothesis is devised that provides the hints about the possible causes of errors.
4. Proving hypothesis: In the final step, the hypothesis needs to be proved. It is done by comparing the data in the hypothesis with the original data to ensure that the hypothesis explains the existence of hints completely. In case, the hypothesis is unable to explain the existence of hints, it is either incomplete or contains multiple errors in it.
In this strategy, first step is to identify all the possible causes and then using the data each cause is analyzed and eliminated if it is found invalid. Note that as in induction strategy, deduction strategy is also based on some assumptions. To use this strategy following steps are followed.
1. Identifying the possible causes or hypotheses: A list of all the possible causes of errors is formed. Using this list, the available data can be easily structured and analyzed.
2. Eliminating possible causes using the data: The list is examined to recognize the most probable cause of errors and the rest of the causes are deleted.
3. Refining the hypothesis: By analyzing the possible causes one by one and looking for contradiction leads to elimination of invalid causes. This results in a refined hypothesis containing few specific possible causes.
4. Proving the hypothesis: This step is similar to the fourth step in induction method.
This method is effectively used for locating errors in small programs. According to this strategy, when an error has occurred, one needs to start tracing the program backward one step at a time evaluating the values of all variables until the cause of error is found. This strategy is useful but in a large program with many thousands lines of code, the number of backward paths increases and becomes unmanageably large.
Debugging by Testing
This debugging method can be used in conjunction with debugging by induction and debugging by deduction methods. Additional test cases are designed that help in obtaining information to devise and prove a hypothesis in induction method and to eliminate the invalid causes and refine the hypothesis in deduction method. Note that the test cases used in debugging are different from the test cases used in testing process. Here, the test cases are specifically designed to explore the internal program state.