9618 AS Computer Science
Research has shown that the earlier an error can be found, the cheaper it is to fix it. Testing software before release is essential, but testing throughout development is even more critical. The purpose of testing is to discover errors — program testing can show the presence of bugs, but never to show their absence!
Most programs written will contain errors, as programmers are human and do make mistakes. A program fault is something that makes a program not do what it is supposed to do under certain circumstances.
Fault avoidance starts with provision of comprehensive and rigorous program specification at the end of analysis phase, followed by use of formal methods:
Testing will show presence of faults to be corrected, but cannot guarantee that programs are fault-free under all circumstances. Faults can appear during the lifetime of a program and may be exposed during live running.
Software may not perform as expected for a number of reasons:
| Source of Error | Description |
|---|---|
| Programmer mistake | Coding errors made during development |
| Requirement specification | Specification not drawn up correctly |
| Design error | Software designer made a design error |
| User interface | Poorly designed interface causes user mistakes |
| Hardware failure | Computer hardware experiences failure |
Syntax errors are errors in the grammar of a source program. A syntax error occurs when a program statement does not follow the rules of the programming language, for example, incorrect spelling of a keyword.
| Error Type | Example |
|---|---|
| Typos and spelling errors | PRINNT instead of PRINT |
| Missing or extra brackets | IF (x > 5 THEN (missing closing bracket) |
| Missing quotes | OUTPUT "Hello (missing closing quote) |
| Misplaced/missing semicolons | In languages that require them |
| Invalid variable names | Using reserved keywords as variable names |
| Incorrect use of operators | Using = instead of ← for assignment |
| Incorrectly nested loops | Mismatched IF/ENDIF, WHILE/ENDWHILE |
FUNCTION generate_username(first_name STRING, last_name STRING) RETURNS STRING
DECLARE username : STRING
username = SUBSTRING(first_name, 1, 1) + SUBSTRING(last_name, 1, 1)
RETURN username
ENDFUNCTION
PROCEDURE main()
OUTPUT "Enter your first name: "
INPUT first_name
username ← generate_username[first_name, last_name] // Wrong brackets!
ENDPROCEDURE
CALL Main // Wrong capitalization and missing ()
FUNCTION generate_username(first_name : STRING, last_name : STRING) RETURNS STRING
DECLARE username : STRING
username ← SUBSTRING(first_name, 1, 1) + SUBSTRING(last_name, 1, 1)
RETURN username
ENDFUNCTION
PROCEDURE main()
OUTPUT "Enter your first name: "
INPUT first_name
username ← generate_username(first_name, last_name) // Correct!
ENDPROCEDURE
CALL main() // Correct!
Syntax errors are usually detected by the compiler or interpreter before the program runs. If your program won't even start, check for syntax errors first!
Logic errors are errors in the logic of a program, meaning the program does not do what it is supposed to do. The program runs, but produces incorrect output or results. These errors are usually found when the program is being tested.
| Error Type | Example | Correct Version |
|---|---|---|
| Wrong operator | IF x > 0 OR y > 0 | IF x > 0 AND y > 0 |
| Wrong arithmetic | area ← width - length | area ← length * width |
| Loop one extra time | FOR i = 0 TO 10 | FOR i = 0 TO 9 |
| Array index off by one | Accessing index 5 in array[0..4] | Access index 0 to 4 only |
| Using uninitialized variables | Using count before setting to 0 | Initialize: count ← 0 |
| Infinite loops | WHILE x > 0 (x never changes) | Ensure x changes in loop |
FUNCTION calculate_area(length : REAL, width : REAL) RETURNS REAL
// Checks for valid dimensions and calculates area
IF length > 0 OR width > 0 THEN // Wrong: allows negatives!
DECLARE area : REAL
area ← width - length // Wrong: subtraction instead of multiplication!
RETURN area
ELSE
OUTPUT "Length and width must be positive values."
ENDIF
ENDFUNCTION
FUNCTION calculate_area(length : REAL, width : REAL) RETURNS REAL
// Checks for valid dimensions and calculates area
IF length > 0 AND width > 0 THEN // Correct: both must be positive
DECLARE area : REAL
area ← length * width // Correct: multiplication for area
RETURN area
ELSE
OUTPUT "Length and width must be positive values."
ENDIF
ENDFUNCTION
Run-time errors happen when a program executes an invalid instruction, encounters an out of bounds error, or attempts to divide by zero. The program may halt unexpectedly or go into an infinite loop.
| Error Type | Example | Prevention |
|---|---|---|
| Division by zero | result ← x / 0 | Check divisor ≠ 0 before division |
| Array index out of bounds | Accessing array[10] when array is size 5 | Validate index before access |
| File not found | Opening non-existent file | Check file exists before opening |
| Memory overflow | Infinite recursion | Set recursion limits |
| Type mismatch | Adding string to number | Validate data types |
| Null pointer reference | Accessing uninitialized object | Check for null before access |
FUNCTION divide_numbers(a : REAL, b : REAL) RETURNS REAL
DECLARE result : REAL
result ← a / b // Will crash if b = 0!
RETURN result
ENDFUNCTION
// Calling with b = 0 causes run-time error
answer ← divide_numbers(10, 0) // CRASH!
FUNCTION divide_numbers(a : REAL, b : REAL) RETURNS REAL
DECLARE result : REAL
IF b = 0 THEN
OUTPUT "Error: Cannot divide by zero!"
RETURN -1 // Return error code
ELSE
result ← a / b
RETURN result
ENDIF
ENDFUNCTION
// Safe calling
answer ← divide_numbers(10, 0) // Returns -1 with error message
The key difference: Syntax errors prevent the program from running, Logic errors allow program to run but produce wrong results, Run-time errors cause program to crash during execution.
Programs need to be tested before they are released. Tests begin from the moment they are written; they should be documented to show that the program is robust and ready for general use.
The purpose of testing is to discover errors. Program testing can be used to show the presence of bugs, but never to show their absence. Testing takes place during the testing stage of the program development life cycle.
A dry run (also called a walkthrough) involves manually tracing through the code on paper to predict output and track variables. This is done using a trace table.
Stub testing is employed during development of modular programs, conducted before all modules have been fully implemented.
White-box testing tests the internal logic and code structure. The tester knows how the program works and chooses suitable test data that checks every path through the code.
Black-box testing focuses on functionality of software without considering its internal code structure. Testers do not have access to internal workings.
Software consists of many modules written by different programmers. Integration testing tests that modules work correctly when joined together into one program.
Alpha testing is performed in-house by software testers before being released to customers. This is the first phase of user acceptance testing.
Beta testing is carried out by external users in real-world environments. When software is produced for general sale, there is no specific customer to perform acceptance testing.
Acceptance testing is the final check to ensure the program meets the original client requirements. For bespoke software, this is performed by the customer.
| Testing Method | Who Performs It | Purpose |
|---|---|---|
| Dry Run | Programmer | Trace through code manually with trace tables |
| White-box | Developer | Test internal logic, every path through code |
| Black-box | Tester | Test functionality without seeing code |
| Integration | Developer | Test modules work together correctly |
| Alpha | In-house testers | Early testing before customer release |
| Beta | External users | Real-world testing by selected users |
| Acceptance | Customer | Final check before sign-off |
| Stub | Developer | Test incomplete programs with dummy modules |
During the design stage of a software project, a suitable testing strategy must be worked out. We need a test plan to ensure testing of software from the very beginning.
| Type | Description | Example (Age 12-18) |
|---|---|---|
| Normal (Valid) | Typical data values that are valid | Age = 14, 16 |
| Abnormal (Erroneous) | Data values that system should not accept (wrong type) | Age = "H", "@", "twenty" |
| Extreme | Maximum and minimum values of normal data accepted | Age = 12, 18 |
| Boundary | Values on either side of max/min (largest/smallest unacceptable) | Age = 11, 19 |
Remember: Extreme data is AT the boundary (still valid), while Boundary data is JUST OUTSIDE the boundary (invalid). Both are needed to test the edge cases!
A program accepts a user's age between 0 and 120 inclusive. Here is a sample test plan:
| Test No. | Description | Input | Expected Output | Type |
|---|---|---|---|---|
| 1 | Valid age within range | 25 | "Age accepted" | Normal |
| 2 | Input is not a number | "twenty" | "Invalid input" | Abnormal |
| 3 | Age above maximum | 130 | "Age out of range" | Extreme |
| 4 | Age at upper boundary | 120 | "Age accepted" | Boundary |
| 5 | Age at lower boundary | 0 | "Age accepted" | Boundary |
| 6 | Age just below lower boundary | -1 | "Age out of range" | Boundary |
| 7 | Blank input | (blank) | "Please enter your age" | Abnormal |
A program accepts age between 12 and 18 inclusive:
| Type | Test Input | Expected Result |
|---|---|---|
| Normal | 14 | Accepted ✓ |
| Normal | 16 | Accepted ✓ |
| Extreme | 12 | Accepted ✓ (minimum valid) |
| Extreme | 18 | Accepted ✓ (maximum valid) |
| Abnormal | H | Rejected ✗ (wrong type) |
| Abnormal | @ | Rejected ✗ (wrong type) |
| Boundary | 11 | Rejected ✗ (just below minimum) |
| Boundary | 19 | Rejected ✗ (just above maximum) |
Don't confuse extreme data with boundary data! Extreme data is the highest/lowest VALID values (still accepted). Boundary data is just OUTSIDE the valid range (should be rejected). You need to test BOTH!
Program maintenance is the process of updating or improving a program after it has been delivered to the user. Unlike physical equipment, programs don't wear out, but they may need to be changed due to errors, changing requirements, or new technology.
| Type | Purpose | Example |
|---|---|---|
| Corrective | Fixes bugs or errors found during real-world use | Fixing a bug that causes crash when special characters entered |
| Perfective | Improves performance or adds small enhancements | Replacing loading screen with progress bar for better user feedback |
| Adaptive | Modifies program to support new environments or requirements | Modifying program to work on tablets instead of just desktops |
Corrective maintenance is used to correct any errors that appear during use. For example, trapping a run-time error that had been missed during testing.
Perfective maintenance is used to improve performance of a program during its use. This includes enhancing functionality and improving user experience.
Adaptive maintenance is used to alter a program so it can perform any new tasks required by the customer or work in new environments.
A patch is a small program released by developers to run with an existing program to correct an error or provide extra functionality. Patches are an essential part of ongoing maintenance.
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
Answer:
Additional points for deeper understanding:
| Term | Definition |
|---|---|
| Syntax Error | An error in the grammar/rules of a programming language that prevents compilation |
| Logic Error | An error where the program runs but produces incorrect results due to wrong logic |
| Run-time Error | An error that occurs during program execution, causing the program to crash |
| Bug | A fault or error in a program |
| Debugging | The process of finding and correcting errors in a program |
| Patch | A small program released to correct an error or add functionality to existing software |
| Dry Run | Manually tracing through code on paper to predict output and track variables |
| Trace Table | A table showing values of variables at each step of program execution |
| White-box Testing | Testing internal logic and code structure with knowledge of how the program works |
| Black-box Testing | Testing functionality without knowledge of internal code, focusing on inputs/outputs |
| Integration Testing | Testing that different modules work correctly when combined together |
| Alpha Testing | In-house testing by software testers before release to customers |
| Beta Testing | Testing by external users in real-world environments |
| Acceptance Testing | Final testing by customer to verify software meets requirements before sign-off |
| Stub Testing | Testing using dummy modules to simulate missing components |
| Normal Data | Typical valid data values that should be accepted by the system |
| Abnormal Data | Data values of wrong type that the system should not accept |
| Extreme Data | Maximum and minimum valid values at the boundaries of accepted range |
| Boundary Data | Values just outside the valid range that should be rejected |
| Corrective Maintenance | Maintenance to fix bugs and errors found during real-world use |
| Perfective Maintenance | Maintenance to improve performance or add enhancements |
| Adaptive Maintenance | Maintenance to adapt software for new environments or requirements |
| Topic | Key Point |
|---|---|
| Syntax Error | Grammar error, program won't compile, found by compiler |
| Logic Error | Wrong results, program runs, found by testing |
| Run-time Error | Program crashes, use exception handling |
| White-box | Tests internal logic, tester knows code |
| Black-box | Tests functionality, tester doesn't know code |
| Extreme Data | At boundary, VALID, should be accepted |
| Boundary Data | Just outside, INVALID, should be rejected |