Unit Testing

It’s all fun and games until you realize your database is wrong bc there are no tests—Kirsten Garrison

Did You Know?

Unit testing may save your life, and it can even be fun. Accountants “test” with double-entry accounting. Accountants that don’t do double-entry don’t last long in the profession. In fact, such accountants may not even exist. The programming profession is not like this, but it should be.

Kinds of Testing

First things first! Unit testing is not the only kind of testing. In fact the whole idea of testing has several dimensions.

How much of a system are you testing?

What are you testing?

Do you care about implementation or just the functional results?

Also see Wikipedia’s software testing category page, and this StackOverflow question and its answers.

The Importance of Unit Testing

Unit testing is crucial. It is done by developers, not QA. In many organizations, unit tests are required: programmers are not allowed to check-in code or build a system unless their unit tests pass. Please read:

How NOT to Unit Test

Sometimes one wonders if the world is divided into (1) practitioners that know how to unit test and (2) textbook writers that don’t know squat about it.

Some textbook writers (I won’t name them here) show you pathetic “test drivers” that go through a the code and print out results for humans to check.

This Ain’t It, Chief

Like someone’s gonna sit there are run the program a gazillion times during debugging and read the output off the screen?!?

The Right Way To Unit Test

Unit tests should be non-interactive. They are made up of a huge number of statements that exercise some code and compare the computed result with the expected result. (See: the computer checks the result, not a slow human that doesn't have the patience to type in all of tests each time a change is made to the code.) A test driver can report the number of successes and number of failures when it’s finished. The many, many, many reasons for unit testing and the benefits it provides can be found all over the web, but one advantage stands out in particular:

A COMPREHENSIVE UNIT TEST SUITE ALLOWS YOU TO REFACTOR WITH CONFIDENCE

Go ahead and make that change to improve your code! Your tests will protect you!

Unit Tests F.I.R.S.T.

Unit tests differ from other kinds of tests in that they must be F.I.R.S.T.

When you do unit testing properly, you get some great advantages:

Read those advantages again.

It is hard to overstate how important each of those items really and truly is.

For more, read Uncle Bob’s Clean Code or watch the testing episodes (especially Episode 6) of Clean Coders.

What Do Tests Look Like?

Tests contain assertions about the behavior of your software.

For example, suppose we were asked to write a function to determine whether a value was a prime number. We want it to return true or false if the value is an integer in the range 2..1000000000000 inclusive, and throw an error message for all other inputs. Our test suite would make the following assertions:

For another example, let’s say we want to build a type for money bags. A money bag holds a certain amount of money in a variety of different currencies. Let’s specify the money bag behavior in language that is very, very close to code:

This is not a complete list of behaviors. These are just examples of what your tests may look like.

Exercise: Write some more things to test.

Unit Testing Frameworks

It is possible to write a little application of your own which executes each of the tests and counts the number of successes and failures. But since the work of setting up and tearing down tests, counting successes and failures, and reporting and so on is the same for every test, it makes a lot of sense to use an existing test framework. What are some popular frameworks?

LanguageSome Testing Frameworks
JavaJUnit, TestNG
JavaScriptQUnit, NodeUnit, Mocha, should.js, espresso, Jasmine
Pythonunittest2, nose, py.test
Rubyminitest, test-unit, riot, RSpec

How many are there? You might just be surprised.

At this point, you should go get some practice with one of the following:

Unit Testing in Practice

Exercise: What’s a boundary condition anyway? Do some research. Write a three-page paper about them. Give a bunch of examples.

TDD

Start by reading Uncle Bob’s The Three Rules of TDD.

Powerful stuff! This requires discipline, but it pays off. See what he is saying:

  1. You are not allowed to write any production code unless it is to make a failing unit test pass.

    So start by writing tests. Whenever you want to write production code, write a test for it first. (This helps you understand what you are going to write.)

  2. You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.

    So don’t get ahead of yourself with the tests. You aren’t allowed to write super big tests. Just one little bit of test behavior at a time. When you write a failing test and you see it fail, switch to writing production code to make it pass.

  3. You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

    Again, don’t get ahead of the tests, ever.

In practice, you can do TDD with Red-Green-Refactor. Watch the little clip here, but consider paying the 10 bucks to see the whole episode:

More from Uncle Bob:

David Ehringer’s presentation is pretty good:

This is an interesting discussion of TDD:

Exercise: Find some articles “against” TDD.