Download presentation
Presentation is loading. Please wait.
1
2.3 Testing Programs 12 – Program Correctness
2
Attendance Quiz #11 Software Design
3
Tip #12: Default Arguments
Software Design A default function parameter is used if the user does not supply a value. What is the advantage/disadvantage of using the default function parameter, in term of execution speed, memory usage and etc? int add(int x, int y = 1) { return x + y; } int main() { int result1 = add(5); int result2 = add(5, 3); return 0; } int add(int x, int y) int result1 = add(5); // Error template<class T> struct vector_imitation { void resize(int new_size, T new_values=T()); }; vector_imitation<int> v; // [] (v is empty) v.resize(3); // [0, 0, 0] (since int() == 0) v.resize(5, 42); // [0, 0, 0, 42, 42] Advantages and Disadvantages. In 99% of cases you don't need half of the function parameters. With normal functions, default parameters can make code harder to read. When refactoring, default parameters can be used to add functionality without breaking code. Introduces problems reviewing or using code written by others - hidden parameters. Some functions tend to have the same parameter value in most calls. Default parameters supply those common values and also helps you see the "suggested" value. **NOTE: google's coding style suggests avoiding them.
4
To Error is Human What to do with an error:
Program Correctness What to do with an error: Return a special value. Use a bool return value to indicate success or failure. Set a global variable. Print an error message. Print an error message and exit the program. Put an input or output stream in a fail state. The first three options allow the user of a function to respond to the error. To err is human… But to really screw up, you need a computer!
5
Exceptions Program Correctness An alternate way to indicate an error, especially if there are several possible errors, is through the use of exceptions. Exceptions are used to signal that an error has occurred during the execution of a program. You can insert code in your program that throws an exception when a particular kind of error occurs. When an exception is thrown, the normal flow of execution is interrupted and control transfers to another part of the program. An exception handler allows the user to catch or handle the exception.
6
Exception Handling The exception object can be of any type.
Program Correctness The exception object can be of any type. The standard library includes standard exception classes. User defined exceptions can be of any data type. If an exception occurs and is not caught, the program stops and an error message is displayed. To avoid uncaught exceptions you write a try block that can throw an exception and follow it with a catch block that catches the exception and handles it. Code within a try/catch block is referred to as protected code. More than one catch block can follow a try block. Each catch block handles a different kind of exception. They are checked in the order in which they appear.
7
try-catch Blocks Program Correctness try { } If all statements in the try block execute without error, the exception handler (the catch blocks) are skipped age = read_int("Enter your age: "); catch (std::ios_base::failure& f) { cerr << "Invalid number format input" << endl; age = DEFAULT_AGE; } catch (std::exception& ex) { cerr << "Fatal error: " << ex.what() << endl; abort(); } catch (...) { cerr << "Undefined exception in read_int" << endl; abort(); }
8
When To Use try-catch Blocks
Program Correctness When an error event happens routinely and could be considered part of normal execution, handle without throwing exceptions. Use try-catch blocks Around code that can potentially (and unexpectedly) generate an exception. Prevent and recover from application crashes. Throw an exception when your program can identify an external problem that prevents execution. Compared to error reporting via return-codes and if statements, using try / catch / throw is likely to result in code that has fewer bugs, is less expensive to develop, and has faster time-to-market. Constructors and Destructors Constructors don't have a return type, so it's not possible to use return codes, therefore to throw an exception. Destructors should never throw an exception because of stack unwinding.
9
Standard Exceptions Exception Source bad_alloc bad_cast bad_typeid
Program Correctness Exception Source bad_alloc Thrown by new. bad_cast Thrown by dynamic_cast. bad_typeid Thrown by typeid. domain_error Thrown when a mathematically invalid domain is used. length_error Thrown when a too big std::string is created. invalid_argument Thrown due to invalid arguments. out_of_range Thrown by the 'at' method. io_base::failure Thrown by I/O stream objects after erroneous I/O operations. runtime_error Exception that theoretically cannot be detected by reading the code. range_error when you try to store a value which is out of range. overflow_error Thrown if a mathematical overflow occurs. underflow_error Thrown if a mathematical underflow occurs. … Catch all throws
10
Vector Example animals.at() throws an exception. animals[ ] does not!
Program Correctness #include <iostream> #include <vector> #include <string> #include <stdexcept> using namespace std; int main(int aargc, char* argv[]) { vector<string> animals = { "dog", "cat", "horse" }; try for (int i = 0; i < 4; i++) //cout << animals[i] << endl; cout << animals.at(i) << endl; } catch (std::out_of_range& oor) { cerr << oor.what() << endl; } // catch anything thrown within try block that derives from std::exception catch (const std::exception &exc) { cerr << exc.what() << endl; } // catch everything, but can't do anything w/exception. catch (...) { cerr << "???" << endl; } return 0; animals.at() throws an exception. animals[ ] does not!
11
Define Your Own Program Correctness You can define your own exceptions by inheriting and overriding exception class functionality. #include <iostream> #include <exception> using namespace std; struct MyException : public exception { virtual const char* what() const throw() return "C++ Exception"; } }; int main() try throw MyException(); catch(MyException& e) cout << "MyException caught " << e.what() << endl; catch(exception& e) { cout << e.what() << endl; } //Other errors what() is a public method provided by exception class and it has been overridden by all the child exception classes. This returns the cause of an exception.
12
2.3, pgs. 148-159 2.3 Testing Programs Structured Walkthroughs
Levels and Types of Testing Preparations for Testing Testing Tips for Program Systems Developing the Test Data Testing Boundary Conditions Who Does the Testing? Stubs Drivers Testing a Class Using a Test Framework Regression Testing Integration Testing 2.3, pgs
13
Testing Programs Software Design Even after all syntax and run-time errors are removed and a program executes through to normal completion, there is a possibly that undetected logic errors exist. The "best" kind of logic error is one that occurs in an area of the program that always runs. The "worst" kind is in an obscure part of the code that is executed infrequently. Testing Techniques: Structured walkthroughs. Testing at various levels. Blackbox / whitebox testing. Test boundary conditions.
14
Structured Walkthroughs
Software Design Most logic errors surface during the design phase and are the result of incorrect algorithms .Some may result from typographical errors that do not cause syntax or run-time errors Checking the algorithm carefully before implementing it helps avoid logic errors. After implementation, we can hand-trace the algorithm, carefully simulate the execution of each step, and then compare its result to the execution result. A structured walkthrough is when a designer explains the algorithm or program to other team members and simulates its execution with other team members looking on.
15
Levels of Testing Software Design Unit Testing – the smallest testable piece of software; in object oriented design, this will be either a function or a class. Integration testing — testing the interactions among units; this may involve testing interactions among functions in a class but generally involves testing interactions among several classes. System testing — testing the whole program in the context in which it will be used; a program is generally part of a collection of other programs and hardware called a system; sometimes a program will work correctly until some other software is loaded onto the system. Acceptance testing — system testing designed to show that the program meets its functional requirements; this generally involves the use of the system in the real environment or as close to the real environment as possible.
16
Internal Testing Software Design Black-box testing: closed-box testing or functional testing Tests the item (function, class, or program) based on its interfaces and functional requirements. Input parameters are varied over their allowed range and the results are compared against independently calculated results. Input parameters outside the allowed range are tested to ensure that the function responds as specified. Value of data fields and any global variables can also be used in testing. White-box testing: glass-box testing, open-box testing, and coverage testing Tests the software element (function, class, or program) using knowledge of its internal structure. The goal is to exercise as many of the possible paths through the element as is practical.
17
Who Does the Testing? Testing is done by:
Software Design Testing is done by: the programmer. other members of the software team who did not code the module being tested. the final users of the software product. It is extremely important not to rely only on the programmer who coded a module to test it because programmers often are blind to their own oversights. Involving future users helps determine whether they have difficulty interpreting prompts for data (since they are typically less knowledgeable about programming).
18
Tips for Testing Classes
Software Design If the function implements an interface, the interface specification should document the input parameters and the expected results. Document each function parameter and class attribute carefully, using comments as you write the code. Leave a trace of execution by displaying the function name as you enter it. Display the values of all input parameters upon entry to a function. Also display the values of any class attributes that are accessed by this function; check that these values make sense. Display the values of all function outputs after returning from a function. By hand computation, verify that these values are correct.
19
2.4 Debugging a Program Using a Debugger 2.4, pgs
20
Symbolic Debugging Software Design Single-step execution involves executing a statement in increments as small as one program statement; examining the contents of variables at each step. Setting breakpoints allows us to divide programs into sections. The debugger executes until it encounters a breakpoint. When our program pauses, if the next statement is a call to a function, we can select single-step execution in the function, called step into. Or we can execute all the function statements as a group and pause after the return from the function, called step over. Although the process is similar among IDEs, the actual mechanics of using a debugger depend on the specific IDE that we are using.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.