Back to Home

Python Unit Test Generation

python · unit-testing · test generation · pythoscope

Python Unit Test Generation

Only the lazy did not write about the need to write tests yet. But let's be honest, writing tests is often boring. Especially for legacy code. Hundreds of repeating, uniform lines. Boredom. What can be done with this?

image
A picture to attract attention. Beautiful python, huh? (Photo by Paweł Stefaniak)

Pythoscope


Fortunately, we are programmers - people are lazy, ready to kill a couple of weeks in order to solve the one-hour task in five minutes. So in a few minutes of googling in Yandex, I found colleagues in misfortune and an interesting solution to facilitate writing tests.

Install Pythoscope:

sudo pip install Pythoscope


Note
Unfortunately, the stable branch has unicode problems. For test purposes, it will work, but for a real application it is better to use the dev-branch, since it works stably:

sudo apt-get install bzr
bzr branch lp:pythoscope
cd pythoscope/
python setup.py install




Test cat


image

To test a cat, we first need a cat. Let's write it:
# cat.py
class Cat(object):
    def __init__(self, name='Tom'):
        self.name = name
    def eat(self, food):
        if food == 'fish':
            return 'Yummy!'
        else:
            return 'Ugh!'


Now go to the folder with cat.py and initialize the Pythoscope:

pythoscope --init


The command will create a .pythoscope folder, where all the information related to the Pythoscope is stored. And now, finally, the generation of the tests themselves:

pythoscope cat.py


We now have the tests folder with cat_test.py nested. In which ... Almost nothing:

# tests/cat_test.py
import unittest
class TestCat(unittest.TestCase):
    def test___init__(self):
        # cat = Cat(name)
        assert False # TODO: implement your test here
    def test_eat(self):
        # cat = Cat(name)
        # self.assertEqual(expected, cat.eat(food))
        assert False # TODO: implement your test here
if __name__ == '__main__':
    unittest.main()


Not much? Well, at least now there is a framework that will save us time when writing tests.
As it turned out, there is no magic - tests themselves will not be written. But not everything is lost, we can help Pythoscope understand what to run for tests. For this, the so-called “points of entry” are realizable — some use-case uses of our code.

Let's write points of entry for our kote:

# .pythoscope/points-of-entry/eat_fish_poe.py
from cat import Cat
Cat().eat('fish')


Run the test generation again:
pythoscope cat.py


Now better, a method has been added to the test class that really tests something:
# tests/cat_test.py
...
def test_eat_returns_Yummy_for_fish_after_creation_with_Tom(self):
        cat = Cat('Tom')
        self.assertEqual('Yummy!', cat.eat('fish'))
...


But what if you don’t put kote to the fish? Error? It is necessary to check this:
# .pythoscope/points-of-entry/eat_tomato_poe.py
from cat import Cat
Cat().eat('tomato')


We generate:

pythoscope cat.py


Well, all that remains is to check:

nosetests
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK


Fine! Successful and easy testing!

Read Next