separates what a procedure does from how it is implemented
-
In cpp, we use functions to implement PA
-
Can change implementation without affecting users as long as interface remains unchanged
.h header defines what, not how, functions do
.cpp defines how functions work • functions can be used in another file
Code that calls the function depends on the interface, not implementation
As long as abstraction of a function does not change, usage of the function still works
The implementation of an abstraction can be understood without examining any other abstraction implementation
You can replace one (correct) implementation of an abstraction with another (correct) one, and no callers of that abstraction will need to be modified
Signature describes inputs and outputs of function
Comments describe what function does
//REQUIRES: v is not empty
//EFFECTS: returns the sum of the numbers in v
double sum( std::vector<double> v );
-
functions with REQUIRES clauses are called partial
-
functions without REQUIRES clause are called complete
//MODIFIES: v
//EFFECTS: sorts v
void sort( std:: vector<double> &v );
- A function that modifies inputs or global data has side effect
-
Usage:
assert( expression )
; -
Does nothing if the expression is true
-
Exits and prints error message if expression is false
#include <cassert>
int main( )
{
assert ( true ); // does nothing
assert ( false ); // crash with debug message
}
#define NDEBUG
- Ensure that code works as expected
- Meet the reqs of the spec
Test one piece, e.g., one function, at a time. Find and fix bugs early with smaller, less complex, easier to understand tests
Write small helper functions for tests
//stats_test.cpp
void test_mean( )
{
vector<double> data = { 1, 2, 3 };
double result = mean( data );
assert( result == 2 );
}
Thorough testing with "small" test cases is sufficient to find a large proportion of bugs within a system
Can fail if...
- Code coverage is incomplete
- Cannot detect bugs that occur as the result of interactions adn race conditions that it doesn't (or cannot) test
Test the entire system after all the individually-tested pieces have been integrated
Automatically run all unit and system tests after a code change
make test
for running regression tests
- Code tests
- Code implementation with the goal of passing the tests
- Debug and add more tests