**Asserts** are useful for telling you about **the internal state of the program**. For example, that your data structures have a valid state, e.g., that a `Time` data structure won't hold the value of `25:61:61`. The conditions checked by asserts are preconditions (that the caller keeps its contract), postconditions (that the callee keeps its contract), and invariants (that a data structure always holds some property after the function returns-- an invariant is a condition that is a precondition and a postcondition). **Unit tests** are useful for telling you about **the external behavior of the module**. Your `Stack` may have a consistent state after the `push()` method is called, but if the size of the stack doesn't increase by one, then that is an error. (For example, the trivial case where the incorrect `push()` implementation only checks the asserts and exits.) There can be some overlap in what is being tested. For example, a `Stack`'s postcondition may actually assert that the stack size increases by one. But there are limits to what can be performed in that assert: Should it also check that the top element is what was just added? For both, the goal is to increase quality. For unit testing, the goal is to find bugs. For assertions, the goal is to make debugging easier by observing invalid program states as soon as they occur. Note that *neither* technique verifies correctness. In fact, if you conduct unit testing with the goal to verify the program is correct, you will likely come up with uninteresting test that you know will work. It's a psychological effect: you'll do whatever it is to meet your goal. If your goal is to find bugs, your activities will reflect that. Both are important, and have their own purposes. [As a final note about assertions: To get the most value, you need to use them at all critical points in your program, and not a few key functions. Otherwise, the original source of the problem might have been masked and hard to detect without hours of debugging.]