Пользователь
0,0
рейтинг
4 сентября 2013 в 12:38

Разработка → Python. Генерация юнит-тестов из песочницы

Только ленивый ещё не писал о необходимости писать тесты. Но давайте признаемся честно — писать тесты зачастую скучно. Особенно для legacy-кода. Сотни повторяющихся, однообразных строк. Скука. Что с этим можно сделать?

image
Картинка для привлечения внимания. Красивый питон, да? (Автор фото: Paweł Stefaniak)

Pythoscope


Благо, мы программисты — народ ленивый, готовы убить пару недель для того, что бы решить часовую задачу за пять минут. Так что за несколько минут гугления в яндексе я нашел коллег по несчастью и интересное решение по облегчению написания тестов.

Устанавливаем Pythoscope:

sudo pip install Pythoscope


Примечание
К сожалению, у stable-ветки проблемы с юникодом. Для тестовых целей сойдет и она, но для реального применения лучше воспользоваться dev-веткой, благо она работает стабильно:

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




Протестируем кота


image

Что бы тестировать кота, нам сначала собственно нужен кот. Напишем его:
# 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!'


Теперь перейдем в папку с cat.py и инициализируем Pythoscope:

pythoscope --init


Команда создаст папку .pythoscope, где хранится вся информация, связанная с Pythoscope. А теперь, наконец, генерация собственно тестов:

pythoscope cat.py


У нас появилась папка tests с вложенным cat_test.py. В котором… Почти ничего нет:

# 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()


Негусто? Ну, по крайней мере теперь есть каркас, который будет экономить нам время при написании тестов.
Как выяснилось, магии не бывает — тесты сами не напишутся. Но не всё потеряно, мы можем помочь Pythoscope понять, что запускать для тестов. Для этого реализавны, так называемые «точки входа» (points of entry) — некие use-case использования нашего кода.

Напишем points of entry для нашего котэ:

# .pythoscope/points-of-entry/eat_fish_poe.py

from cat import Cat
Cat().eat('fish')


Запустим еще раз генерацию тестов:
pythoscope cat.py


Теперь лучше, к тестовому классу добавился метод который действительно что-то тестирует:
# 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'))

...


А что если подсунуть котэ не рыбу? Ошибка? Надо и это проверить:
# .pythoscope/points-of-entry/eat_tomato_poe.py

from cat import Cat
Cat().eat('tomato')


Генерируем:

pythoscope cat.py


Отлично, осталось лишь проверить:

nosetests

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

OK



Превосходно! Удачного и легкого тестирования!
@zloy531
карма
6,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (4)

  • 0
    Не совсем понял, чем это отличается от стандартного doctest'а. т.е. от создания файла cat_test.txt со следующим содержимым:

    >>> import cat
    >>> boris = cat.Cat()
    >>> boris.eat("fish")
    'Yummy!'
    >>> boris.eat("tomato")
    'Ugh!'
    >>> 
    


    и последующим запуском:
    python -m doctest cat_test.txt
    

    ?
    • +1
      Собственно отличий нет. Но это решение лишено основных минусов doctestов (позволю себе скопипастить их):
      — сложный код быстро становится нечитаемым
      — текстовый редактор не подсветит такой код,
      — статический анализатор не найдет в нем ошибок
      • +3
        — сложный код быстро становится нечитаемым

        Так это с любым кодом может так произойти, не только в тестах. Зависит от того как его писать. :)

        — текстовый редактор не подсветит такой код,

        IDE PyCharm подсвечивает код в комментариях, а также работает с ним как с обычным кодом если перед строчкой кода написать ">>>".

        Скриншот


        — статический анализатор не найдет в нем ошибок

        Зависит от IDE опять же, повторюсь, PyCharm c таким кодом работает так же как с исходником.
  • 0
    Прошу прощения за оффтоп:
    Автор фотографии — Paweł Stefaniak

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.