# Unit Tests and Program Implementation

CS 300 Lecture 8-1
Bart Massey

# Unit Tests

• Come from pseudocode / detailed design

• Written before implementation ("test-driven development")

• and after
• Not every unit will be tested

• Every unit should at least be desk-checked
• Interesting units should be inspected by someone else or tested
• Really interesting units should get both inspection and testing

# Unit Tests, Drivers and Stubs

• Need some way to call the unit: "driver"

• Typically use a "unit test framework"
• Need some way for the unit to call what it calls

• Develop bottom-up
• Make something workable for testing: "stub"

# Unit Testing and State

• For inferior (not functional) languages, need to manage state accessed by routine

• This may involve

• State creation tools
• Capturing and replaying state
• This is hard, so the less state a unit depends on, the better

• Hence, few global variables

# From pseudocode to code

• Don't be afraid to rework pseudocode as you go

• Correct errors
• Match implementation language
• Tracing should be easy

• You will add things not in the pseudocode

• Type declarations
• Assertions
• Memory management
• Instrumentation
• Error handling code

# Your Code Should Fail Early

• Ideally, defective code will not compile

• Turn on all warnings and treat them as errors
• At least, it would be nice if errors happened during runtime startup

• A defect hit during normal program operation is pretty late

• Short-running units / programs are way easier to deal with than long-running ones

# You Are Not Using Enough Assertions

• Instance of the fail-early principle

# Memory Management Is Hard

• At least, it is hard in inferior (non-GC) languages

• Any non-trivial memory management should be inspected by someone else

• Learn to use memory analysis tools, e.g. valgrind

# The Pairing Principle

• Every alloc should have a free

• Every open should have a close

• Every time you do something, think of and note "obligations" produced by it

• Ideally, "discharge" those right away

# Unit Control Flow Made Easy

• Idea: Successive strengthening of invariants

• Start by picking off special cases
• Assertions: fail for unhandled cases
• Recursion: get base case
• Special cases: early return
• Each line of the unit you should know more about what you're working with
• At the end of the routine you should just be able to dispatch stuff
• break and continue are your friends
• Idea: Case analysis

• Conditionals and case statements are the same thing
• Idea: Hoare clauses and loops

# Indentation Is The Enemy

• Nesting depth only thing that has been shown to correlate strongly with poor code quality

• Early return vs else

• Splitting out subunits

• Write things the way other people write them in your language

• Maybe there's a reason
• Regardless, it means others can work with your code
• Don't fight the language

# Coupling and Cohesion Again

• Every unit tells a story

• If a unit tells two unrelated stories, break it up

• If a unit needs a lot of information to tell its story, put it with the information

• This is the idea behind OOP

# Assertions, Dammit

• Any time you can reasonably check that things are as you expect with an assertion, add it

• Crashes are better than wrong answers
• You won't hit the assertions anyhow..right?
• Your language has good assertion facilities: use them

# Instrumentation

• If code might be wrong, but you can't stop

• If things are complicated and you want to be able to understand and maintain your code

• Build instrumentation infrastructure

# Error Handling

• Your language probably has an exception mechanism

• All error returns must be handled

• Many can be handled with assertions, but not all
• This is a real design thing

• Clarifying comments at the top of interesting units

• Block comments inside unit blocks

• Comments should not restate the program

• Comment anything that might be mysterious

• Or better yet fix the mystery
• Use the comment-doc facilities of your language

# At The Top Of Every File

Copyright (c) 2015 Bart Massey


• Description of the file

# ifdef Is Not A Source Code Management System

• Your code is checked into Git

• When you delete something, just delete it

• Don't comment it out
• Don't ifdef it out
• Dead or irrelevant code makes things incredibly more confusing