[Tutor] TDD in Python
Peter Otten
__peter__ at web.de
Tue Sep 27 05:27:29 EDT 2016
angela ebirim wrote:
> Hello everyone,
>
> I'm a new member on this maling list and am in the process of learning
> python.
>
> I'm keen to learn about testing my Python code and hoping someone could
> help me with this query...
>
> #test.py
>
> class Test:
> def __init__(self, members):
> self.members = members
>
> def printMembers(self):
> print('Printing members of Test class...')
> for member in self.members: print('\t%s ' % member)
>
>
> test = Test(['Gazelle', 'Elephant', 'Lion', 'Fish'])
> test.printMembers()
>
> #test_test.py
>
> import unittest
> from test import Test
>
> class TestTestCase(unittest.TestCase):
> """Tests for `test.py`."""
>
> #preparing to test
>
> def setUp(self):
> """Sample test case"""
> print "TestTest::setUp_:begin"
> # self.members = [1, 2, 3, 4, 5]
> self.members = Test([1, 2, 3, 4])
>
>
> def test_is_printMembers(self):
> """Will print a list of contents?"""
> self.assertTrue(self.members.printMembers)
>
>
> if __name__ == '__main__':
> unittest.main()
>
> Does my test code in test_test.py look correct?
Steven has enough experience to plough through and show you how to test what
you have, but if you have the choice another approach is often advisable:
write your code in such a way that it is easy to test.
The easiest code to test is a function with a return value that is
completely determined by its input, e. g.
def add(a, b):
return a + b
This is called a "pure" function. A test would be just
self.assertEqual(add(1, 2), 3)
Slightly harder but still doable is a class
class Calculator:
def __init__(self, a, b):
self.a = a
self.b = b
def sum(self): return self.a + self.b
The test is
self.assertEqual(Caculator(1, 2).sum(), 3)
or in more complex cases
class Test(TestCase):
def setUp(self):
self.calculator = Calculator(1, 2)
def test_sum(self):
self.assertEqual(self.calculator.sum(), 3)
When you have to interact with the environment (the console, a GUI, a
database) good tests will be harder to create, so the lazy bastard's
approach is to avoid them if you can. That's why I would not add a
print_sum() method to the above Caculator class. print_sum() would
implicitly communicate with the console, so if you are serious about testing
you might consider that it's closed while you write, redirected to a file,
even a file on a full device, ... the possibilities and failure modes are
endless.
Instead I might add a format_sum() method
def format_sum(self):
return "{0.a} + {0.b} = {1}".format(self, self.sum())
If I want to print I can invoke it with
c = Calculator(1, 2)
print(c.format_sum())
which is not much harder than
c.print_sum()
but more flexible and easy to test
def test_format_sum(self):
self.assertEqual(
self.calculator.format_sum(),
"1 + 2 = 3")
The outside world remains messy, but my Calculator class is unaffected, let
the makers of print() take care of it.
More information about the Tutor
mailing list