9.3 - Testing
Types of programming errors
During the development of a program, errors often appear that can prevent it from working as intended. These errors must be identified and corrected quickly to ensure the program functions correctly. There are two main types of errors: syntax errors and logic errors.
Syntax errors
Syntax errors occur when the code violates the rules or grammar of the programming language, making it impossible for the compiler or interpreter to understand and translate the source code into executable form.
Characteristics of syntax errors:
- Compilers and interpreters detect syntax errors during the translation process.
- They typically return an error message indicating the location of the problem, allowing the programmer to fix it before the program can run.
Logic errors
Logic errors happen when the code runs without syntax issues, but the program produces unexpected or incorrect results. These errors arise from flaws in the program's reasoning or algorithm, even though the compiler or interpreter can execute the code.
Characteristics of logic errors:
- Unlike syntax errors, logic errors are not flagged by compilers or interpreters.
- They are discovered through running the program, observing its behaviour, and using systematic testing methods like test plans.
- Fixing logic errors involves refining the code to correct the faulty logic.
Once errors are identified, programmers refine the code to resolve them.
Examples of programming errors
To illustrate how errors can appear in code, consider practical examples where syntax or logic issues cause problems.
Example of logic errors in a multiplication function
Jerry has created a function intended to multiply all positive integers up to a given number n (for example, if n is 4, it should calculate 1 × 2 × 3 × 4). However, the function contains logic errors that prevent it from working correctly.
Logic errors identified:
- Logic error 1 - The variable
countis declared and set to 1 inside the loop, causing it to reset on each iteration. To fix this, move the declaration ofcount = 1before the loop starts. - Logic error 2 - The line
count = count * nmultiplies byneach time instead of the loop variablei. Change it tocount = count * ito multiply by the correct value.
Example of a syntax error in a file name validation function
Shreena is developing a function to validate file names in a database.
The function checks if the file name has any exclamation marks and returns "Rejected" if it does or "Accepted" if it does not. The while loop lacks an endwhile statement to close it properly. Add endwhile before the return statement, indented to match the while loop's start.
This is an example of input validation.
Stages of testing in development
Testing is a crucial part of program development to ensure reliability and correctness. It occurs at different points to catch errors early and verify the final product. There are two primary types of testing: iterative testing and final testing.
Iterative testing
Iterative testing involves checking the program during its development, often module by module. Programmers test a section of code, identify errors, fix them, and test again, repeating until the module works as expected. This approach helps spot and resolve small errors early, preventing them from growing into larger issues later.
Final testing
Final testing, also known as terminal testing, takes place at the end of development. The entire program is tested as a whole to confirm it operates correctly. Even if modules work independently, interactions between them can introduce new errors.
Using both iterative and final testing together minimises bugs in the released program, combining early fixes with comprehensive checks.
Creating and using test plans
Before implementing a program, create a test plan to systematically verify its behaviour. A test plan outlines what to test, how to test it, and covers all possible paths through the program. It anticipates potential issues and selects test data to expose them. During testing, record actual outcomes and whether each test passes or fails to track progress.
Types of test data
Test data should cover a range of scenarios to thoroughly check the program.
Four main categories of test data:
- Normal data - Typical inputs a user might provide, to ensure the program handles everyday use correctly.
- Boundary data (also called extreme data) - Values at the edges of acceptable ranges, to test limits like minimum or maximum values.
- Invalid data - Inputs with the correct data type but invalid content (e.g., a negative age where only positive is allowed), which the program should reject.
- Erroneous data - Inputs with an incorrect data type (e.g., letters instead of numbers), which the program should reject.
Example test plan for an alarm code system
Consider a program for setting a 3-5 digit alarm code. The test plan below includes types of data, specific examples, reasons for testing, and expected outcomes. In practice, add columns for actual outcomes and pass/fail during testing.
| Type of data | Test data | Reason for testing | Expected outcome |
|---|---|---|---|
| Normal | 2476 | To check handling of typical user input. | Code accepted. |
| Normal | No input | To verify prompting for missing input. | Prompt to enter a code. |
| Boundary | 000 | To test the smallest acceptable code (3 digits). | Code accepted. |
| Boundary | 99999 | To test the largest acceptable code (5 digits). | Code accepted. |
| Invalid | 12 | To check rejection of codes shorter than 3 digits. | Error: The code is too short. |
| Invalid | 632191 | To check rejection of codes longer than 5 digits. | Error: The code is too long. |
| Erroneous | 23aY | To test rejection of non-numeric characters. | Error: The code contains non-numeric data. |