Programming for Problem Solving
Subject Code: BE01000121
Unit 10-Debugging and Testing
1. Debugging
● Debugging Techniques: Common debugging practices
● Use of debugging tools
2. Testing:
● Testing: Writing test cases
● Unit testing
1. Debugging
1.1 What is Debugging?
● Debugging is the process of identifying, analyzing, and removing bugs
(errors) in a program.
● It is a crucial step in the software development life cycle and helps
ensure that a program behaves as expected.
1.2 Common Debugging Techniques
Here are some widely used techniques for debugging:
a) Print Debugging (Using printf)
Add printf() statements to display variable values at different points.
Example:
Code:
#include <stdio.h>
int main() {
int a = 10, b = 0;
printf("Before division: a = %d, b = %d\n", a, b);
int c = a / b; // Runtime error: Division by zero
printf("Result = %d\n", c);
return 0;
}
Output:
Before division: a = 10, b = 0
Floating point exception (core dumped)
● Use Case:
This helps you identify the value of variables right before the crash
happens.
b) Rubber Duck Debugging
● Explain your code line by line to someone (or even a rubber duck) —
helps catch logical errors.
c) Code Review
● Have peers review your code — they might spot errors you've
overlooked.
d) Backtracking
● Trace your steps backward from the point of failure to find where it
started.
e) Binary Search Debugging
● Divide the code in half and test each part to isolate the bug.
1.3 Use of Debugging Tools
a) GDB (GNU Debugger)
Basic Commands:
● gdb ./a.out – start debugger
● break main – set breakpoint
● run – start execution
● next – go to next line
● print variable – print variable value
● quit – exit debugger
Example:
Code:
#include <stdio.h>
int main() {
int x = 5;
int y = 0;
int z = x / y;
printf("z = %d\n", z);
return 0;
}
Steps to Debug with GDB:
1. Compile with -g:
gcc -g debug_example.c
2. Run GDB:
gdb ./a.out
3. Set breakpoint:
break main
4. Run:
run
5. Observe error and analyze.
2. Testing
2.1 What is Testing?
● Testing is the process of executing a program with the intent of finding
bugs and verifying correctness.
2.2 Writing Test Cases
● A test case includes:
○ Input data
○ Expected output
○ Actual output
○ Pass/Fail status
Example Test Case Table:
Test Case Input Expected Output Actual Output Result
TC1 2, 3 5 5 Pass
TC2 -1, 4 3 3 Pass
TC3 100, -100 0 0 Pass
Sample Function with Test Cases:
Code:
#include <stdio.h>
int add(int a, int b) {
return a + b;
}
int main() {
printf("Test Case 1: %d\n", add(2, 3)); // Output: 5
printf("Test Case 2: %d\n", add(-1, 4)); // Output: 3
printf("Test Case 3: %d\n", add(100, -100)); // Output: 0
return 0;
}
2.3 Unit Testing
Definition:
Testing individual functions or modules in isolation.
Benefits:
● Early detection of bugs
● Easier maintenance
● Documentation of expected behavior
Manual Unit Testing Example in C:
Code:
#include <stdio.h>
#include <assert.h>
int factorial(int n) {
if(n < 0) return -1;
if(n == 0) return 1;
return n * factorial(n - 1);
}
int main() {
assert(factorial(0) == 1);
assert(factorial(5) == 120);
assert(factorial(-3) == -1);
printf("All test cases passed!\n");
return 0;
}
Output:
All test cases passed!
Note:
● If any test fails, the program will abort with an error message.
Use Cases and Real-life Scenarios
Use Case 1: Debugging a Segmentation Fault
● When accessing memory incorrectly (e.g., dereferencing null pointers).
int *ptr = NULL;
*ptr = 10; // Segmentation fault
● Debug with GDB or analyze with print statements.
Use Case 2: Unit Testing for a Math Library
● Create reusable test cases for each function (add, subtract, multiply,
etc.) using assert().
Use Case 3: Validating User Input
Code:
int readPositiveInt() {
int x;
do {
printf("Enter positive integer: ");
scanf("%d", &x);
} while (x <= 0);
return x;
}
● Write test cases to ensure the function rejects zero and negative values.
Best Practices for Debugging and Testing
● Write code in small, testable functions.
● Use meaningful variable names to reduce confusion.
● Comment your code to explain logic.
● Don’t ignore compiler warnings.
● Start testing early and test often.
● Automate tests wherever possible.
********