OpenQuality.ru

Качество программного обеспечения

Качество программного обеспечения: в главных ролях

Лента  Радар  Блог  Опыт  
Разум  Видео  Заметки  Эпизоды


Python: модульное тестирование с MiniMock

Добрый день.

Модуль MiniMock – пожалуй, один из наиболее изящных способов создания mock-объектов в Python. История MiniMock началась с 25 строк кода, которые Ian Bicking набросал под впечатлением от модуля python-mock. Будучи приверженцем doctest, Ian решил задействовать его возможности для подготовки имитаторов. В результате, по наводке python-mock и с doctest наперевес, появился MiniMock, возможности которого охватывают базовые сценарии создания mock-объектов. За три года усилиями энтузиастов функциональность модуля MiniMock значительно расширилась, но он по-прежнему остается компактным и удобным в использовании.

Текущая версия модуля доступна на python.org. Ниже представлена работа с последней на сегодня версией 1.2.3. В качестве примера рассматривается максимально упрощенная система выдачи книг в библиотеке. Модуль library.py содержит два класса Books и Readers. Работа с классами Books и Readers иллюстрируется функцией simple_example. Файл library.py:

class Books:
        def __init__ (self, title):
                self.title = title
                self.reader = "In place"
 
        def current_reader (self, reader):
                self.reader = reader
 
        def get_reader (self):
                return self.reader
 
 
class Readers:
        def __init__ (self, name):
                self.name = name
                self.book = ""
 
        def current_book (self, book):
                self.book = book
 
        def get_book (self):
                return self.book
 
 
def simple_example():
        reader = Readers ("Obama")
        book = Books ("War and Peace")
 
        reader.current_book (book.title)
        book.current_reader (reader.name)
 
        title = reader.get_book()
        print title
 
        reader_name = book.get_reader()
        print reader_name
 
if __name__ == "__main__":
        simple_example()

Запуск:

[capt@rh564 Work]# python library.py
War and Peace
Obama

Когда книга выдается читателю, должны быть выполнены два действия: название книги необходимо записать в формуляр читателя, а фамилию читателя – в формуляр книги. Этим занимается функция book_checkout, представленная в модуле main.py:

from library import Readers, Books
 
def book_checkout (reader, book):
        reader.current_book (book.title)
        book.current_reader (reader.name)

Подготовим тест для этой функции. Мы хотим быть уверенными в том, что при ее выполнении будут вызваны два метода: current_book для читателя и current_reader для книги. Дополним скрипт main.py:

from minimock import Mock, TraceTracker, assert_same_trace
from library import Readers, Books
 
def book_checkout (reader, book):
        reader.current_book (book.title)
        book.current_reader (reader.name)
 
 
def test_book_checkout():
        tt = TraceTracker()
 
        Readers.current_book = Mock ('Readers.current_book', tracker = tt)
        Books.current_reader = Mock ('Books.current_reader', tracker = tt)
 
        reader = Readers("Obama")
        book = Books("War and Peace")
 
        expect_mock_output = """\
        Called Readers.current_book('War and Peace')
        Called Books.current_reader('Obama')"""
 
        book_checkout (reader, book)
        assert_same_trace(tt, expect_mock_output)
 
test_book_checkout()

Результат запуска main.py более чем лаконичен:

[capt@rh564 Work]# python main.py
[capt@rh564 Work]#

Что произойдет, если мы изменим логику работы book_checkout? Скажем, уберем вызов book.current_reader (reader.name) и тем самым “забудем” прописать в формуляре книги ее нынешнего читателя? Вот что получится:

[capt@rh564 MiniMock]# python main.py
Traceback (most recent call last):
  File "main.py", line 25, in ?
    test_book_checkout()
  File "main.py", line 23, in test_book_checkout
    assert_same_trace(tt, expect_mock_output)
  File "build/bdist.linux-x86_64/egg/minimock.py", line 213, in assert_same_trace
AssertionError: Expected:
        Called Readers.current_book('War and Peace')
        Called Books.current_reader('Obama')
Got:
    Called Books.current_reader('Obama')

Причина появления AssertionError: при выполнении book_checkout вызов методов отличается от ожидаемого. Таким образом, unit-тест test_book_checkout отслеживает поведение функции book_checkout. Если логика ее работы изменится, мы будем предупреждены.

Более подробную информацию о MiniMock можно получить в документации к модулю. Помимо этого, будет полезно ознакомиться с кодом minimock.py (доступен в архиве MiniMock-1.2.3.tar.gz). Он небольшой, но достаточно информативный. Каждый класс снабжен описанием и примерами его использования. Счастливого взлета.

Отправить в Twitter, Facebook, ВКонтакте | Опубликовано 02.06.2009 в рубрике "Модульные тесты"

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

  1. Автор комментария : Ochir | June 22, 2009

    Добрый день!

    спасибо за статью, пригодилась.
    А вы пробовали использовать другие mock модули?
    в частности mox и pmock?

    С уважением,
    Очир

    [Ответить]


  2. Автор комментария : Капитан Аляска | June 23, 2009

    Добрый день, Очир! Спасибо за добрые слова. Pmock не пробовал (вот что о нем пишут: pMock has not been under active development since mid 2004). В Mox смотрел только примеры из документации. Задач, в которых было бы удобно его применить, пока не встретил.

    [Ответить]


  3. Автор комментария : Очир | July 13, 2009

    можете удалить предыдущий коммент. Проблема была в классе, в котором находились тест кейсы. При вынесении тест кейсов в отдельные функции заработало. Правда почему не работает в классах - загадка…

    [Ответить]


  4. Автор комментария : Капитан Аляска | July 14, 2009

    Добрый день, Очир. restore() пробовал, работает. Но не вызывал из tearDown(). Посмотрите вот эту ссылку: похоже, решалась подобная задача:
    http://osdir.com/ml/python.testing.general/2008-02/msg00000.html

    [Ответить]



Добавить комментарий

Пожалуйста, исправьте результат: дважды два равно



КРАТКОЕ СОДЕРЖАНИЕ

Что такое качество программного обеспечения и как его улучшить: теория и практика, задачи и решения, подводные камни и обходные пути.


ПУТЕВОДИТЕЛЬ

Проект был основан в 2008 году. За это время часть статей устарела, а некоторые из них вызывают улыбку, но пусть они останутся в том виде, в котором были написаны. Cписок всех статей с краткой аннотацией и разбивкой по рубрикам: открыть.

ПОДПИСКА

Доступ к самым интересным материалам по электропочте и RSS. Подробности.

ИЩЕЙКА