[Tutor] unittests

Danny Yoo dyoo at hashcollision.org
Tue Apr 1 19:54:45 CEST 2014

> Yes, that unit test was written by Danny (I assume -- I suppose he might
> have copied it from somewhere else.)

Oh, who knows where I got that code from.  :P

---

Sydney, you can also take a look at some of the official documentation
of the unittest library:

https://docs.python.org/2/library/unittest.html#basic-example

You don't have to read all of it, but touching on it and knowing where
the documentation and reference is can be helpful.  The
"assertAlmostEqual" is part of the library,

https://docs.python.org/2/library/unittest.html#unittest.TestCase.assertAlmostEqual

In Scott's case, he was computing with floating point, so writing the
tests to use inexact almost-equality comparison seemed reasonable to
me.

You might find this also useful:

http://www.diveintopython.net/unit_testing/

> Although they might be a bug in the test! In this case, Danny intends
> that as a deliberately buggy test -- 1.732... is *not* "approximately
> equal" to 2, at least not according to the rules of unittest.

As a side note, when I'm writing tests, I usually write them
deliberately wrong the first time and run them to make sure that the
framework is properly reporting errors.  Only after I see failing
tests do I put in the right values for the test.  It helps me gain
more confidence that the universe is all right.

>> I am quite unclear how one proceeds to set up unittests.

Functions that take inputs and return values are usually easy to test.
For simple programs, express a piece of functionality and some
property you expect that functionality to have.  In pure computations
like math functions, you can state the inputs and expected outputs as
a test.

By the way, if we can't even do that, to express the expected output
of our functions, then that might be a sign that we don't understand
what we're trying to code!  So there's a good reason to consider test
cases early: it forces us to put a stake in the ground and say: "This
is what the function is supposed to do, and if it doesn't do this, the
code is wrong."

If I know that a properly functioning f() is supposed to behave like this:

f(9) ==> 3
f(10) ==> 42
f(1) ==> 32

then I want to write those concrete cases as tests.  An easy way to do
so is to use the unittest library to write those tests.  We can write
the cases above as the following test:

###############################
class MyTests(unittest.TestCase):
def testCrazyFunction(self):
self.assertEqual(f(9), 3)
self.assertEqual(f(10), 42)
self.assertEqual(f(1), 32)
###############################

What this means is that I have some expectations on what the function
is supposed to do, apart from how it is actually coded.  That's
important, to express those expectations, because usually you trust
your expectations more than you trust the implementing code.  So if
the test breaks, usually it's the code that's broken, so it gives a
quick canary-in-the-coalmine.

If you want to explore this more, check for Kent Beck's: "Test-driven
Development: By Example".