Lecture 8-1

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

Idiom Is Your Friend

  • 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

  • Follow the coding standard

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

Comments

  • 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 notice

    Copyright (c) 2015 Bart Massey
    
  • Any license information

  • 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

Follow The Above Rules

  • Implementation should be 10-20% of dev effort

  • This is how you keep it that way

  • In general, code doesn't have bugs

Last modified: Monday, 16 November 2015, 1:24 AM