Как мне настроить процесс разработки TDD с помощью Google App Engine?

Я в первую очередь парень из Ruby, но в последнее время я работал над большим количеством материалов Python, в частности, с кодом App Engine. В Ruby я бы использовал автоматическую непрерывную интеграцию (autotest), инструменты покрытия кода (rcov), статический анализ (reek) и тестирование мутаций (heckle) в моем процессе разработки, но я не уверен, как лучше всего настроить аналогичный процесс разработки для среды App Engine. Я также интересовался бы аналогами RSpec и Cucumber для Python, который может работать в App Engine.

Ответы

Ответ 1

В моем проекте GAE я использую:

  • NoseGAE - это критическая часть, которая связывает всех остальных вместе.
  • Макет, как в Джон отличный ответ. Я использую это в основном для AWS и других веб-сервисов.
  • Светильники (пакет, а не идея)

Я также предпочитаю многие идиомы Rails. Я разбил свои тесты на единицу и функционально использовал пакеты Python. Вы можете запустить подмножество тестов с помощью --tests=unit или --tests=functional. Это все немного более ручно, чем Rails, но по крайней мере я могу unit test жесткий материал и убедиться, что у меня никогда нет регрессий.

Я также сделал простой класс FunctionalTest для выполнения большинства распространенных действий в Rails, таких как assert_response и assert_xpath (аналогично assert_select).

class FunctionalTest(Test):
  def get(self, *args, **kw):
    self.response = app.get(*args, **kw)

  def post(self, *args, **kw):
    self.response = app.post(*args, **kw)

  def assert_response(self, expected):
    pattern = str(expected) if re.search(r'^\d+$', expected) \
                            else (r'^\d+ %s' % expected)
    assert re.search(pattern, self.response.status, re.IGNORECASE), \
           'Response status was not "%s": %s' % (expected, self.response.status)

  def assert_xpath(self, path, expected):
    element = ElementTree.fromstring(self.response.body)
    found_nodes = element.findall('.' + path)
    if type(expected) is int:
      assert_equal(expected, len(found_nodes))
    elif type(expected) is str or type(expected) is unicode:
      assert (True in [(node.text == expected) for node in found_nodes])
    else:
      raise Exception, "Unknown expected value: %r" % type(expected)

Если вы выполняете множество поисков равенства элементов ListElement, обязательно изучите синтаксис --tests=foo, потому что тестирование для сопоставления элементов в списке выполняется очень медленно.

Иногда мне нравится загружать консоль Rails на мои данные прибора, чтобы узнать, что происходит в тестовой среде (т.е. script/console test). Чтобы сделать что-то подобное с GAE, запустите dev_appserver.py с параметром --datastore_path="$TMPDIR/nosegae.datastore" (или, возможно, замените /tmp на $TMPDIR.

Ответ 2

В Python вы не всегда найдете один-один эквивалент инструментов тестирования Ruby, но в Python есть отличные инструменты тестирования. Некоторые из полезных инструментов, которые я нашел полезными, включают:

  • unittest - инструмент xUnit, включенный в стандартную библиотеку Python. Он включает в себя все основы для модульного тестирования.
  • doctest - потрясающая часть стандартной библиотеки, она позволяет вам писать тесты в docstrings функций, классов, модулей, методы. Это отлично подходит для передачи предполагаемого использования API. Ian Bicking предлагает использовать доктрину для развития, управляемого поведением. Doctest очень хорошо вписывается в систему документации Sphinx (вы можете убедиться, что все примеры в документации проходят каждый раз при сборке документов).
  • nose и py.test видны как версии следующего поколения unittest. Они могут запускать все существующие экземпляры unittest, но допускают более простые, неклассовые модульные тесты. py.test также позволяет распределенное выполнение.
  • mock - хорошая библиотека для насмешливого поведения.
  • tdaemon наблюдает за каталогом обновлений вашего кода и повторно выполнит ваш тестовый набор. (мой личный филиал содержит несколько неудобных улучшений).
  • Buildbot, Bitten и даже Hudson все хорошо работают как полноценные серверы непрерывной интеграции для кода Python.
  • coverage.py вычисляет покрытие кода вашего кода.
  • pylint предоставит логический анализ вашего кода, убедившись, что он соответствует общим правилам кодирования и не имеет общих ошибок. Существует также "более легкий" инструмент анализа, PyFlakes.
  • Существует несколько инструментов тестирования HTTP/Browser, которые хорошо работают в Python, включая Twill, Selenium и Windmill.

Если вы используете Django для App Engine, он включает несколько расширений для unittest, которые позволяют имитировать HTTP-клиент и постоянство базы данных.

Существует множество других инструментов, которые я не использовал (например, PySpec и Behaviour), что также может быть полезно. Я не видел никакого инструмента тестирования мутаций в Python, но я уверен, что есть один (я хотел бы узнать, что это такое).

Счастливое тестирование!

Ответ 3

Не использовал App Engine, но мое чувство для самых популярных инструментов тестирования python -

  • unittest/doctest - это пакеты тестирования из стандарта Python библиотека. unittest - это xUnit для python.
  • nose - тестовый бегун/искатель. У него много вариантов, в том числе --with-coverage, который использует coverage, чтобы дать вам покрытие кода отчетов.
  • pylint - это наиболее функциональный инструмент для проверки текста для python. Полезно за синтаксическая проверка, поскольку она рекомендует использовать неиспользуемые переменные/функции, когда методы должны быть функциями и т.д.
  • pester (тестирование мутаций)
  • buildbot (непрерывная интеграция)

Вероятно, вам захочется ссылаться на этот (не совсем полный) список Python Инструменты тестирования.

Для BDD поле было тонким в последний раз, когда я проверил. Многие из настоящих инструментов BDD не использовались с носом и/или слишком ограничивались в синтаксисе, который они требовали. Возможно, вам повезло с spec, который является BDD-подобным носовым плагином. Просто нашел pyccuracy, который очень похож на огурец, но у меня нет попробовал.

Для чего стоит, теперь я просто использую nosetests -v (носовой бегун с --verbose), который будет использовать первую строку докшлинга в тестовом бегуне вывод. То есть, учитывая тест, например:

class TestFoo(unittest.TestCase):
    def testAnyNameHere(self):
        """ Foo should be bar"""
        foo = "bar"
        self.assertEqual(foo, 'bar')

nosetests будут давать:

$ nosetests -v
Foo should be bar... ok

-----------------------------
Ran 1 tests in 0.002s
OK

Ответ 5

Для тестирования мутации попробуйте mutmut, он доступен на https://github.com/boxed/mutmut/

Это так же просто, как "pip install mutmut", затем "mutmut run", если вы используете pytest.