[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