Содержание страницы
26.3. unittest – Фреймворк для модульного тестирования¶unittest – Unit testing framework
(Если вы уже знакомы с основными понятиями тестирования, можете перейти к списку методов assert.)
Фреймворк для модульного тестирования unittest изначально был вдохновлён JUnit и по духу близок к основным фреймворкам модульного тестирования на других языках. Он поддерживает автоматизацию тестов, совместное использование кода настройки и завершения для тестов, объединение тестов в коллекции, а также независимость тестов от фреймворка для составления отчётов.
Для этого unittest поддерживает несколько важных концепций в объектно-ориентированном стиле:
- тестовая фикстура
- Тестовая фикстура представляет собой подготовку, необходимую для выполнения одного или нескольких тестов, и любые сопутствующие действия по очистке. Это может включать, например, создание временных или прокси-баз данных, каталогов или запуск серверного процесса.
- тестовый случай
- Тестовый пример – это отдельная единица тестирования. Он проверяет конкретную реакцию на определённый набор входных данных. unittest предоставляет базовый класс TestCase, который можно использовать для создания новых тестовых примеров.
- набор тестов
- Набор тестов – это совокупность тестовых случаев, наборов тестов или и того, и другого. Он используется для объединения тестов, которые должны выполняться вместе.
- исполнитель тестов
- Исполнитель тестов – это компонент, который управляет выполнением тестов и предоставляет результат пользователю. Исполнитель может использовать графический интерфейс, текстовый интерфейс или возвращать специальное значение, указывающее на результаты выполнения тестов.
См. также
- Модуль doctest
- Ещё один модуль поддержки тестирования с совершенно другим подходом.
- Простое тестирование в Smalltalk: с шаблонами
- Оригинальная статья Кента Бека о фреймворках тестирования, использующих шаблон, общий для unittest.
- Nose и py.test
- Сторонние фреймворки unittest с более лёгким синтаксисом для написания тестов. Например, assert func(10) == 42.
- Таксономия инструментов тестирования Python
- Обширный список инструментов тестирования Python, включая фреймворки функционального тестирования и библиотеки имитационных объектов (mock).
- Список рассылки по тестированию в Python
- Группа по интересам для обсуждения тестирования и инструментов тестирования в Python.
Скрипт Tools/unittestgui/unittestgui.py в дистрибутиве исходного кода Python – это инструмент с графическим интерфейсом для обнаружения и выполнения тестов. Он предназначен в первую очередь для упрощения работы тех, кто только знакомится с модульным тестированием. Для производственных сред рекомендуется запускать тесты с помощью системы непрерывной интеграции, такой как Buildbot, Jenkins или Hudson.
26.3.1. Простой пример¶Basic example
Модуль unittest предоставляет богатый набор инструментов для создания и запуска тестов. В этом разделе показано, что даже небольшого подмножества этих инструментов достаточно для удовлетворения потребностей большинства пользователей.
Вот короткий скрипт для тестирования трёх функций из модуля random:
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.seq = list(range(10))
def test_shuffle(self):
# проверить, что перемешанная последовательность не теряет ни одного элемента
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, list(range(10)))
# должно вызывать исключение для неизменяемой последовательности
self.assertRaises(TypeError, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq)
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
if __name__ == '__main__':
unittest.main()
Тестовый пример создаётся путём создания подкласса unittest.TestCase. Три отдельных теста определяются методами, имена которых начинаются с букв test. Это соглашение об именах сообщает программе запуска тестов, какие методы представляют собой тесты.
Суть каждого теста сводится к вызову assertEqual() для проверки ожидаемого результата; assertTrue() – для проверки условия; или assertRaises() – чтобы убедиться, что возникает ожидаемое исключение. Эти методы используются вместо оператора assert, чтобы средство запуска тестов могло накапливать все результаты и формировать отчёт.
Если определён метод setUp(), средство запуска тестов выполнит его перед каждым тестом. Аналогично, если определён метод tearDown(), средство запуска тестов вызовет его после каждого теста. В примере setUp() использовался для создания новой последовательности для каждого теста.
Последний блок демонстрирует простой способ запуска тестов. unittest.main() предоставляет интерфейс командной строки для тестового скрипта. При запуске из командной строки указанный скрипт выдаёт вывод, который выглядит так:
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
Передача параметра -v тестовому скрипту укажет unittest.main() включить более высокий уровень подробности и выдать следующий вывод:
test_choice (__main__.TestSequenceFunctions) ... ok
test_sample (__main__.TestSequenceFunctions) ... ok
test_shuffle (__main__.TestSequenceFunctions) ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.110s
OK
Приведённые выше примеры показывают наиболее часто используемые возможности unittest, которых достаточно для удовлетворения многих повседневных потребностей тестирования. В остальной части документации подробно рассматривается полный набор возможностей, начиная с основ.
26.3.2. Интерфейс командной строки¶Command-Line Interface
Модуль unittest можно использовать из командной строки для запуска тестов из модулей, классов или даже отдельных тестовых методов:
python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
Можно передать список с любой комбинацией имён модулей, а также полных имён классов или методов.
Тестовые модули также можно указывать по пути к файлу:
python -m unittest tests/test_something.py
Это позволяет использовать автодополнение имён файлов в оболочке для указания тестового модуля. Указанный файл по-прежнему должен быть импортируем как модуль. Путь преобразуется в имя модуля путём удаления ‘.py’ и замены разделителей пути на ‘.’. Если требуется выполнить тестовый файл, который не импортируется как модуль, следует запускать файл напрямую.
Можно запускать тесты с большей детализацией (повышенной подробностью), передав флаг -v:
python -m unittest -v test_module
При запуске без аргументов запускается автоматическое обнаружение тестов:
python -m unittest
Чтобы получить список всех параметров командной строки:
python -m unittest -h
Изменено в версии 3.2: В более ранних версиях можно было запускать только отдельные тестовые методы, а не модули или классы.
26.3.2.1. Параметры командной строки¶Command-line options
unittest поддерживает следующие параметры командной строки:
- -b, --buffer¶
Потоки стандартного вывода и стандартной ошибки буферизируются во время выполнения теста. Вывод при успешном тесте отбрасывается. При ошибке или провале теста вывод выводится обычным образом и добавляется к сообщениям о неудаче.
- -c, --catch¶
Нажатие Control-C во время выполнения теста дожидается завершения текущего теста, после чего выводит все накопленные результаты. Второе нажатие Control-C вызывает обычное исключение KeyboardInterrupt.
См. раздел Обработка сигналов с описанием функций, предоставляющих эту возможность.
- -f, --failfast¶
Остановить выполнение теста при первой же ошибке или неудаче.
Новое в версии 3.2: Были добавлены параметры командной строки -b, -c и -f.
Командная строка также может использоваться для автоматического обнаружения тестов, для запуска всех тестов в проекте или только их части.
26.3.3. Обнаружение тестов¶Test Discovery
Новое в версии 3.2.
Unittest поддерживает простое обнаружение тестов. Чтобы быть совместимыми с обнаружением тестов, все тестовые файлы должны быть модулями или пакетами, импортируемыми из корневого каталога проекта (это означает, что их имена файлов должны быть валидными идентификаторами).
Обнаружение тестов реализовано в TestLoader.discover(), но также может использоваться из командной строки. Основное использование в командной строке:
cd project_directory
python -m unittest discover
Примечание
В качестве сокращения python -m unittest эквивалентно python -m unittest discover. Если требуется передать аргументы для обнаружения тестов, подкоманду discover необходимо указывать явно.
Подкоманда discover имеет следующие параметры:
- -v, --verbose¶
Подробный вывод
- -s, --start-directory directory¶
Каталог для начала обнаружения (по умолчанию .)
- -p, --pattern pattern¶
Шаблон для сопоставления тестовых файлов (по умолчанию test*.py)
- -t, --top-level-directory directory¶
Корневой каталог проекта (по умолчанию – каталог начала поиска)
Параметры -s, -p и -t можно передавать в качестве позиционных аргументов в указанном порядке. Следующие две командные строки эквивалентны:
python -m unittest discover -s project_directory -p '*_test.py'
python -m unittest discover project_directory '*_test.py'
Помимо пути можно передать имя пакета, например myproject.subpackage.test, в качестве начального каталога. Указанное имя пакета будет импортировано, а его расположение в файловой системе будет использовано как начальный каталог.
Внимание
Обнаружение тестов загружает тесты путём их импорта. Когда обнаружение найдёт все тестовые файлы в указанном начальном каталоге, оно преобразует пути в имена пакетов для импорта. Например, foo/bar/baz.py будет импортирован как foo.bar.baz.
Если пакет установлен глобально, и предпринимается попытка обнаружения тестов в другой копии пакета, то импорт может произойти из неправильного места. Если это произойдет, обнаружение тестов выдаст предупреждение и завершится.
Если указать начальный каталог как имя пакета, а не путь к каталогу, то discover считает, что местоположение, из которого он импортирует, и есть то, которое вы имели в виду, поэтому предупреждение не появится.
Тестовые модули и пакеты могут настраивать загрузку и обнаружение тестов с помощью протокола load_tests.
26.3.4. Организация тестового кода¶Organizing test code
Основными строительными блоками модульного тестирования являются тестовые сценарии – отдельные сценарии, которые необходимо настроить и проверить на корректность. В unittest тестовые сценарии представлены экземплярами unittest.TestCase. Чтобы создать собственные тестовые сценарии, нужно написать подклассы TestCase или использовать FunctionTestCase.
Тестовый код экземпляра TestCase должен быть полностью самодостаточным, чтобы его можно было запускать как изолированно, так и в произвольной комбинации с любым количеством других тестовых сценариев.
Простейший подкласс TestCase просто реализует тестовый метод (т.е. метод, имя которого начинается с test) для выполнения конкретного тестового кода:
import unittest
class DefaultWidgetSizeTestCase(unittest.TestCase):
def test_default_widget_size(self):
widget = Widget('The widget')
self.assertEqual(widget.size(), (50, 50))
Обратите внимание, что для проверки чего-либо используются методы assert*(), предоставляемые базовым классом TestCase. Если тест не пройден, будет возбуждено исключение, и unittest определит тестовый сценарий как неудачу. Любые другие исключения будут рассматриваться как ошибки.
Тестов может быть много, и их настройка может быть повторяющейся. К счастью, можно вынести код настройки, реализовав метод setUp(), который тестовый фреймворк будет автоматически вызывать для каждого запускаемого теста:
import unittest
class SimpleWidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget('The widget')
def test_default_widget_size(self):
self.assertEqual(self.widget.size(), (50,50),
'incorrect default size')
def test_widget_resize(self):
self.widget.resize(100,150)
self.assertEqual(self.widget.size(), (100,150),
'wrong size after resize')
Примечание
Порядок выполнения различных тестов определяется сортировкой имен тестовых методов в соответствии со встроенным порядком строк.
Если метод setUp() возбуждает исключение во время выполнения теста, фреймворк сочтёт, что в тесте произошла ошибка, и тестовый метод не будет выполнен.
Аналогично можно предоставить метод tearDown(), который выполняет очистку после выполнения тестового метода:
import unittest
class SimpleWidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget('The widget')
def tearDown(self):
self.widget.dispose()
Если setUp() выполнился успешно, tearDown() будет запущен вне зависимости от того, успешно ли выполнился тестовый метод.
Такое рабочее окружение для тестового кода называется фикстурой.
Экземпляры тестовых сценариев группируются по тестируемым функциям. unittest предоставляет для этого механизм: тестовый набор, представленный классом unittest.TestSuite. В большинстве случаев вызов unittest.main() сделает всё правильно, соберёт все тестовые сценарии модуля и выполнит их.
Однако, если требуется настроить сборку набора тестов, это можно сделать самостоятельно:
def suite():
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase('test_default_size'))
suite.addTest(WidgetTestCase('test_resize'))
return suite
Определения тестовых сценариев и тестовых наборов можно размещать в тех же модулях, что и тестируемый код (например, widget.py), но есть несколько преимуществ в размещении тестового кода в отдельном модуле, например test_widget.py:
- Тестовый модуль можно запускать автономно из командной строки.
- Тестовый код проще отделить от поставляемого кода.
- Меньше соблазна изменять тестовый код, чтобы подогнать его под тестируемый код, без веской причины.
- Тестовый код должен изменяться гораздо реже, чем тестируемый код.
- Тестируемый код проще поддаётся рефакторингу.
- Тесты для модулей, написанных на C, всё равно должны быть в отдельных модулях – так почему бы не придерживаться этого подхода?
- Если стратегия тестирования меняется, нет необходимости изменять исходный код.
26.3.5. Повторное использование старого тестового кода¶Re-using old test code
Некоторые пользователи могут обнаружить, что у них есть существующий тестовый код, который они хотели бы запускать из unittest, без преобразования каждой старой тестовой функции в подкласс TestCase.
По этой причине unittest предоставляет класс FunctionTestCase. Этот подкласс TestCase можно использовать для обёртывания существующей тестовой функции. Также можно предоставить функции настройки и очистки.
Рассмотрим следующую тестовую функцию:
def testSomething():
something = makeSomething()
assert something.name is not None
# ...
можно создать эквивалентный экземпляр тестового случая следующим образом, с опциональными методами настройки и завершения:
testcase = unittest.FunctionTestCase(testSomething,
setUp=makeSomethingDB,
tearDown=deleteSomethingDB)
Примечание
Хотя FunctionTestCase можно использовать для быстрого преобразования существующей тестовой базы в систему на основе unittest, этот подход не рекомендуется. Уделив время созданию правильных подклассов TestCase, можно значительно упростить будущий рефакторинг тестов.
В некоторых случаях существующие тесты могут быть написаны с использованием модуля doctest. Если это так, doctest предоставляет класс DocTestSuite, который может автоматически создавать экземпляры unittest.TestSuite из существующих тестов на основе doctest.
26.3.6. Пропуск тестов и ожидаемые сбои¶Skipping tests and expected failures
Новое в версии 3.1.
Unittest поддерживает пропуск отдельных тестовых методов и даже целых классов тестов. Кроме того, он поддерживает пометку теста как «ожидаемого сбоя» – теста, который сломан и будет провален, но не должен учитываться как сбой в TestResult.
Пропуск теста – это просто использование skip() декоратора или одного из его условных вариантов.
Базовый пропуск выглядит так:
class MyTestCase(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")
@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_format(self):
# Тесты, которые работают только для определённой версии библиотеки.
pass
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_windows_support(self):
# код тестирования для Windows
pass
Это вывод приведённого выше примера в подробном режиме:
test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'
test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'
test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'
----------------------------------------------------------------------
Ran 3 tests in 0.005s
OK (skipped=3)
Классы можно пропускать так же, как методы:
@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
def test_not_run(self):
pass
TestCase.setUp() также может пропустить тест. Это полезно, когда ресурс, который необходимо настроить, недоступен.
Ожидаемые сбои используют декоратор expectedFailure().
class ExpectedFailureTestCase(unittest.TestCase):
@unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")
Легко создать собственные декораторы пропуска, написав декоратор, который вызывает skip() для теста, когда его нужно пропустить. Этот декоратор пропускает тест, если переданный объект не имеет определённого атрибута:
def skipUnlessHasattr(obj, attr):
if hasattr(obj, attr):
return lambda func: func
return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))
Следующие декораторы реализуют пропуск тестов и ожидаемые сбои:
- @unittest.skip(reason)¶
Безусловно пропускает декорированный тест. Параметр reason должен описывать причину пропуска теста.
- @unittest.skipIf(condition, reason)¶
Пропустить декорированный тест, если condition истинно.
- @unittest.skipUnless(condition, reason)¶
Пропустить декорированный тест, если condition не истинно.
- @unittest.expectedFailure¶
Помечает тест как ожидаемый сбой. Если тест завершается ошибкой при запуске, он не учитывается как сбой.
- exception unittest.SkipTest(reason)¶
Это исключение возбуждается для пропуска теста.
Обычно можно использовать TestCase.skipTest() или один из декораторов пропуска, вместо прямого возбуждения этого исключения.
Пропущенные тесты не будут выполнять setUp() или tearDown(). Пропущенные классы не будут выполнять setUpClass() или tearDownClass().
26.3.7. Классы и функции¶Classes and functions
Этот раздел подробно описывает API unittest.
26.3.7.1. Тестовые случаи¶Test cases
- class unittest.TestCase(methodName='runTest')¶
Экземпляры класса TestCase представляют логические тестовые единицы в вселенной unittest. Этот класс предназначен для использования в качестве базового класса, при этом конкретные тесты реализуются конкретными подклассами. Этот класс реализует интерфейс, необходимый тестовому исполнителю для управления тестами, и методы, которые тестовый код может использовать для проверки и сообщения о различных видах ошибок.
Каждый экземпляр TestCase выполнит один базовый метод: метод с именем methodName. Однако стандартная реализация methodName по умолчанию, runTest(), будет запускать каждый метод, начинающийся с test, как отдельный тест и соответствующим образом подсчитывать успехи и неудачи. Поэтому в большинстве случаев использования TestCase не нужно ни менять methodName, ни переопределять метод runTest() по умолчанию.
Изменено в версии 3.2: TestCase может быть успешно создан без предоставления methodName. Это упрощает эксперименты с TestCase из интерактивного интерпретатора.
Экземпляры TestCase предоставляют три группы методов: одна группа используется для запуска теста, другая – реализацией теста для проверки условий и сообщения об ошибках, а также некоторые запрашивающие методы, позволяющие получать информацию о самом тесте.
Методы первой группы (выполнение теста):
- setUp()¶
Метод, вызываемый для подготовки тестового окружения (fixture). Он вызывается непосредственно перед вызовом тестового метода; любое исключение, возбуждённое этим методом, будет считаться ошибкой, а не неудачей теста. Реализация по умолчанию ничего не делает.
- tearDown()¶
Метод, вызываемый сразу после вызова тестового метода и записи результата. Он вызывается, даже если тестовый метод возбудил исключение, поэтому реализация в подклассах должна быть особенно внимательна при проверке внутреннего состояния. Любое исключение, возбуждённое этим методом, будет считаться ошибкой, а не неудачей теста. Этот метод вызывается только в случае успешного выполнения setUp(), независимо от результата тестового метода. Реализация по умолчанию ничего не делает.
- setUpClass()¶
Метод класса, вызываемый перед запуском тестов в отдельном классе. setUpClass вызывается с классом в качестве единственного аргумента и должен быть декорирован как classmethod():
@classmethod def setUpClass(cls): ...
См. Фикстуры классов и модулей для получения дополнительных сведений.
Новое в версии 3.2.
- tearDownClass()¶
Метод класса, вызываемый после завершения тестов в отдельном классе. tearDownClass вызывается с классом в качестве единственного аргумента и должен быть декорирован как classmethod():
@classmethod def tearDownClass(cls): ...
См. Фикстуры классов и модулей для получения дополнительных сведений.
Новое в версии 3.2.
- run(result=None)¶
Запускает тест, собирая результат в объект TestResult, переданный как result. Если result опущен или равен None, создаётся временный объект результата (путём вызова метода defaultTestResult()) и используется. Объект результата возвращается вызывающему run() вызывающему.
Тот же эффект можно получить, просто вызвав экземпляр TestCase.
Изменено в версии 3.3: Предыдущие версии run не возвращали результат. Не возвращал его и вызов экземпляра.
- skipTest(reason)¶
Вызов этого метода во время выполнения тестового метода или setUp() пропускает текущий тест. См. Пропуск тестов и ожидаемые сбои для получения дополнительной информации.
Новое в версии 3.1.
- debug()¶
Запускает тест без сбора результата. Это позволяет исключениям, возникшим в тесте, распространяться до вызывающего кода, и может использоваться для поддержки запуска тестов под отладчиком.
Класс TestCase предоставляет ряд методов для проверки и сообщения об ошибках, таких как:
Метод Проверяет, что Новое в assertEqual(a, b) a == b assertNotEqual(a, b) a != b assertTrue(x) bool(x) is True assertFalse(x) bool(x) is False assertIs(a, b) a is b 3.1 assertIsNot(a, b) a is not b 3.1 assertIsNone(x) x is None 3.1 assertIsNotNone(x) x is not None 3.1 assertIn(a, b) a in b 3.1 assertNotIn(a, b) a not in b 3.1 assertIsInstance(a, b) isinstance(a, b) 3.2 assertNotIsInstance(a, b) not isinstance(a, b) 3.2 Все методы assert принимают аргумент msg, который, если указан, используется в качестве сообщения об ошибке при неудаче (см. также longMessage). Обратите внимание, что аргумент-ключевое слово msg можно передавать в assertRaises(), assertRaisesRegex(), assertWarns(), assertWarnsRegex() только когда они используются как контекстный менеджер.
- assertEqual(first, second, msg=None)¶
Проверяет, что first и second равны. Если значения не равны, тест завершится с ошибкой.
Кроме того, если first и second имеют один и тот же тип и являются одним из list, tuple, dict, set, frozenset или str, или любым типом, который подкласс регистрирует с помощью addTypeEqualityFunc(), то будет вызвана функция сравнения, специфичная для этого типа, чтобы сгенерировать более полезное сообщение об ошибке по умолчанию (см. также список методов для конкретных типов).
Изменено в версии 3.1: Добавлен автоматический вызов типовой функции сравнения.
Изменено в версии 3.2: добавлена функция assertMultiLineEqual() как функция сравнения по умолчанию для строк.
- assertNotEqual(first, second, msg=None)¶
Проверяет, что first и second не равны. Если значения равны, тест завершится с ошибкой.
- assertTrue(expr, msg=None)¶
- assertFalse(expr, msg=None)¶
Проверяет, что expr истинно (или ложно).
Обратите внимание, что это эквивалентно bool(expr) is True, а не expr is True (для последнего используйте assertIs(expr, True)). Этого метода также следует избегать, когда доступны более специфичные методы (например, assertEqual(a, b) вместо assertTrue(a == b)), поскольку они предоставляют лучшее сообщение об ошибке в случае неудачи.
- assertIs(first, second, msg=None)¶
- assertIsNot(first, second, msg=None)¶
Проверяет, что first и second вычисляются (или не вычисляются) в один и тот же объект.
Новое в версии 3.1.
- assertIsNone(expr, msg=None)¶
- assertIsNotNone(expr, msg=None)¶
Проверяет, что expr равен (или не равен) None.
Новое в версии 3.1.
- assertIn(first, second, msg=None)¶
- assertNotIn(first, second, msg=None)¶
Проверяет, находится ли first в second (или не находится).
Новое в версии 3.1.
- assertIsInstance(obj, cls, msg=None)¶
- assertNotIsInstance(obj, cls, msg=None)¶
Проверяет, что obj является (или не является) экземпляром cls (который может быть классом или кортежем классов, как поддерживается функцией isinstance()). Чтобы проверить точный тип, используйте assertIs(type(obj), cls).
Новое в версии 3.2.
Также можно проверить, что исключения и предупреждения возбуждаются с помощью следующих методов:
Метод Проверяет, что Новое в assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) возбуждает exc assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) возбуждает exc и сообщение соответствует регулярному выражению r 3.1 assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) возбуждает warn 3.2 assertWarnsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) возбуждает warn и сообщение соответствует регулярному выражению r 3.2 - assertRaises(exception, callable, *args, **kwds)¶
- assertRaises(exception, msg=None)
Проверяет, что исключение возбуждается, когда callable вызывается с любыми позиционными или ключевыми аргументами, которые также передаются в assertRaises(). Тест проходит, если возбуждается исключение, является ошибкой, если возбуждается другое исключение, или завершается неудачей, если исключение не возбуждено. Чтобы перехватить любую из группы исключений, можно передать кортеж, содержащий классы исключений, как исключение.
Если переданы только аргументы исключение и, возможно, msg, возвращается менеджер контекста, чтобы проверяемый код можно было написать встроенно, а не в виде функции:
with self.assertRaises(SomeException): do_something()
При использовании в качестве менеджера контекста assertRaises() принимает дополнительный ключевой аргумент msg.
Менеджер контекста сохранит перехваченный объект исключения в своем атрибуте исключение. Это может быть полезно, если требуется выполнить дополнительные проверки возбужденного исключения:
with self.assertRaises(SomeException) as cm: do_something() the_exception = cm.exception self.assertEqual(the_exception.error_code, 3)
Изменено в версии 3.1: Добавлена возможность использовать assertRaises() в качестве менеджера контекста.
Изменено в версии 3.2: Добавлен атрибут исключение.
Изменено в версии 3.3: добавлен ключевой аргумент msg при использовании в качестве менеджера контекста.
- assertRaisesRegex(exception, regex, callable, *args, **kwds)¶
- assertRaisesRegex(exception, regex, msg=None)
Как и assertRaises(), но также проверяет, что regex соответствует строковому представлению возбужденного исключения. regex может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, подходящей для использования в re.search(). Примеры:
self.assertRaisesRegex(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
или:
with self.assertRaisesRegex(ValueError, 'literal'): int('XYZ')
Новое в версии 3.1: под именем assertRaisesRegexp.
Изменено в версии 3.2: Переименован в assertRaisesRegex().
Изменено в версии 3.3: добавлен ключевой аргумент msg при использовании в качестве менеджера контекста.
- assertWarns(warning, callable, *args, **kwds)¶
- assertWarns(warning, msg=None)
Проверяет, что предупреждение генерируется, когда callable вызывается с любыми позиционными или ключевыми аргументами, которые также передаются в assertWarns(). Тест проходит, если генерируется warning, и завершается неудачей, если нет. Любое исключение является ошибкой. Чтобы перехватить любую из группы предупреждений, можно передать кортеж, содержащий классы предупреждений, как warnings.
Если указаны только предупреждение и, возможно, msg, возвращается менеджер контекста, позволяющий писать тестируемый код inline, а не в виде функции:
with self.assertWarns(SomeWarning): do_something()
При использовании в качестве менеджера контекста assertWarns() принимает дополнительный именованный аргумент msg.
Менеджер контекста сохраняет перехваченный объект предупреждения в своём атрибуте warning, а исходную строку, вызвавшую предупреждение, в атрибутах filename и lineno. Это может быть полезно, если требуется выполнить дополнительные проверки перехваченного предупреждения:
with self.assertWarns(SomeWarning) as cm: do_something() self.assertIn('myfile.py', cm.filename) self.assertEqual(320, cm.lineno)
Этот метод работает независимо от фильтров предупреждений, установленных на момент его вызова.
Новое в версии 3.2.
Изменено в версии 3.3: добавлен ключевой аргумент msg при использовании в качестве менеджера контекста.
- assertWarnsRegex(warning, regex, callable, *args, **kwds)¶
- assertWarnsRegex(warning, regex, msg=None)
Аналогично assertWarns(), но также проверяет, что regex соответствует сообщению перехваченного предупреждения. regex может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодное для использования с re.search(). Пример:
self.assertWarnsRegex(DeprecationWarning, r'legacy_function\(\) is deprecated', legacy_function, 'XYZ')
или:
with self.assertWarnsRegex(RuntimeWarning, 'unsafe frobnicating'): frobnicate('/etc/passwd')
Новое в версии 3.2.
Изменено в версии 3.3: добавлен ключевой аргумент msg при использовании в качестве менеджера контекста.
Существуют также другие методы для выполнения более специфических проверок, например:
Метод Проверяет, что Новое в assertAlmostEqual(a, b) round(a-b, 7) == 0 assertNotAlmostEqual(a, b) round(a-b, 7) != 0 assertGreater(a, b) a > b 3.1 assertGreaterEqual(a, b) a >= b 3.1 assertLess(a, b) a < b 3.1 assertLessEqual(a, b) a <= b 3.1 assertRegex(s, r) r.search(s) 3.1 assertNotRegex(s, r) not r.search(s) 3.2 assertCountEqual(a, b) a и b содержат одни и те же элементы в одинаковом количестве, независимо от их порядка 3.2 - assertAlmostEqual(first, second, places=7, msg=None, delta=None)¶
- assertNotAlmostEqual(first, second, places=7, msg=None, delta=None)¶
Проверяет, что first и second приблизительно (или не приблизительно) равны, вычисляя разность, округляя до заданного числа десятичных знаков (по умолчанию 7) и сравнивая с нулём. Обратите внимание, что эти методы округляют значения до заданного числа десятичных знаков (т.е. как функция round()), а не до значащих цифр.
Если указан delta вместо places, то разность между first и second должна быть меньше или равна (или больше) delta.
Указание одновременно delta и places вызывает исключение TypeError.
Изменено в версии 3.2: assertAlmostEqual() автоматически считает почти равными объекты, которые сравниваются как равные. assertNotAlmostEqual() автоматически завершается неудачей, если объекты сравниваются как равные. Добавлен именованный аргумент delta.
- assertGreater(first, second, msg=None)¶
- assertGreaterEqual(first, second, msg=None)¶
- assertLess(first, second, msg=None)¶
- assertLessEqual(first, second, msg=None)¶
Проверяет, что first соответственно >, >=, < или <= по отношению к second в зависимости от имени метода. Если это не так, тест завершается ошибкой:
>>> self.assertGreaterEqual(3, 4) AssertionError: "3" unexpectedly not greater than or equal to "4"
Новое в версии 3.1.
- assertRegex(text, regex, msg=None)¶
- assertNotRegex(text, regex, msg=None)¶
Проверяет, что поиск regex соответствует (или не соответствует) text. В случае неудачи сообщение об ошибке будет содержать шаблон и text (или шаблон и часть text, которая неожиданно совпала). regex может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодной для использования в re.search().
Новое в версии 3.1: под именем assertRegexpMatches.
Изменено в версии 3.2: Метод assertRegexpMatches() переименован в assertRegex().
Новое в версии 3.2: assertNotRegex().
- assertCountEqual(first, second, msg=None)¶
Проверяет, что последовательность first содержит те же элементы, что и second, независимо от их порядка. Если нет, генерируется сообщение об ошибке с перечислением различий между последовательностями.
Дублирующиеся элементы не игнорируются при сравнении first и second. Проверяется, что каждый элемент имеет одинаковое количество в обеих последовательностях. Эквивалентно: assertEqual(Counter(list(first)), Counter(list(second))) но также работает с последовательностями нехэшируемых объектов.
Новое в версии 3.2.
Метод assertEqual() направляет проверку равенства для объектов одного типа к различным методам, специфичным для типа. Эти методы уже реализованы для большинства встроенных типов, но также можно зарегистрировать новые методы с помощью addTypeEqualityFunc():
- addTypeEqualityFunc(typeobj, function)¶
Регистрирует метод, специфичный для типа, который вызывается assertEqual() для проверки, равны ли два объекта одного и того же typeobj (не подклассы). function должен принимать два позиционных аргумента и третий именованный аргумент msg=None, как и assertEqual(). Он должен вызывать исключение self.failureException(msg) при обнаружении неравенства между первыми двумя параметрами – возможно, предоставляя полезную информацию и подробно объясняя неравенства в сообщении об ошибке.
Новое в версии 3.1.
Список методов, специфичных для типа, автоматически используемых assertEqual(), приведен в следующей таблице. Обратите внимание, что обычно нет необходимости вызывать эти методы напрямую.
Метод Используется для сравнения Новое в assertMultiLineEqual(a, b) строки 3.1 assertSequenceEqual(a, b) последовательности 3.1 assertListEqual(a, b) списки 3.1 assertTupleEqual(a, b) кортежи 3.1 assertSetEqual(a, b) множества или неизменяемые множества 3.1 assertDictEqual(a, b) словари 3.1 - assertMultiLineEqual(first, second, msg=None)¶
Проверяет, что многострочная строка first равна строке second. При неравенстве в сообщение об ошибке будет включена разница между двумя строками с выделением отличий. Этот метод используется по умолчанию при сравнении строк с assertEqual().
Новое в версии 3.1.
- assertSequenceEqual(first, second, msg=None, seq_type=None)¶
Проверяет, что две последовательности равны. Если передан seq_type, то first и second должны быть экземплярами seq_type, иначе будет вызвана ошибка. Если последовательности различаются, формируется сообщение об ошибке, показывающее разницу между ними.
Этот метод не вызывается напрямую assertEqual(), но используется для реализации assertListEqual() и assertTupleEqual().
Новое в версии 3.1.
- assertListEqual(first, second, msg=None)¶
- assertTupleEqual(first, second, msg=None)¶
Проверяет, что два списка или кортежа равны. Если нет, формируется сообщение об ошибке, показывающее только различия между ними. Ошибка также возникает, если какой-либо из параметров имеет неправильный тип. Эти методы используются по умолчанию при сравнении списков или кортежей с assertEqual().
Новое в версии 3.1.
- assertSetEqual(first, second, msg=None)¶
Проверяет, что два множества равны. Если нет, формируется сообщение об ошибке, в котором перечислены различия между множествами. Этот метод используется по умолчанию при сравнении множеств или frozensets с assertEqual().
Завершается ошибкой, если first или second не имеют метода set.difference() .
Новое в версии 3.1.
- assertDictEqual(first, second, msg=None)¶
Проверяет, что два словаря равны. Если нет, формируется сообщение об ошибке, показывающее различия в словарях. Этот метод будет использоваться по умолчанию для сравнения словарей в вызовах assertEqual().
Новое в версии 3.1.
Наконец, TestCase предоставляет следующие методы и атрибуты:
- fail(msg=None)¶
Безусловно сообщает о провале теста, с msg или None в качестве сообщения об ошибке.
- failureException¶
Этот атрибут класса задаёт исключение, возбуждаемое тестовым методом. Если тестовой платформе нужно использовать специализированное исключение, возможно, для передачи дополнительной информации, она должна создать подкласс этого исключения, чтобы корректно работать с платформой. Начальное значение этого атрибута – AssertionError.
- longMessage¶
Если установлено в True, то любое явное сообщение об ошибке, переданное в assert-методы, будет добавлено в конец стандартного сообщения об ошибке. Стандартные сообщения содержат полезную информацию о вовлечённых объектах, например, сообщение от assertEqual показывает repr двух неравных объектов. Установка этого атрибута в True позволяет иметь пользовательское сообщение об ошибке в дополнение к стандартному.
Этот атрибут по умолчанию равен True. Если установлен в False, то пользовательское сообщение, переданное методу assert, подавит стандартное сообщение.
Настройку класса можно переопределить в отдельных тестах, назначив атрибут экземпляра в True или False перед вызовом методов assert.
Новое в версии 3.1.
- maxDiff¶
Этот атрибут управляет максимальной длиной вывода различий методами assert, которые сообщают о различиях при неудаче. По умолчанию он равен 80*8 символов. Методы assert, на которые влияет этот атрибут: assertSequenceEqual() (включая все методы сравнения последовательностей, которые делегируют ему), assertDictEqual() и assertMultiLineEqual().
Установка maxDiff в None означает, что нет максимальной длины различий.
Новое в версии 3.2.
Тестовые фреймворки могут использовать следующие методы для сбора информации о тесте:
- countTestCases()¶
Возвращает количество тестов, представленных этим тестовым объектом. Для экземпляров TestCase это значение всегда равно 1.
- defaultTestResult()¶
Возвращает экземпляр класса результата теста, который следует использовать для этого класса тестового случая (если другой экземпляр результата не предоставлен методу run()).
Для экземпляров TestCase это всегда будет экземпляр TestResult; подклассы TestCase должны переопределять это при необходимости.
- id()¶
Возвращает строку, идентифицирующую конкретный тестовый случай. Обычно это полное имя тестового метода, включая имя модуля и класса.
- shortDescription()¶
Возвращает описание теста или None, если описание не было предоставлено. Реализация по умолчанию этого метода возвращает первую строку докстринга тестового метода, если она есть, или None.
Изменено в версии 3.1: В версии 3.1 это было изменено так, что имя теста добавляется в краткое описание даже при наличии докстринга. Это вызвало проблемы совместимости с расширениями unittest, и добавление имени теста было перенесено в TextTestResult в Python 3.2.
- addCleanup(function, *args, **kwargs)¶
Добавляет функцию, которая будет вызвана после tearDown() для очистки ресурсов, используемых во время теста. Функции будут вызываться в порядке, обратном порядку их добавления (LIFO). Они вызываются с теми аргументами и именованными аргументами, которые были переданы в addCleanup() при их добавлении.
Если setUp() завершается неудачей, так что tearDown() не вызывается, то все добавленные функции очистки всё равно будут вызваны.
Новое в версии 3.1.
- doCleanups()¶
Этот метод вызывается безусловно после tearDown(), или после setUp(), если setUp() возбуждает исключение.
Он отвечает за вызов всех функций очистки, добавленных с помощью addCleanup(). Если нужно, чтобы функции очистки вызывались до tearDown(), то можно вызвать doCleanups() самостоятельно.
doCleanups() извлекает методы из стека функций очистки по одному, поэтому его можно вызывать в любое время.
Новое в версии 3.1.
- class unittest.FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)¶
Этот класс реализует часть интерфейса TestCase, которая позволяет тестовому раннеру управлять тестом, но не предоставляет методы, которые тестовый код может использовать для проверки и сообщения об ошибках. Он используется для создания тестовых случаев с использованием устаревшего тестового кода, позволяя интегрировать его в тестовый фреймворк на основе unittest.
26.3.7.1.1. Устаревшие псевдонимы¶Deprecated aliases
По историческим причинам некоторые методы TestCase имели один или несколько псевдонимов, которые теперь устарели. В следующей таблице перечислены правильные имена вместе с их устаревшими псевдонимами:
Имя метода Устаревший псевдоним Устаревший псевдоним assertEqual() failUnlessEqual assertEquals assertNotEqual() failIfEqual assertNotEquals assertTrue() failUnless assert_ assertFalse() failIf assertRaises() failUnlessRaises assertAlmostEqual() failUnlessAlmostEqual assertAlmostEquals assertNotAlmostEqual() failIfAlmostEqual assertNotAlmostEquals assertRegex() assertRegexpMatches assertRaisesRegex() assertRaisesRegexp Устарело с версии 3.1: псевдонимы fail*, перечисленные во втором столбце.
Устарело с версии 3.2: псевдонимы assert*, перечисленные в третьем столбце.
Устарело с версии 3.2: assertRegexpMatches и assertRaisesRegexp были переименованы в assertRegex() и assertRaisesRegex()
26.3.7.2. Группировка тестов¶Grouping tests
- class unittest.TestSuite(tests=())¶
Этот класс представляет собой агрегацию отдельных тестовых случаев и тестовых наборов. Он предоставляет интерфейс, необходимый тестовому раннеру, чтобы его можно было запускать как любой другой тестовый случай. Запуск экземпляра TestSuite равносилен итерации по набору с запуском каждого теста по отдельности.
Если задан tests, он должен быть итерабельным объектом, содержащим отдельные тестовые примеры или другие тестовые наборы, которые будут использоваться для первоначального построения набора. Дополнительные методы предоставляются для добавления тестовых примеров и наборов в коллекцию позже.
Объекты TestSuite во многом аналогичны объектам TestCase, за исключением того, что они не реализуют тест напрямую. Вместо этого они служат для объединения тестов в группы, которые должны выполняться совместно. Есть несколько дополнительных методов для добавления тестов в экземпляры TestSuite:
- addTests(tests)¶
Добавляет все тесты из итерируемого объекта, содержащего экземпляры TestCase и TestSuite, в данный тестовый набор.
Это эквивалентно перебору tests с вызовом addTest() для каждого элемента.
TestSuite имеет общие следующие методы с TestCase:
- run(result)¶
Запускает тесты, связанные с этим набором, собирая результат в объект результата теста, переданный как result. Обратите внимание, что, в отличие от TestCase.run(), TestSuite.run() требует обязательной передачи объекта результата.
- debug()¶
Запускает тесты, связанные с этим набором, без сбора результата. Это позволяет исключениям, возбуждённым тестом, распространяться до вызывающего кода и может использоваться для поддержки запуска тестов под отладчиком.
- countTestCases()¶
Возвращает количество тестов, представленных этим тестовым объектом, включая все отдельные тесты и поднаборы.
- __iter__()¶
Тесты, сгруппированные в TestSuite, всегда извлекаются через итерацию. Подклассы могут предоставлять тесты лениво, переопределяя __iter__(). Обратите внимание, что этот метод может вызываться несколько раз для одного набора (например, при подсчёте тестов или сравнении на равенство) поэтому на всех повторных итерациях должны возвращаться одни и те же тесты.
Изменено в версии 3.2: В более ранних версиях TestSuite обращался к тестам напрямую, а не через итерацию, поэтому переопределения __iter__() было недостаточно для предоставления тестов.
В типичном использовании объекта TestSuite метод run() вызывается TestRunner, а не тестовым стендом конечного пользователя.
26.3.7.3. Загрузка и запуск тестов¶Loading and running tests
- class unittest.TestLoader¶
Класс TestLoader используется для создания тестовых наборов из классов и модулей. Обычно нет необходимости создавать экземпляр этого класса; модуль unittest предоставляет экземпляр, который может использоваться совместно как unittest.defaultTestLoader. Однако использование подкласса или экземпляра позволяет настраивать некоторые конфигурируемые свойства.
Объекты TestLoader имеют следующие методы:
- loadTestsFromTestCase(testCaseClass)¶
Возвращает набор всех тестовых случаев, содержащихся в классе testCaseClass, производном от TestCase.
- loadTestsFromModule(module)¶
Возвращает набор всех тестовых случаев, содержащихся в данном модуле. Этот метод ищет в module классы, производные от TestCase, и создает экземпляр класса для каждого тестового метода, определенного в классе.
Примечание
Хотя использование иерархии классов, производных от TestCase, может быть удобным для совместного использования фикстур и вспомогательных функций, определение тестовых методов в базовых классах, которые не предназначены для прямого инстанцирования, плохо сочетается с этим методом. Однако это может быть полезно, когда фикстуры различаются и определяются в подклассах.
Если модуль предоставляет функцию load_tests, она будет вызвана для загрузки тестов. Это позволяет модулям настраивать загрузку тестов. Это протокол load_tests.
Изменено в версии 3.2: Добавлена поддержка load_tests.
- loadTestsFromName(name, module=None)¶
Возвращает набор всех тестовых случаев по строковому спецификатору.
Спецификатор name – это «точечное имя», которое может разрешаться в модуль, класс тестового случая, тестовый метод внутри класса тестового случая, экземпляр TestSuite или вызываемый объект, возвращающий экземпляр TestCase или TestSuite. Эти проверки применяются в указанном порядке; то есть метод в классе возможного тестового случая будет распознан как «тестовый метод внутри класса тестового случая», а не как «вызываемый объект».
Например, если у вас есть модуль SampleTests, содержащий класс SampleTestCase, производный от TestCase, с тремя тестовыми методами (test_one(), test_two() и test_three()), то спецификатор 'SampleTests.SampleTestCase' приведет к тому, что этот метод вернет набор, который запустит все три тестовых метода. Использование спецификатора 'SampleTests.SampleTestCase.test_two' приведет к возврату тестового набора, который запустит только тестовый метод test_two(). Спецификатор может ссылаться на модули и пакеты, которые еще не были импортированы; они будут импортированы как побочный эффект.
Метод опционально разрешает name относительно заданного module.
- loadTestsFromNames(names, module=None)¶
Аналогично loadTestsFromName(), но принимает последовательность имён, а не одно имя. Возвращаемое значение – тестовый набор, содержащий все тесты, определённые для каждого имени.
- getTestCaseNames(testCaseClass)¶
Возвращает отсортированную последовательность имён методов, найденных в testCaseClass; и он должен быть подклассом TestCase.
- discover(start_dir, pattern='test*.py', top_level_dir=None)¶
Находит все тестовые модули, рекурсивно обходя подкаталоги, начиная с указанного каталога, и возвращает объект TestSuite, содержащий их. Будут загружены только тестовые файлы, соответствующие pattern. (Используется сопоставление с образцом в стиле shell.) Будут загружены только имена модулей, которые можно импортировать (т.е. являются допустимыми идентификаторами Python).
Все тестовые модули должны быть импортируемыми из корневого каталога проекта. Если стартовый каталог не является корневым, то корневой каталог необходимо указать отдельно.
Если импорт модуля завершается неудачей, например из-за синтаксической ошибки, то это будет записано как одна ошибка, и обнаружение продолжится.
Если имя тестового пакета (каталог с __init__.py) соответствует шаблону, то в пакете будет проверено наличие функции load_tests. Если она существует, то она будет вызвана с аргументами loader, tests, pattern.
Если функция load_tests существует, то обнаружение не выполняет рекурсивный обход пакета, load_tests отвечает за загрузку всех тестов в пакете.
Шаблон намеренно не хранится как атрибут загрузчика, чтобы пакеты могли продолжать поиск самостоятельно. top_level_dir хранится, чтобы load_tests не нужно было передавать этот аргумент в loader.discover().
start_dir может быть как точечным именем модуля, так и каталогом.
Новое в версии 3.2.
Следующие атрибуты TestLoader можно настроить либо через создание подкласса, либо присваиванием экземпляру:
- testMethodPrefix¶
Строка, задающая префикс имён методов, которые будут интерпретироваться как тестовые методы. Значение по умолчанию – 'test'.
Это влияет на getTestCaseNames() и все методы loadTestsFrom*().
- sortTestMethodsUsing¶
Функция, используемая для сравнения имён методов при сортировке в getTestCaseNames() и во всех методах loadTestsFrom*().
- class unittest.TestResult¶
Этот класс используется для сбора информации о том, какие тесты прошли успешно, а какие завершились неудачей.
Объект TestResult хранит результаты набора тестов. Классы TestCase и TestSuite обеспечивают корректную запись результатов; авторам тестов не нужно заботиться о записи результатов тестов.
Тестовые фреймворки, построенные на основе unittest, могут нуждаться в доступе к объекту TestResult, создаваемому при выполнении набора тестов для целей отчётности; экземпляр TestResult возвращается методом TestRunner.run() для этой цели.
Экземпляры TestResult имеют следующие атрибуты, которые будут интересны при просмотре результатов выполнения набора тестов:
- errors¶
Список, содержащий кортежи из двух элементов: экземпляры TestCase и строки с форматированными трассировками. Каждый кортеж представляет тест, вызвавший неожиданное исключение.
- failures¶
Список, содержащий кортежи из двух элементов: экземпляры TestCase и строки с форматированными трассировками. Каждый кортеж представляет тест, в котором ошибка была явно зафиксирована с помощью методов TestCase.assert*().
- skipped¶
Список, содержащий кортежи из двух элементов: экземпляры TestCase и строки с причиной пропуска теста.
Новое в версии 3.1.
- expectedFailures¶
Список, содержащий кортежи из двух элементов: экземпляры TestCase и строки с форматированными трассировками. Каждый кортеж представляет ожидаемую ошибку тестового случая.
- unexpectedSuccesses¶
Список, содержащий экземпляры TestCase, которые были отмечены как ожидаемые ошибки, но прошли успешно.
- testsRun¶
Общее количество запущенных на данный момент тестов.
- buffer¶
Если установлено в true, sys.stdout и sys.stderr будут буферизироваться между вызовами startTest() и stopTest(). Собранный вывод будет выводиться в настоящие sys.stdout и sys.stderr только если тест завершается неудачей или ошибкой. Любой вывод также присоединяется к сообщению об ошибке или сбое.
Новое в версии 3.2.
- failfast¶
Если установлено в true, stop() будет вызван при первой неудаче или ошибке, останавливая выполнение тестов.
Новое в версии 3.2.
- wasSuccessful()¶
Возвращает True, если все выполненные на данный момент тесты прошли, иначе возвращает False.
- stop()¶
Этот метод может быть вызван, чтобы сигнализировать, что выполняемый набор тестов должен быть прерван установкой атрибута shouldStop в True. Объекты TestRunner должны учитывать этот флаг и возвращаться без выполнения дополнительных тестов.
Например, эта возможность используется классом TextTestRunner для остановки тестового фреймворка, когда пользователь подает сигнал прерывания с клавиатуры. Интерактивные инструменты, предоставляющие реализации TestRunner, могут использовать это аналогичным образом.
Следующие методы класса TestResult используются для поддержки внутренних структур данных и могут быть расширены в подклассах для поддержки дополнительных требований к отчетности. Это особенно полезно при создании инструментов, поддерживающих интерактивную отчетность во время выполнения тестов.
- startTest(test)¶
Вызывается перед запуском тестового сценария test.
- stopTest(test)¶
Вызывается после выполнения тестового сценария test, независимо от результата.
- startTestRun(test)¶
Вызывается один раз перед выполнением любых тестов.
Новое в версии 3.1.
- stopTestRun(test)¶
Вызывается один раз после выполнения всех тестов.
Новое в версии 3.1.
- addError(test, err)¶
Вызывается, когда тестовый пример test вызывает неожиданное исключение. err – это кортеж в формате, возвращаемом sys.exc_info(): (type, value, traceback).
Реализация по умолчанию добавляет кортеж (test, formatted_err) в атрибут errors экземпляра, где formatted_err – это форматированная трассировка, полученная из err.
- addFailure(test, err)¶
Вызывается, когда тестовый пример test сигнализирует о неудаче. err – это кортеж в формате, возвращаемом sys.exc_info(): (type, value, traceback).
Реализация по умолчанию добавляет кортеж (test, formatted_err) в атрибут failures экземпляра, где formatted_err – это форматированная трассировка, полученная из err.
- addSuccess(test)¶
Вызывается, когда тестовый сценарий test завершается успешно.
Реализация по умолчанию ничего не делает.
- addSkip(test, reason)¶
Вызывается, когда тестовый сценарий test пропускается. reason – причина, которую тест указал для пропуска.
Реализация по умолчанию добавляет кортеж (test, reason) в атрибут skipped экземпляра.
- addExpectedFailure(test, err)¶
Вызывается, когда тестовый пример test завершается неудачей, но был помечен декоратором expectedFailure().
Реализация по умолчанию добавляет кортеж (test, formatted_err) в атрибут expectedFailures экземпляра, где formatted_err – это форматированная трассировка, полученная из err.
- addUnexpectedSuccess(test)¶
Вызывается, когда тестовый пример test был помечен декоратором expectedFailure(), но завершился успешно.
Реализация по умолчанию добавляет тест в атрибут unexpectedSuccesses экземпляра.
- class unittest.TextTestResult(stream, descriptions, verbosity)¶
Конкретная реализация TestResult, используемая TextTestRunner.
Новое в версии 3.2: Ранее этот класс назывался _TextTestResult. Старое имя всё ещё существует как псевдоним, но является устаревшим.
- unittest.defaultTestLoader¶
Экземпляр класса TestLoader, предназначенный для совместного использования. Если настройка TestLoader не требуется, можно использовать этот экземпляр вместо многократного создания новых.
- class unittest.TextTestRunner(stream=None, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, warnings=None)¶
Базовая реализация средства запуска тестов, которая выводит результаты в поток данных. Если stream равен None (по умолчанию), в качестве выходного потока данных используется sys.stderr. Этот класс имеет несколько настраиваемых параметров, но в целом очень прост. Графические приложения, которые запускают наборы тестов, должны предоставлять альтернативные реализации.
По умолчанию этот запускатор показывает DeprecationWarning, PendingDeprecationWarning, ResourceWarning и ImportWarning, даже если они игнорируются по умолчанию. Предупреждения об устаревании, вызванные устаревшими методами unittest, также обрабатываются особым образом: когда фильтры предупреждений установлены в 'default' или 'always', они будут появляться только один раз на модуль, чтобы избежать слишком большого количества предупреждений. Это поведение можно переопределить с помощью опций -Wd или -Wa, оставив warnings равным None.
Изменено в версии 3.2: Добавлен аргумент warnings.
Изменено в версии 3.2: Поток по умолчанию устанавливается в sys.stderr во время создания экземпляра, а не во время импорта.
- _makeResult()¶
Этот метод возвращает экземпляр TestResult, используемый run(). Он не предназначен для прямого вызова, но может быть переопределён в подклассах для предоставления собственного TestResult.
_makeResult() создаёт экземпляр класса или вызываемого объекта, переданного в конструктор TextTestRunner в качестве аргумента resultclass. По умолчанию используется TextTestResult, если resultclass не предоставлен. Класс результата создаётся со следующими аргументами:
stream, descriptions, verbosity
- unittest.main(module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None)¶
Программа командной строки, которая загружает набор тестов из module и запускает их; это в первую очередь для удобного выполнения тестовых модулей. Простейший способ использования этой функции – добавить следующую строку в конец тестового скрипта:
if __name__ == '__main__': unittest.main()
Можно запускать тесты с более подробной информацией, передав аргумент verbosity:
if __name__ == '__main__': unittest.main(verbosity=2)
Аргумент defaultTest задаёт имя теста, который будет запущен, если имена тестов не указаны в argv. Если он не указан или равен None, и имена тестов не переданы через argv, запускаются все тесты, найденные в module.
Аргумент argv может быть списком параметров, переданных программе, где первый элемент – имя программы. Если он не указан или равен None, используются значения sys.argv.
Аргумент testRunner может быть либо классом средства запуска тестов, либо уже созданным экземпляром такого класса. По умолчанию main вызывает sys.exit() с кодом возврата, указывающим на успех или неудачу выполнения тестов.
Аргумент testLoader должен быть экземпляром TestLoader, по умолчанию используется defaultTestLoader.
main поддерживает использование из интерактивного интерпретатора путём передачи аргумента exit=False. При этом результат выводится на стандартный вывод без вызова sys.exit():
>>> from unittest import main >>> main(module='test_module', exit=False)
Параметры failfast, catchbreak и buffer имеют тот же эффект, что и одноимённые параметры командной строки.
Аргумент warning задаёт фильтр предупреждений, который следует использовать во время выполнения тестов. Если он не указан, он останется равным None, если опция -W передана python, в противном случае он будет установлен в 'default'.
Вызов main на самом деле возвращает экземпляр класса TestProgram. Результат выполнения тестов сохраняется в атрибуте result.
Изменено в версии 3.1: Добавлен параметр exit.
Изменено в версии 3.2: Добавлены параметры verbosity, failfast, catchbreak, buffer и warnings.
26.3.7.3.1. Протокол load_tests¶load_tests Protocol
Новое в версии 3.2.
Модули или пакеты могут настраивать загрузку тестов из себя во время обычного запуска тестов или обнаружения тестов, реализуя функцию с именем load_tests.
Если тестовый модуль определяет load_tests, он будет вызван TestLoader.loadTestsFromModule() со следующими аргументами:
load_tests(loader, standard_tests, None)
Она должна возвращать TestSuite.
loader – это экземпляр TestLoader, который выполняет загрузку. standard_tests – это тесты, которые загружаются по умолчанию из модуля. Обычно тестовые модули хотят только добавить или удалить тесты из стандартного набора. Третий аргумент используется при загрузке пакетов в ходе обнаружения тестов.
Типичная функция load_tests, которая загружает тесты из определённого набора классов TestCase, может выглядеть так:
test_cases = (TestCase1, TestCase2, TestCase3)
def load_tests(loader, tests, pattern):
suite = TestSuite()
for test_class in test_cases:
tests = loader.loadTestsFromTestCase(test_class)
suite.addTests(tests)
return suite
Если запущено обнаружение (из командной строки или вызовом TestLoader.discover()) с шаблоном, соответствующим имени пакета, то в пакете __init__.py будет проверено наличие load_tests.
Примечание
Шаблон по умолчанию – 'test*.py'. Он соответствует всем Python-файлам, начинающимся с 'test', но не соответствует тестовым каталогам.
Шаблон вида 'test*' будет соответствовать как тестовым пакетам, так и модулям.
Если в пакете __init__.py определена load_tests, то она будет вызвана, и обнаружение в пакете не продолжится. load_tests вызывается со следующими аргументами:
load_tests(loader, standard_tests, pattern)
Она должна вернуть TestSuite, представляющий все тесты из пакета. (standard_tests будет содержать только тесты, собранные из __init__.py.)
Поскольку шаблон передаётся в load_tests, пакет может продолжить (и, возможно, изменить) обнаружение тестов. Функция load_tests, которая «ничего не делает» для тестового пакета, будет выглядеть так:
def load_tests(loader, standard_tests, pattern):
# корневой каталог, кэшированный на экземпляре загрузчика
this_dir = os.path.dirname(__file__)
package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
standard_tests.addTests(package_tests)
return standard_tests
26.3.8. Фикстуры классов и модулей¶Class and Module Fixtures
Фикстуры уровня класса и модуля реализованы в TestSuite. Когда тестовый набор встречает тест из нового класса, вызывается tearDownClass() из предыдущего класса (если он есть), а затем setUpClass() из нового класса.
Аналогично, если тест из другого модуля, отличного от предыдущего, то выполняется tearDownModule из предыдущего модуля, а затем setUpModule из нового модуля.
После выполнения всех тестов запускаются финальные tearDownClass и tearDownModule.
Обратите внимание, что общие фикстуры плохо совместимы с такими возможностями, как параллельное выполнение тестов, и нарушают изоляцию тестов. Их следует использовать с осторожностью.
Порядок тестов по умолчанию, создаваемый загрузчиками тестов unittest, группирует все тесты из одних и тех же модулей и классов вместе. Это приводит к тому, что setUpClass / setUpModule (и т.д.) вызываются ровно один раз для каждого класса и модуля. Если перемешать порядок так, чтобы тесты из разных модулей и классов оказались рядом, эти общие функции фикстур могут быть вызваны несколько раз в одном запуске тестов.
Общие фикстуры не предназначены для работы с наборами, имеющими нестандартный порядок. BaseTestSuite по-прежнему существует для фреймворков, которые не хотят поддерживать общие фикстуры.
Если в одной из общих функций фикстур возникает исключение, тест отмечается как ошибочный. Поскольку соответствующего экземпляра теста нет, создаётся объект _ErrorHolder (с тем же интерфейсом, что и у TestCase) для представления ошибки. Если используется стандартный исполнитель тестов unittest, эта деталь не имеет значения, но для авторов фреймворков она может быть актуальной.
26.3.8.1. setUpClass и tearDownClass¶setUpClass and tearDownClass
Они должны быть реализованы как методы класса:
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._connection = createExpensiveConnectionObject()
@classmethod
def tearDownClass(cls):
cls._connection.destroy()
Если нужно, чтобы setUpClass и tearDownClass в базовых классах вызывались, то их необходимо вызывать явно. Реализации в TestCase пусты.
Если во время setUpClass возникает исключение, тесты в классе не выполняются, и tearDownClass не вызывается. Пропущенные классы не будут иметь выполненных setUpClass или tearDownClass. Если исключение – это SkipTest, то класс будет отмечен как пропущенный, а не как ошибочный.
26.3.8.2. setUpModule и tearDownModule¶setUpModule and tearDownModule
Их следует реализовывать как функции:
def setUpModule():
createConnection()
def tearDownModule():
closeConnection()
Если в setUpModule возникает исключение, ни один из тестов в модуле не будет выполнен, и tearDownModule не будет вызван. Если исключение – это SkipTest, то модуль будет отмечен как пропущенный, а не как ошибочный.
26.3.9. Обработка сигналов¶Signal Handling
Новое в версии 3.2.
Параметр командной строки -c/--catch для unittest, а также параметр catchbreak для unittest.main(), обеспечивают более удобную обработку Ctrl+C во время запуска тестов. При включённом поведении перехвата Ctrl+C позволяет завершиться текущему выполняющемуся тесту, а затем выполнение тестов завершается и выводятся все результаты на данный момент. Повторное нажатие Ctrl+C вызовет KeyboardInterrupt обычным образом.
Обработчик сигнала Ctrl+C пытается оставаться совместимым с кодом или тестами, которые устанавливают свой собственный обработчик signal.SIGINT. Если вызывается обработчик unittest, но он не является установленным обработчиком signal.SIGINT, т.е. он был заменён тестируемой системой и делегирован ей, то вызывается обработчик по умолчанию. Обычно это ожидаемое поведение для кода, который заменяет установленный обработчик и делегирует ему. Для отдельных тестов, которым требуется отключить обработку Ctrl+C в unittest, можно использовать декоратор removeHandler().
Существует несколько вспомогательных функций для разработчиков фреймворков, позволяющих включить обработку control-c в тестовых фреймворках.
- unittest.installHandler()¶
Устанавливает обработчик Ctrl+C. При получении signal.SIGINT (обычно в ответ на нажатие пользователем Ctrl+C) у всех зарегистрированных результатов вызывается stop().
- unittest.registerResult(result)¶
Регистрирует объект TestResult для обработки Ctrl+C. Регистрация результата сохраняет слабую ссылку на него, поэтому это не мешает сборщику мусора удалить результат.
Регистрация объекта TestResult не имеет побочных эффектов, если обработка Ctrl+C не включена, поэтому тестовые фреймворки могут безоговорочно регистрировать все создаваемые ими результаты независимо от того, включена ли обработка.
- unittest.removeResult(result)¶
Удаляет зарегистрированный результат. После удаления результата stop() больше не будет вызываться для этого объекта результата в ответ на Ctrl+C.
- unittest.removeHandler(function=None)¶
При вызове без аргументов эта функция удаляет обработчик сочетания клавиш Control-C, если он был установлен. Эту функцию также можно использовать как декоратор теста, чтобы временно удалить обработчик на время выполнения теста:
@unittest.removeHandler def test_signal_handling(self): ...