Инфраструктура поблочного тестирования для модуля Python

Я пишу модуль Python, и я хотел бы к модульному тесту его. Я плохо знаком с Python и несколько обманутый доступными опциями.

В настоящее время я хотел бы записать свои тесты как doctests, как мне нравится декларативный, а не обязательный стиль (однако, не стесняйтесь разуверять меня этого предпочтения, если это дезинформировано). Это поднимает несколько вопросов, однако:

  1. Куда я должен поместить тесты? В том же файле как код они тестируют (или в docstrings для doctests)? Или считают лучше выделить их в их собственный каталог?
  2. Как я могу запустить все тесты в целом модуле от командной строки сразу?
  3. Как я могу сообщить о покрытии кода набора тестов?
  4. Какие-либо другие лучшие практики я должен знать для поблочного тестирования в Python?

8
задан fmark 14 July 2010 в 02:25
поделиться

6 ответов

не стесняйтесь разуверить меня в этом предпочтение, если оно дезинформирует

Я считаю, что использовал doctest более широко (намного расширяя границы его использования по назначению), чем любой другой разработчик открытого кода, по крайней мере в рамках одного проекта - все тесты в моем gmpy проекте являются doctests. Это было совершенно новым в то время, когда gmpy только начинался, это казалось отличным маленьким трюком, и если что-то стоит делать, то стоит делать это в избытке - верно?)

Ошибаетесь. За исключением gmpy, где переделывать всё под правильные юнит-тесты было бы слишком накладно, я больше никогда не допускал этой ошибки: в наши дни я использую юнит-тесты как юнит-тесты, а доктесты просто для проверки документации, как они всегда и должны были использоваться. То, что делают доктесты (сравнивают ожидаемый и фактический результат на равенство - и все), просто не является хорошей или надежной основой для создания надежного набора тестов. Иначе и быть не могло.

Я бы рекомендовал вам посмотреть на nose. Модуль unittest в новом Python 2.7 намного богаче и приятнее, и если вы застряли на 2.4, 2.5 или 2.6, вы все равно можете использовать новые возможности с помощью unittest2, который вы можете скачать и установить; nose хорошо дополняет unittest.

Если вы терпеть не можете unittest (но - попробуйте, он вам понравится!), попробуйте py.test, альтернативный пакет с совершенно другой философией.

Но, пожалуйста, не растягивайте doctest для тестирования чего-либо, кроме примеров в документации! Сравнение "точно-качественно" слишком часто встает на вашем пути, как мне пришлось узнать за свой (метафорический;-) счет в gmpy...

12
ответ дан 5 December 2019 в 08:50
поделиться

Мне не нравятся доктесты по следующим причинам:

  • Вы не можете запустить подмножество тестов. Когда тест не проходит, полезно запустить только один тест. Doctest не предоставляет возможности сделать это.
  • Если в середине доктеста происходит сбой, все останавливается. Я бы предпочел увидеть все результаты, чтобы решить, как устранить поломку.
  • Стиль кодирования является стилизованным и должен иметь результаты для печати.
  • Ваш код выполняется особым образом, поэтому сложнее понять, как он будет выполняться, сложнее добавить помощников и сложнее запрограммировать тесты.

Этот список взят из моего сообщения в блоге Что мне не нравится в doctest , где есть еще кое-что и длинная ветка комментариев, в которых обсуждаются моменты.

О покрытии: я не верю, что есть инструмент покрытия для Python, который измерял бы охват в рамках тестов. Но поскольку это просто длинные списки операторов без ветвей или циклов, это проблема?

3
ответ дан 5 December 2019 в 08:50
поделиться

doctests отлично подходят для быстрых, второстепенных модульных тестов, которые описывают некоторые из основных способов использования рассматриваемых объектов (поскольку они отображаются в строках документации и, следовательно, помогают (что угодно) и т. Д.) .

Я лично обнаружил, что обширное и более тщательное тестирование более эффективно с использованием модуля unittest, и теперь модуль 2.7 (обратно перенесенный на unittest2) имеет еще более удобные утверждения. Вы можете настроить наборы тестов и любой сложный сценарий с помощью фреймворка модульного тестирования и покрыть целые ряды различных тестов за один раз (из командной строки)

покрытия.py , от Неда Батчелдера и как Упоминания @bstpierre будут работать с любым из них, и я рекомендую его, чтобы увидеть, что вы тестировали в коде, а что нет. Вы можете добавить его в систему CI (например, Hudson или что-то еще, что вы хотите использовать), чтобы не отставать от того, что покрыто, а что нет, а отчеты HTML отлично подходят для того, чтобы увидеть, что не было затронуто тестированием. Покрытие поддерживает вывод Junit xml, который многие системы CI знают, как отображать текущие результаты в диаграммах, чтобы вы могли видеть, как со временем сборка становится лучше или хуже.

1
ответ дан 5 December 2019 в 08:50
поделиться

У меня есть подозрение, что Алекс может быть немного впереди меня на кривой программиста, но если вы хотите услышать мнение человека с некоторым опытом работы с Python (в качестве "пользователя", а не эксперта или евангелиста), но не в той же лиге, мои выводы о тестировании модулей были практически такими же.

Doctests может показаться отличным вариантом для простого тестирования в начале, и я пошел в этом направлении для какого-то личного проекта дома, потому что это было рекомендовано в другом месте. На работе мы используем nose (хотя он настолько консервирован и завёрнут, что у меня сложилось впечатление, что до недавнего времени мы использовали pyUnit), и несколько месяцев назад я перешёл на nose и дома.

Первоначальное время на установку и управление, а также отделение от реального кода, может показаться ненужным в начале, особенно когда вы тестируете что-то не очень большое, но в долгосрочной перспективе я обнаружил, что доктесты встают на пути каждого рефакторинга или реструктуризации, которые я хотел сделать, их довольно трудно поддерживать, практически невозможно масштабировать, и это очень быстро компенсирует первоначальную экономию. И да, я знаю, что модульное тестирование - это не то же самое, что интеграционное тестирование, но доктесты имеют тенденцию слишком строго определять ваши единицы для вас. Они также не очень хорошо подходят для unit-based agile, если вы когда-нибудь решите, что это подходящий инструмент для набросков или модель разработки.

Возможно, вам потребуется немного времени, чтобы спланировать и затем усовершенствовать свои модульные тесты так, как это делает pyUnit или nose, но есть шанс, что даже в краткосрочной перспективе вы обнаружите, что это действительно помогает вам на многих уровнях. Я знаю, что это помогло мне, и я относительно недавно столкнулся со сложностью и масштабом кодовой базы, над которой я работаю в настоящее время. Просто нужно сжать зубы на первые несколько недель.

2
ответ дан 5 December 2019 в 08:50
поделиться

Чтобы узнать о покрытии, посмотрите отличный extension.py .

В остальном все, что написал Алекс Мартелли, очень точно.

1
ответ дан 5 December 2019 в 08:50
поделиться

Я согласен со всеми вышеприведенными пунктами о том, что doctest не масштабируется, и я предпочитаю придерживаться unittest.

Один совет, который я могу внести, это вызывать юнит-тесты из обработки кода __name__ == "__main__, так что если файл тестов запускается как скрипт, он будет запускать свои тесты.

eg:

#!/usr/bin/env python

"""
Unit tests for the GetFiles.py utility
"""

import unittest
from FileUtilities import getTree

class TestFileUtilities(unittest.TestCase):

   def testGetTree(self):
      """
      Tests that a known tree is found and incidentally confirms
      that we have the tree we expected to use for our current
      sample extraction.
      """
      found = getTree('./anzmeta-dtd', '.pen')
      expected_path_tail = ['ISOdia.pen',
                       'ISOgrk1.pen',
                       'ISOtech.pen']
      for i, full_path in enumerate(found):
         assert full_path.endswith( expected_path_tail[i] ), expected_path_tail[i]

# other tests elided         

if __name__ == "__main__":
   # When this module is executed from the command-line, run all its tests
   unittest.main()
0
ответ дан 5 December 2019 в 08:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: