CSCE 315 Lecture 19
Jump to navigation
Jump to search
« previous | Monday, March 5, 2012 | next »
Testing
Helps find errors that exist.
A systematic attempt to break a working program, unlike other parts of software development, whose goal is to avoid errors.
FYI, we can never prove the absence of errors.
- Unit Testing
- Testing af a single class, routine, or program; usually done by a single programmer
- Isolated from the rest of the system
- Component Testing
- Test small packages
- Integration Testing
- Test the whole application
- Regression Testing
- Re-test to make sure that new errors have not been implemented.
- System testing
- Testing the entire software in final configuration with the hardware
- finds security, performance, resource, and timing problems
Testing First
- Identify errors more quickly
- Doesn't take more effort later
- think about requirements and design before writing code
Testing during development
- Boundary Testing
- Make sure that code handles boundary conditions (sorting an empty array or an array with 1 element).
- Check loop and conditional bounds
- Preconditions and Postconditions
- Verify that the procedure starts with the correct preconditions and produces correct postconditions.
- Assertions
- assert.h (C/C++); Assert, AssertionError (Java)
- checking for pre-/postconditions
- Helps identify where problem occurs
- usually placed in calling routine
- Defensive Programming
- Protecting the program from bad data
- Check for "not going to happen" cases
- Error Returns
- Good API and routine design include error codes that need to be checked
- Exception handling (try-catch)
Systematic Testing
- Incremental Testing
- Test along the way; don't wait until everything is finished.
- Simple parts first
- Find the "easy" bugs
- Know expected output
- Design a test case that you will know the answer to.
- Make hand-checks convenient
- Not always easy to do
- Verify conservation properties
- StartCount + NumInserted − NumDeleted = FinalCount
- Compare independent implementations
- Multiple implementations to compute the same data should agree
- Useful for testing tricky code to increase performance (compare to slow, brute-force method)
- Measure Test Coverage
- What portion of code is actually tested? Aim for 100%
- Logic Coverage: test every execution path through the code.
- Structured Basis: test every line (no need for every combination of paths)
- Data flow Testing
- Examine data rather than control
- 3 states: Defined (init, but not used), Entered (data input), Killed (information is deleted)
- Compilers test Defined-Defined, Defined-Killed, etc. conditions
- Write tests for Defined-Used cases.