prev | Version 1107 (Mon Nov 27 20:46:04 2006) | next |
JUnit
is a testing framework originally written by Kent Beck and Erich Gamma in 1997unittest
self
)unittest.TestCase
unittest.main(), which:
unittest.TestCase
TestCase
assert
statementsassert_(condition)
: check that something is true (note the underscore)assertEqual(a, b)
: check that two things are equalassertNotEqual(a, b)
: the reverse of the aboveassertRaises(exception, func, …args…)
: call func
with arguments (if provided), and check that it raises the right exceptionfail()
: signal an unconditional failureimport unittest class TestAddition(unittest.TestCase): def test_zeroes(self): self.assertEqual(0 + 0, 0) self.assertEqual(5 + 0, 5) self.assertEqual(0 + 13.2, 13.2) def test_positive(self): self.assertEqual(123 + 456, 579) self.assertEqual(1.2e20 + 3.4e20, 3.5e20) def test_mixed(self): self.assertEqual(-19 + 20, 1) self.assertEqual(999 + -1, 998) self.assertEqual(-300.1 + -400.2, -700.3) if __name__ == '__main__': unittest.main()
.F. ====================================================================== FAIL: test_positive (__main__.TestAddition) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_addition.py", line 12, in test_positive self.assertEqual(1.2e20 + 3.4e20, 3.5e20) AssertionError: 4.6e+20 != 3.5e+20 ---------------------------------------------------------------------- Ran 3 tests in 0.000s FAILED (failures=1)
[a, b, c, …]
, it produces [a, a+b, a+b+c, …]
None
?def running_sum(seq): result = seq[0:1] for i in range(2, len(seq)): result.append(result[i-1] + seq[i]) return result class SumTests(unittest.TestCase): def test_empty(self): self.assertEqual(running_sum([]), []) def test_single(self): self.assertEqual(running_sum([3]), [3]) def test_double(self): self.assertEqual(running_sum([2, 9]), [2, 11]) def test_long(self): self.assertEqual(running_sum([-3, 0, 3, -2, 5]), [-3, -3, 0, -2, 3])
F.E. ====================================================================== ERROR: test_long (__main__.SumTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "running_sum_wrong.py", line 22, in test_long self.assertEqual(running_sum([-3, 0, 3, -2, 5]), [-3, -3, 0, -2, 3]) File "running_sum_wrong.py", line 7, in running_sum result.append(result[i-1] + seq[i]) IndexError: list index out of range ====================================================================== FAIL: test_double (__main__.SumTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "running_sum_wrong.py", line 19, in test_double self.assertEqual(running_sum([2, 9]), [2, 11]) AssertionError: [2] != [2, 11] ---------------------------------------------------------------------- Ran 4 tests in 0.001s FAILED (failures=1, errors=1)
def running_sum(seq): result = seq[0:1] for i in range(1, len(seq)): result.append(result[i-1] + seq[i]) return result
.... ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK
setUp
method, unittest
calls it before running each testtearDown
method, it is run after each testclass TestThiamine(unittest.TestCase): def setUp(self): self.fixture = Molecule(C=12, H=20, O=1, N=4, S=1) def test_erase_nothing(self): nothing = Molecule() self.fixture.erase(nothing) self.assertEqual(self.fixture['C'], 12) self.assertEqual(self.fixture['H'], 20) self.assertEqual(self.fixture['O'], 1) self.assertEqual(self.fixture['N'], 4) self.assertEqual(self.fixture['S'], 1) def test_erase_single(self): self.fixture.erase(Molecule(H=1)) self.assertEqual(self.fixture, Molecule(C=12, H=19, O=1, N=4, S=1)) def test_erase_self(self): self.fixture.erase(self.fixture) self.assertEqual(self.fixture, Molecule())
.E. ====================================================================== ERROR: test_erase_self (__main__.TestThiamine) ---------------------------------------------------------------------- Traceback (most recent call last): File "setup.py", line 49, in test_erase_self self.fixture.erase(self.fixture) File "setup.py", line 21, in erase for k in other.atoms: RuntimeError: dictionary changed size during iteration ---------------------------------------------------------------------- Ran 3 tests in 0.000s FAILED (errors=1)
TestCase.assertRaises
to check that a specific function raises a specific exceptiontry
/except
yourselfValueError
if the range is empty, or if the set of values is emptyclass TestInRange(unittest.TestCase): def test_no_values(self): try: in_range([], 0.0, 1.0) except ValueError: pass else: self.fail() def test_bad_range(self): try: in_range([0.0], 4.0, -2.0) except ValueError: pass else: self.fail()
StringIO
and cStringIO
modules can read and write strings instead of filesStringIO
wrappers around strings)StringIO
)class TestDiff(unittest.TestCase): def wrap_and_run(self, left, right, expected): left = StringIO(left) right = StringIO(right) actual = StringIO() diff(left, right, actual) self.assertEqual(actual.getvalue(), expected) def test_empty(self): self.wrap_and_run('', '', '') def test_lengthy_match(self): str = '''\ a b c ''' self.wrap_and_run(str, str, '') def test_single_line_mismatch(self): self.wrap_and_run('a\n', 'b\n', '1\n') def test_middle_mismatch(self): self.wrap_and_run('a\nb\nc\n', 'a\nx\nc\n', '2\n')
"J"
appears three times in a string)x = find_all(structure)[0]
is almost always wrongRect
is correctoverlap
, and see if the output is correctFigure 16.1: Rectangle Overlap Test Cases
Exercise 16.1:
Python has another unit testing module called doctest
.
It searches files for sections of text that look like interactive
Python sessions, then re-executes those sections and checks the
results. A typical use is shown below.
def ave(values): '''Calculate an average value, or 0.0 if 'values' is empty. >>> ave([]) 0.0 >>> ave([3]) 3.0 >>> ave([15, -1.0]) 7.0 ''' sum = 0.0 for v in values: sum += v return sum / float(max(1, len(values))) if __name__ == '__main__': import doctest doctest.testmod()
Convert a handful of the tests you have written for other
questions in this lecture to use doctest
. Do you prefer it
to unittest
? Why or why not? Do you think doctest
makes it easier to test small problems? Large ones? Would it be
possible to write something similar for C, Java, Fortran, or
Mathematica?
prev | Copyright © 2005-06 Python Software Foundation. | next |