[Tutor] Fitting data to error function

Danny Yoo dyoo at hashcollision.org
Mon Mar 16 23:40:19 CET 2015


On Mon, Mar 16, 2015 at 3:22 PM, Colin Ross <colin.ross.dal at gmail.com> wrote:
> Yes, thank you, they were suppose to both be E_out.
>
> And to answer your last question, I do not. Can you please explain?

The article:

    http://en.wikipedia.org/wiki/Unit_testing

may help.


As a brief intro: we treat each interesting function as a
independently-testable "unit", and write code that exercises each
function against a series of input->expected output pairs.

E.g. toy example: if we were writing a function to compute hypotenuse:

##############################
def h(x, y):
    return sqrt(sq(x) + sq(y))

def sqrt(x):
    return x**0.5

def sq(x):
    return x ** 2
##############################

then we can "unit test" the individual functions.



Here is a complete toy example of the idea:

###############################
import unittest

def hypo(x, y):
    return sqrt(sq(x) + sq(y))

def sqrt(x):
    return x**0.5

def sq(x):
    return x ** 2

class HypoTestCases(unittest.TestCase):
   def testSqrt(self):
        self.assertEqual(2, sqrt(4))
        self.assertEqual(0, sqrt(0))

   def testSq(self):
        self.assertEqual(1, sq(1))
        self.assertEqual(4, sq(2))
        self.assertEqual(9, sq(3))

   def testHypo(self):
        self.assertEqual(5, hypo(3, 4))

if __name__ == '__main__':
    unittest.main()
################################



When we run this program, the unit tests will execute and tell us if
they see any deviation between expectations and reality.

################################################
$ python hypo.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
################################################



Now let us intentionally damage one of the functions.  Change the
definition of sq(x): to:

#############
def sq(x):
    return x * 2
#############

and execute the unit tests again.  We'll now see something very interesting:


##############################################################################
$ python hypo.py
FF.
======================================================================
FAIL: testHypo (__main__.HypoTestCases)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "hypo.py", line 23, in testHypo
    self.assertEqual(5, hypo(3, 4))
AssertionError: 5 != 3.7416573867739413

======================================================================
FAIL: testSq (__main__.HypoTestCases)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "hypo.py", line 18, in testSq
    self.assertEqual(1, sq(1))
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 3 tests in 0.000s

FAILED (failures=2)
##############################################################################


Our "unit test code" will automatically report if the actual output of
a function mismatches against the expected output.  Flaws in auxiliary
functions can be reported, which means that if we do see problems, we
can more easily scope what the issue is.  Note: from the unit test
error output, we know that sqrt() is probably ok, but hypo() and sq()
are probably broken.  And since hypo()'s definition depends on sq(),
it naturally leads us to investigate sq() first.


It is the use of tests on individual units of our code that lets us
determine a fault without having to look at the entire aggregate
program.  Contrast this with the situation you're in at the moment:
you're currently stuck trying to debug the *entire program* when
something goes wrong.  Unfortunately, this strategy doesn't scale when
programs get too large.  An effective mechanism that programmers use
is to unit test the individual functions.


More information about the Tutor mailing list