У меня есть какие-то тестовые данные и я хочу создать модульный тест для каждого элемента. Моей первой идеей было сделать это так:
import unittest
l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]
class TestSequence(unittest.TestCase):
def testsample(self):
for name, a,b in l:
print "test", name
self.assertEqual(a,b)
if __name__ == '__main__':
unittest.main()
Недостатком этого является то, что он обрабатывает все данные в одном тесте. Я хотел бы создать один тест для каждого элемента на лету. Какие-либо предложения?
python
unit-testing
parameterized-unit-test
Питер Хоффманн
источник
источник
Ответы:
Это называется «параметризация».
Есть несколько инструментов, которые поддерживают этот подход. Например:
Полученный код выглядит так:
Который будет генерировать тесты:
По историческим причинам я оставлю оригинальный ответ около 2008 года):
Я использую что-то вроде этого:
источник
.__name__ =
чтобы включить.exact_method
тестированиеif __name__ == '__main__'
условном выражении? Конечно, он должен выходить за пределы этого, чтобы запускаться во время импорта (помня, что модули Python импортируются только один раз, даже если они импортированы из нескольких разных мест)Использование unittest (начиная с 3.4)
Начиная с Python 3.4, стандартный
unittest
пакет библиотеки имеетsubTest
менеджер контекста.Смотрите документацию:
Пример:
Вы также можете указать пользовательское сообщение и значения параметров для
subTest()
:Используя нос
Нос система тестирования поддерживает это .
Пример (приведенный ниже код является полным содержимым файла, содержащего тест):
Вывод команды переноса носа:
источник
Это можно решить элегантно, используя метаклассы:
источник
__new__
Метод в метаклассе вызывается при определении самого класса, а не при создании первого экземпляра. Я полагаю, что этот метод динамического создания тестовых методов более совместим с самоанализом, используемымunittest
для определения количества тестов в классе (то есть он может составить список тестов до того, как он создаст экземпляр этого класса).class TestSequence(unittest.TestCase, metaclass=TestSequenceMeta):[...]
dct
вместоdict
? Использование ключевых слов в качестве имен переменных сбивает с толку и подвержено ошибкам.Начиная с Python 3.4 для этой цели были введены подтесты unittest. Смотрите документацию для деталей. TestCase.subTest - это менеджер контекста, который позволяет изолировать утверждения в тесте, так что об ошибке будет сообщено с информацией о параметрах, но не остановит выполнение теста. Вот пример из документации:
Результат тестового прогона будет:
Это также часть unittest2 , поэтому она доступна для более ранних версий Python.
источник
setUp()
иtearDown()
не запускаются между суб-тестами.)self.setUp()
теоретически может вызываться вручную из подтеста. Что касаетсяtearDown
автоматического вызова в конце, может быть достаточно.load_tests - это малоизвестный механизм, введенный в 2.7 для динамического создания TestSuite. С его помощью вы можете легко создавать параметризованные тесты.
Например:
Этот код будет запускать все TestCases в TestSuite, возвращенном load_tests. Никакие другие тесты не запускаются автоматически механизмом обнаружения.
Кроме того, вы также можете использовать наследование, как показано в этом билете: http://bugs.python.org/msg151444
источник
Это можно сделать с помощью pytest . Просто напишите файл
test_me.py
с содержанием:И запустите свой тест с командой
py.test --tb=short test_me.py
. Тогда вывод будет выглядеть так:Это просто! Также pytest имеет больше функций , таких как
fixtures
,mark
,assert
и т.д. ...источник
py.test
unittest
py.test. Раньше у меня былиTestCase
базовые классы, которые могли динамически создавать дочерние элементы с различными аргументами, которые они сохраняли бы как переменные класса ... что было немного громоздко.py.test
этом yield_fixtures . Который может выполнить настройку , вернуть некоторые полезные данные в тест и после окончания теста произвести демонтаж . Светильники также могут быть параметризованы .Используйте библиотеку ddt . Он добавляет простые декораторы для методов тестирования:
Эта библиотека может быть установлена с
pip
. Не требуетnose
и отлично работает со стандартнымunittest
модулем библиотеки .источник
Вам будет полезно попробовать библиотеку TestScenarios .
источник
Есть также гипотеза, которая добавляет нечеткое или основанное на свойствах тестирование: https://pypi.python.org/pypi/hypothesis
Это очень мощный метод тестирования.
источник
@given()
макрос внутри класса unittest.Вы можете использовать плагин nose-ittr (
pip install nose-ittr
).Его очень легко интегрировать с существующими тестами, требуются минимальные изменения (если таковые имеются). Он также поддерживает нос многопроцессорной плагин.
Не то чтобы у вас также была возможность настроить
setup
функцию для каждого теста.Также возможно передать
nosetest
параметры, как с их встроенным плагиномattrib
, таким образом, вы можете запустить только определенный тест с определенным параметром:источник
Я использую метаклассы и декораторы для генерации тестов. Вы можете проверить мою реализацию python_wrap_cases . Эта библиотека не требует каких-либо тестовых сред.
Ваш пример:
Консольный вывод:
Также вы можете использовать генераторы . Например, этот код генерирует все возможные комбинации тестов с аргументами
a__list
иb__list
Консольный вывод:
источник
Я столкнулся с ParamUnittest на днях, когда смотрел исходный код на радон ( пример использования в репозитории github ). Он должен работать с другими платформами, расширяющими TestCase (например, Nose).
Вот пример:
источник
РЕЗУЛЬТАТ:
источник
def add_test_methods
функцией. Должно быть,def _add_test_methods
я думаюПросто используйте метаклассы, как показано здесь;
Вывод:
источник
Вы можете использовать
TestSuite
и пользовательскиеTestCase
классы.источник
__init__
функцию.Я обнаружил, что это хорошо работает для моих целей, особенно если мне нужно генерировать тесты, которые выполняют незначительные различия в процессе сбора данных.
TestGenerator
Класс может использоваться , чтобы породить различные наборы тестов , таких какTestCluster
.TestCluster
можно рассматривать как реализациюTestGenerator
интерфейса.источник
Это решение работает с
unittest
иnose
для Python 2 и Python 3:источник
У меня были проблемы с очень специфическим стилем параметризованных тестов. Все наши тесты Selenium могут выполняться локально, но они также должны иметь возможность удаленного запуска на нескольких платформах SauceLabs. По сути, я хотел взять большое количество уже написанных тестовых примеров и параметризовать их с наименьшим количеством возможных изменений в коде. Кроме того, мне нужно было иметь возможность передавать параметры в метод setUp, чего я не видел в других решениях.
Вот что я придумала:
При этом все, что мне нужно было сделать, это добавить простой декоратор @sauce_labs () к каждому обычному старому TestCase, и теперь при их запуске они оборачиваются и переписываются, так что все методы тестирования параметризуются и переименовываются. LoginTests.test_login (self) запускается как LoginTests.test_login_internet_explorer_10.0 (self), LoginTests.test_login_internet_explorer_11.0 (self) и LoginTests.test_login_firefox_43.0 (self), и у каждого из них есть свой собственный параметр. Платформа для запуска, даже в LoginTests.setUp, что крайне важно для моей задачи, поскольку именно там инициализируется соединение с SauceLabs.
В любом случае, я надеюсь, что это может помочь кому-то, кто хочет сделать аналогичную «глобальную» параметризацию своих тестов!
источник
Ответы на основе метаклассов все еще работают в Python3, но вместо
__metaclass__
атрибута нужно использоватьmetaclass
параметр, как в:источник
Мета-программирование - это весело, но можно начать. Большинство решений здесь затрудняют:
Итак, мое первое предложение состоит в том, чтобы следовать простому / явному пути (работает с любым участником тестирования):
Поскольку мы не должны повторяться, мое второе предложение основано на ответе @ Javier: охватить тестирование на основе свойств. Библиотека гипотез:
имеет много других интересных функций (статистика, дополнительный вывод теста, ...)
Класс TestSequence (unittest.TestCase):
Чтобы проверить ваши конкретные примеры, просто добавьте:
Чтобы запустить только один конкретный пример, вы можете закомментировать другие примеры (при условии, что пример будет запущен первым). Вы можете использовать
@given(st.nothing())
. Другой вариант - заменить весь блок:Хорошо, у вас нет четких имен тестов. Но, может быть, вам просто нужно:
Забавный пример
источник
Очень поздно на вечеринку, но у меня были проблемы с этим
setUpClass
.Вот версия ответа @ Javier, которая дает
setUpClass
доступ к динамически распределяемым атрибутам.Выходы
источник
Просто чтобы бросить другой раствор в смеси;)
По сути, это то же самое, что
parameterized
упомянуто выше, но специфично дляunittest
:Пример использования:
источник
Помимо использования setattr, мы можем использовать load_tests начиная с Python 3.2. Пожалуйста, обратитесь к сообщению в блоге blog.livreuro.com/en/coding/python/how-to-generate-discoverable-unit-tests-in-python-dynamically/
источник
Следующее - мое решение. Я нахожу это полезным, когда: 1. Должно работать для unittest.Testcase и unittest обнаружить 2. Иметь набор тестов для разных настроек параметров. 3. Очень просто, нет зависимости от других пакетов импорта unittest
источник
источник