Spec-Zone.ru › Python 3.14

unittest — Модульное тестирование

Исходный код: Lib/unittest/__init__.py

(Если вы уже знакомы с основными понятиями тестирования, можно сразу перейти к списку методов assert.)

Модуль unittest из unittest изначально был вдохновлён JUnit и похож на основные модули модульного тестирования в других языках. Он поддерживает автоматизацию тестирования, совместное использование кода настройки и завершения для тестов, объединение тестов в коллекции и независимость тестов от системы формирования отчётов.

Для этого unittest поддерживает несколько важных понятий в объектно-ориентированном стиле:

тестовая фикстура

Тестовая фикстура — это подготовка, необходимая для выполнения одного или нескольких тестов, а также связанные с ней действия по очистке. Например, это может включать создание временных или прокси-баз данных, каталогов либо запуск серверного процесса.

тестовый случай

Тестовый случай — это отдельная единица тестирования. Он проверяет конкретный отклик на определённый набор входных данных. unittest предоставляет базовый класс TestCase, который можно использовать для создания новых тестовых случаев.

набор тестов

Набор тестов — это коллекция тестовых случаев, наборов тестов или тех и других. Он используется для объединения тестов, которые следует выполнять вместе.

исполнитель тестов

Исполнитель тестов — это компонент, который управляет выполнением тестов и предоставляет пользователю результат. Исполнитель может использовать графический или текстовый интерфейс либо возвращать специальное значение, указывающее результаты выполнения тестов.

См. также

Module doctest

Другой модуль поддержки тестирования с совершенно иным подходом.

Простое тестирование в Smalltalk: использование шаблонов

Оригинальная статья Кента Бека о модулях тестирования, использующих шаблон, общий для unittest.

pytest

Сторонний модуль тестирования unittest с более простым синтаксисом для написания тестов. Например, assert func(10) == 42.

Таксономия инструментов тестирования Python

Обширный список инструментов тестирования Python, включая модули функционального тестирования и библиотеки имитационных объектов.

Список рассылки Testing in Python

Группа по интересам для обсуждения тестирования и инструментов тестирования в Python.

Скрипт Tools/unittestgui/unittestgui.py в дистрибутиве исходного кода Python — это графический инструмент для обнаружения и выполнения тестов. Он предназначен главным образом для удобства тех, кто только начинает заниматься модульным тестированием. Для рабочих сред рекомендуется запускать тесты с помощью системы непрерывной интеграции, например Buildbot, Jenkins, GitHub Actions или AppVeyor.

Базовый пример

Модуль unittest предоставляет богатый набор инструментов для создания и запуска тестов. В этом разделе показано, что для нужд большинства пользователей достаточно небольшой части этих инструментов.

Вот короткий скрипт для проверки трёх строковых методов:

import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()

Тестовый случай создаётся путём создания подкласса unittest.TestCase. Три отдельных теста определены методами, имена которых начинаются с букв test. Это соглашение об именовании позволяет исполнителю тестов определить, какие методы являются тестами.

В основе каждого теста лежит вызов assertEqual() для проверки ожидаемого результата; assertTrue() или assertFalse() для проверки условия; либо assertRaises() для проверки того, что возникает определённое исключение. Эти методы используются вместо оператора assert, чтобы исполнитель тестов мог собрать результаты всех тестов и сформировать отчёт.

Методы setUp() и tearDown() позволяют определить инструкции, которые будут выполняться до и после каждого метода тестирования. Более подробно они рассматриваются в разделе Организация тестового кода.

В заключительном блоке показан простой способ запуска тестов. unittest.main() предоставляет интерфейс командной строки для тестового скрипта. При запуске из командной строки приведённый выше скрипт выдаёт примерно такой результат:

...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

Передача параметра -v тестовому скрипту укажет unittest.main() включить более подробный вывод и выдаст следующий результат:

test_isupper (__main__.TestStringMethods.test_isupper) ... ok
test_split (__main__.TestStringMethods.test_split) ... ok
test_upper (__main__.TestStringMethods.test_upper) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

В примерах выше показаны наиболее часто используемые возможности unittest, которых достаточно для решения многих повседневных задач тестирования. В оставшейся части документации полный набор возможностей рассматривается с самого начала.

Изменено в версии 3.11: Возврат значения из метода тестирования (кроме значения по умолчанию None) теперь считается устаревшим.

Интерфейс командной строки

Модуль 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: В предыдущих версиях можно было запускать только отдельные методы тестирования, но не модули или классы.

Добавлено в версии 3.14: По умолчанию вывод окрашивается; это поведение можно управлять с помощью переменных среды.

Параметры командной строки

unittest поддерживает следующие параметры командной строки:

-b, --buffer

Во время выполнения тестов стандартные потоки вывода и ошибок буферизуются. Вывод при успешном прохождении теста отбрасывается. При сбое или ошибке теста вывод отображается обычным образом и добавляется к сообщениям о сбоях.

-c, --catch

При нажатии Control-C во время выполнения тестов программа дождётся завершения текущего теста, а затем выведет все результаты, полученные к этому моменту. Повторное нажатие Control-C вызывает обычное исключение KeyboardInterrupt.

См. раздел Обработка сигналов, где описаны функции, обеспечивающие эту возможность.

-f, --failfast

Остановить выполнение тестов при первой ошибке или сбое.

-k

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

Шаблоны, содержащие символ подстановки (*), сопоставляются с именем теста с помощью fnmatch.fnmatchcase(); в противном случае выполняется простое сопоставление с учётом регистра по подстроке.

Шаблоны сопоставляются с полным именем метода тестирования, импортированным загрузчиком тестов.

Например, -k foo соответствует foo_tests.SomeTest.test_something, bar_tests.SomeTest.test_foo, но не bar_tests.FooTest.test_something.

--locals

Показывать локальные переменные в трассировках стека.

--durations N

Показывать N самых медленных тестовых случаев (N=0 означает все).

Добавлено в версии 3.2: Добавлены параметры командной строки -b, -c и -f.

Добавлено в версии 3.5: Параметр командной строки --locals.

Добавлено в версии 3.7: Параметр командной строки -k.

Добавлено в версии 3.12: Параметр командной строки --durations.

Командную строку также можно использовать для обнаружения тестов — запуска всех тестов проекта или только их части.

Обнаружение тестов

Добавлено в версии 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.

Изменено в версии 3.4: Обнаружение тестов поддерживает пакеты пространств имён.

Изменено в версии 3.11: Поддержка пакетов пространств имён при обнаружении тестов прекращена. Она не работала начиная с Python 3.7. Начальный каталог и его подкаталоги, содержащие тесты, должны быть обычными пакетами с файлом __init__.py.

Если начальный каталог задан точечным именем пакета, родительские пакеты могут быть пакетами пространств имён.

Изменено в версии 3.14: Поддержка пакетов пространств имён в качестве начального каталога при обнаружении тестов восстановлена. Чтобы не сканировать каталоги, не относящиеся к Python, поиск тестов не выполняется в подкаталогах, не содержащих __init__.py.

Организация тестового кода

Основные строительные блоки модульного тестирования — это тестовые случаи, то есть отдельные сценарии, которые нужно подготовить и проверить на корректность. В 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 WidgetTestCase(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 WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

    def tearDown(self):
        self.widget.dispose()

Если выполнение setUp() прошло успешно, tearDown() будет вызван независимо от того, завершился ли метод тестирования успешно.

Такая рабочая среда для кода тестирования называется тестовой фикстурой. Для выполнения каждого отдельного метода тестирования создаётся новый экземпляр TestCase, служащий уникальной тестовой фикстурой. Таким образом, setUp(), tearDown() и TestCase.__init__() вызываются один раз для каждого теста.

Рекомендуется использовать реализации TestCase для группировки тестов по проверяемым ими возможностям. unittest предоставляет для этого механизм: набор тестов, представленный классом TestSuite из unittest. В большинстве случаев вызов unittest.main() сделает всё необходимое: соберёт все тестовые случаи модуля и выполнит их.

Однако если вы хотите самостоятельно настроить создание набора тестов, это можно сделать так:

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_widget_size'))
    suite.addTest(WidgetTestCase('test_widget_resize'))
    return suite

if __name__ == '__main__':
    runner = unittest.TextTestRunner()
    runner.run(suite())

Определения тестовых случаев и наборов тестов можно поместить в те же модули, что и проверяемый код (например, widget.py), но размещение тестового кода в отдельном модуле, например test_widget.py, имеет ряд преимуществ:

  • Тестовый модуль можно запускать отдельно из командной строки.
  • Тестовый код легче отделить от поставляемого кода.
  • Возникает меньше соблазна менять тестовый код, подгоняя его под проверяемый код без веской причины.
  • Тестовый код следует изменять гораздо реже, чем проверяемый им код.
  • Рефакторинг проверяемого кода становится проще.
  • Тесты для модулей, написанных на C, в любом случае должны находиться в отдельных модулях — так почему бы не придерживаться единообразия?
  • Если стратегия тестирования изменится, исходный код не потребуется менять.

Повторное использование старого тестового кода

Некоторые пользователи захотят запускать имеющийся тестовый код из 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.

Пропуск тестов и ожидаемые сбои

Добавлено в версии 3.1.

Unittest поддерживает пропуск отдельных методов тестирования и даже целых классов тестов. Кроме того, тест можно пометить как «ожидаемый сбой»: такой тест неисправен и завершится неудачей, но не должен считаться сбоем в TestResult.

Чтобы пропустить тест, достаточно использовать @skip декоратор или один из его условных вариантов, вызвать TestCase.skipTest() в методе setUp() или тестирования либо напрямую вызвать исключение SkipTest.

Простой пример пропуска теста:

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):
        # Tests that work for only a certain version of the library.
        pass

    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_windows_support(self):
        # windows specific testing code
        pass

    def test_maybe_skipped(self):
        if not external_resource_available():
            self.skipTest("external resource not available")
        # test code that depends on the external resource
        pass

При запуске приведённого выше примера в подробном режиме будет выведено следующее:

test_format (__main__.MyTestCase.test_format) ... skipped 'not supported in this library version'
test_nothing (__main__.MyTestCase.test_nothing) ... skipped 'demonstrating skipping'
test_maybe_skipped (__main__.MyTestCase.test_maybe_skipped) ... skipped 'external resource not available'
test_windows_support (__main__.MyTestCase.test_windows_support) ... skipped 'requires Windows'

----------------------------------------------------------------------
Ran 4 tests in 0.005s

OK (skipped=4)

Классы можно пропускать так же, как и методы:

@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(). Для пропускаемых модулей не вызываются setUpModule() и tearDownModule().

Различение итераций тестов с помощью под-тестов

Добавлено в версии 3.4.

Если тесты различаются лишь незначительно, например параметрами, unittest позволяет различать их внутри тела метода тестирования с помощью менеджера контекста subTest().

Например, следующий тест:

class NumbersTest(unittest.TestCase):

    def test_even(self):
        """
        Test that numbers between 0 and 5 are all even.
        """
        for i in range(0, 6):
            with self.subTest(i=i):
                self.assertEqual(i % 2, 0)

выдаст следующий результат:

======================================================================
FAIL: test_even (__main__.NumbersTest.test_even) (i=1)
Test that numbers between 0 and 5 are all even.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 11, in test_even
    self.assertEqual(i % 2, 0)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest.test_even) (i=3)
Test that numbers between 0 and 5 are all even.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 11, in test_even
    self.assertEqual(i % 2, 0)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 1 != 0

======================================================================
FAIL: test_even (__main__.NumbersTest.test_even) (i=5)
Test that numbers between 0 and 5 are all even.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 11, in test_even
    self.assertEqual(i % 2, 0)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 1 != 0

Без использования под-теста выполнение остановилось бы после первого сбоя, а диагностировать ошибку было бы сложнее, поскольку значение i не отображалось бы:

======================================================================
FAIL: test_even (__main__.NumbersTest.test_even)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

Классы и функции

В этом разделе подробно описан API unittest.

Тестовые случаи

class unittest.TestCase(methodName='runTest')

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

Каждый экземпляр TestCase выполнит один базовый метод: метод с именем methodName. В большинстве случаев использования TestCase вам не потребуется менять methodName или переопределять стандартный метод runTest().

Изменено в версии 3.2: TestCase можно успешно создать, не указывая methodName. Это упрощает эксперименты с TestCase в интерактивном интерпретаторе.

Экземпляры TestCase предоставляют три группы методов: одна группа используется для запуска теста, другая — реализацией теста для проверки условий и сообщения о сбоях, а некоторые методы запроса позволяют получить информацию о самом тесте.

Методы первой группы (запуск теста):

setUp()

Метод, вызываемый для подготовки тестового окружения. Он вызывается непосредственно перед вызовом тестового метода; любое исключение, кроме AssertionError или SkipTest, вызванное этим методом, будет считаться ошибкой, а не сбоем теста. Стандартная реализация ничего не делает.

tearDown()

Метод, вызываемый сразу после вызова тестового метода и регистрации результата. Он вызывается, даже если тестовый метод вызвал исключение, поэтому реализация в подклассах может потребовать особой осторожности при проверке внутреннего состояния. Любое исключение, кроме AssertionError или SkipTest, вызванное этим методом, будет считаться дополнительной ошибкой, а не сбоем теста (тем самым увеличивая общее число зарегистрированных ошибок). Этот метод вызывается только в том случае, если 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.

subTest(msg=None, **params)

Возвращает менеджер контекста, который выполняет заключенный в него блок кода как подтест. Аргументы msg и params необязательны и могут принимать произвольные значения; они отображаются при каждом сбое подтеста, позволяя легко его идентифицировать.

Тестовый случай может содержать любое количество объявлений подтестов, которые могут быть вложены произвольным образом.

Дополнительные сведения см. в разделе Различение итераций теста с помощью подтестов.

Добавлено в версии 3.4.

debug()

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

Класс TestCase предоставляет несколько методов assert для проверки условий и сообщения о сбоях. В следующей таблице перечислены наиболее часто используемые методы (другие методы assert см. в таблицах ниже):

Метод

Проверяет, что

Добавлен в версии

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

assertIsSubclass(a, b)

issubclass(a, b)

3.14

assertNotIsSubclass(a, b)

not issubclass(a, b)

3.14

Все методы 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(member, container, msg=None)
assertNotIn(member, container, msg=None)

Проверяет, что member содержится (или не содержится) в container.

Добавлено в версии 3.1.

assertIsInstance(obj, cls, msg=None)
assertNotIsInstance(obj, cls, msg=None)

Проверяет, что obj является (или не является) экземпляром cls (который может быть классом или кортежем классов, как поддерживается функцией isinstance()). Чтобы проверить точный тип, используйте assertIs(type(obj), cls).

Добавлено в версии 3.2.

assertIsSubclass(cls, superclass, msg=None)
assertNotIsSubclass(cls, superclass, msg=None)

Проверяет, что cls является (или не является) подклассом superclass (который может быть классом или кортежем классов, как поддерживается функцией issubclass()). Чтобы проверить точный тип, используйте assertIs(cls, superclass).

Добавлено в версии 3.14.

Также можно проверять возникновение исключений, предупреждений и сообщений журнала с помощью следующих методов:

Метод

Проверяет, что

Добавлен в версии

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

assertLogs(logger, level)

Блок with записывает сообщения в журнал для logger с минимальным уровнем level

3.4

assertNoLogs(logger, level)

The with block does not log on

logger с минимальным уровнем level

3.10

assertRaises(exception, callable, *args, **kwds)
assertRaises(exception, *, msg=None)

Проверяет, что при вызове callable с любыми позиционными или именованными аргументами, также переданными в assertRaises(), возникает исключение. Тест проходит, если возникает исключение exception, считается ошибкой, если возникает другое исключение, и завершается сбоем, если исключение не возникает. Чтобы перехватить любое исключение из группы, в качестве exception можно передать кортеж, содержащий классы исключений.

Если указаны только аргументы exception и, возможно, msg, возвращается менеджер контекста, чтобы проверяемый код можно было записать непосредственно, а не в виде функции:

with self.assertRaises(SomeException):
    do_something()

При использовании в качестве менеджера контекста assertRaises() принимает дополнительный аргумент-ключевое слово msg.

Менеджер контекста сохраняет перехваченный объект исключения в своем атрибуте exception. Это может быть полезно, если требуется выполнить дополнительные проверки возникшего исключения:

with self.assertRaises(SomeException) as cm:
    do_something()

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

Изменено в версии 3.1: Добавлена возможность использовать assertRaises() в качестве менеджера контекста.

Изменено в версии 3.2: Добавлен атрибут exception.

Изменено в версии 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 можно передать кортеж, содержащий классы предупреждений.

Если указаны только аргументы warning и, возможно, msg, возвращается менеджер контекста, чтобы проверяемый код можно было записать непосредственно, а не в виде функции:

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 при использовании в качестве менеджера контекста.

assertLogs(logger=None, level=None)

Менеджер контекста для проверки того, что в журнал logger или одного из его дочерних регистраторов записано хотя бы одно сообщение с уровнем не ниже заданного level.

Если указан, logger должен быть объектом logging.Logger или объектом str, задающим имя регистратора. По умолчанию используется корневой регистратор, который перехватит все сообщения, не заблокированные дочерним регистратором с отключенной передачей сообщений.

Если указан, level должен быть числовым уровнем журналирования или его строковым эквивалентом (например, "ERROR" или logging.ERROR). По умолчанию используется logging.INFO.

Тест проходит, если хотя бы одно сообщение, выданное внутри блока with, соответствует условиям logger и level; в противном случае тест завершается сбоем.

Объект, возвращаемый менеджером контекста, — это вспомогательный объект для записи, который отслеживает соответствующие сообщения журнала. У него есть два атрибута:

records

Список объектов logging.LogRecord для соответствующих сообщений журнала.

output

Список объектов str с отформатированным выводом соответствующих сообщений.

Пример:

with self.assertLogs('foo', level='INFO') as cm:
    logging.getLogger('foo').info('first message')
    logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
                             'ERROR:foo.bar:second message'])

Добавлено в версии 3.4.

assertNoLogs(logger=None, level=None)

Менеджер контекста для проверки того, что в журнал logger или одного из его дочерних регистраторов не записывается ни одного сообщения с уровнем не ниже заданного level.

Если указан, logger должен быть объектом logging.Logger или объектом str, задающим имя регистратора. По умолчанию используется корневой регистратор, который перехватит все сообщения.

Если указан, level должен быть числовым уровнем журналирования или его строковым эквивалентом (например, "ERROR" или logging.ERROR). По умолчанию используется logging.INFO.

В отличие от assertLogs(), менеджер контекста ничего не возвращает.

Добавлено в версии 3.10.

Также существуют другие методы для выполнения более специализированных проверок, например:

Метод

Проверяет, что

Добавлен в

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

assertStartsWith(a, b)

a.startswith(b)

3.14

assertNotStartsWith(a, b)

not a.startswith(b)

3.14

assertEndsWith(a, b)

a.endswith(b)

3.14

assertNotEndsWith(a, b)

not a.endswith(b)

3.14

assertHasAttr(a, b)

hasattr(a, b)

3.14

assertNotHasAttr(a, b)

not hasattr(a, b)

3.14

assertAlmostEqual(first, second, places=7, msg=None, delta=None)
assertNotAlmostEqual(first, second, places=7, msg=None, delta=None)

Проверяет, что first и second приблизительно (или не приблизительно) равны: вычисляет разность, округляет её до заданного числа десятичных разрядов (по умолчанию 7) и сравнивает с нулём. Обратите внимание, что эти методы округляют значения до заданного числа десятичных разрядов (то есть подобно функции round()), а не до значащих цифр.

Если вместо places передан аргумент delta, разность между 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.

assertStartsWith(s, prefix, msg=None)
assertNotStartsWith(s, prefix, msg=None)

Проверяет, начинается ли строка Unicode или байтовая строка s с prefix (или не начинается). prefix также может быть кортежем строк для проверки.

Добавлено в версии 3.14.

assertEndsWith(s, suffix, msg=None)
assertNotEndsWith(s, suffix, msg=None)

Проверяет, заканчивается ли строка Unicode или байтовая строка s на suffix (или не заканчивается). suffix также может быть кортежем строк для проверки.

Добавлено в версии 3.14.

assertHasAttr(obj, name, msg=None)
assertNotHasAttr(obj, name, msg=None)

Проверяет, есть ли у объекта obj атрибут name (или нет).

Добавлено в версии 3.14.

Метод 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)

Проверяет равенство двух множеств. Если они не равны, формируется сообщение об ошибке со списком различий между множествами. Этот метод используется по умолчанию при сравнении множеств или неизменяемых множеств с помощью assertEqual().

Проверка завершается неудачей, если у first или second нет метода difference().

Добавлено в версии 3.1.

assertDictEqual(first, second, msg=None)

Проверяет равенство двух словарей. Если они не равны, формируется сообщение об ошибке с указанием различий между словарями. Этот метод используется по умолчанию для сравнения словарей при вызове assertEqual().

Добавлено в версии 3.1.

Наконец, TestCase предоставляет следующие методы и атрибуты:

fail(msg=None)

Безусловно сообщает о неудаче теста, используя msg или None в качестве сообщения об ошибке.

failureException

Этот атрибут класса задаёт исключение, вызываемое методом теста. Если тестовой среде необходимо использовать специализированное исключение, возможно, для передачи дополнительных сведений, это исключение следует расширить подклассом, чтобы корректно взаимодействовать со средой. Начальное значение этого атрибута — AssertionError.

longMessage

Этот атрибут класса определяет поведение при передаче пользовательского сообщения об ошибке в качестве аргумента msg вызову assertXYY, завершившемуся неудачей. True — значение по умолчанию. В этом случае пользовательское сообщение добавляется в конец стандартного сообщения об ошибке. Если задано False, пользовательское сообщение заменяет стандартное.

Настройку класса можно переопределить для отдельных методов теста, присвоив атрибуту экземпляра self.longMessage значение 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, поэтому в Python 3.2 добавление имени теста было перенесено в TextTestResult.

addCleanup(function, /, *args, **kwargs)

Добавляет функцию, которая будет вызвана после tearDown() для очистки ресурсов, использованных во время теста. Функции вызываются в обратном порядке относительно порядка их добавления (LIFO). Они вызываются с аргументами и именованными аргументами, переданными в addCleanup() при их добавлении.

Если setUp() завершится неудачей, то есть tearDown() не будет вызван, все добавленные функции очистки всё равно будут вызваны.

Добавлено в версии 3.1.

enterContext(cm)

Входит в предоставленный менеджер контекста. В случае успеха также добавляет его метод __exit__() в качестве функции очистки с помощью addCleanup() и возвращает результат метода __enter__().

Добавлено в версии 3.11.

doCleanups()

Этот метод вызывается безусловно после tearDown() или после setUp(), если setUp() вызывает исключение.

Он отвечает за вызов всех функций очистки, добавленных с помощью addCleanup(). Если функции очистки необходимо вызвать до tearDown(), можно вызвать doCleanups() самостоятельно.

doCleanups() извлекает функции из стека очистки по одной, поэтому его можно вызвать в любой момент.

Добавлено в версии 3.1.

classmethod addClassCleanup(function, /, *args, **kwargs)

Добавляет функцию, которая будет вызвана после tearDownClass() для очистки ресурсов, использованных во время тестового класса. Функции вызываются в обратном порядке относительно порядка их добавления (LIFO). Они вызываются с аргументами и именованными аргументами, переданными в addClassCleanup() при их добавлении.

Если setUpClass() завершится неудачей, то есть tearDownClass() не будет вызван, все добавленные функции очистки всё равно будут вызваны.

Добавлено в версии 3.8.

classmethod enterClassContext(cm)

Входит в предоставленный менеджер контекста. В случае успеха также добавляет его метод __exit__() в качестве функции очистки с помощью addClassCleanup() и возвращает результат метода __enter__().

Добавлено в версии 3.11.

classmethod doClassCleanups()

Этот метод вызывается безусловно после tearDownClass() или после setUpClass(), если setUpClass() вызывает исключение.

Он отвечает за вызов всех функций очистки, добавленных с помощью addClassCleanup(). Если функции очистки необходимо вызвать до tearDownClass(), можно вызвать doClassCleanups() самостоятельно.

doClassCleanups() извлекает функции из стека очистки по одной, поэтому его можно вызвать в любой момент.

Добавлено в версии 3.8.

class unittest.IsolatedAsyncioTestCase(methodName='runTest')

Этот класс предоставляет API, аналогичный TestCase, и также принимает сопрограммы в качестве тестовых функций.

Добавлено в версии 3.8.

loop_factory

loop_factory, передаваемый в asyncio.Runner. Переопределите его в подклассах с помощью asyncio.EventLoop, чтобы не использовать систему политик asyncio.

Добавлено в версии 3.13.

async asyncSetUp()

Метод, вызываемый для подготовки тестовой фикстуры. Он вызывается после TestCase.setUp(). Этот метод вызывается непосредственно перед вызовом тестового метода; любое исключение, возникшее в этом методе, кроме AssertionError или SkipTest, будет считаться ошибкой, а не провалом теста. Реализация по умолчанию ничего не делает.

async asyncTearDown()

Метод, вызываемый сразу после вызова тестового метода и записи результата. Он вызывается перед tearDown(). Этот метод вызывается, даже если тестовый метод вызвал исключение, поэтому при реализации в подклассах может потребоваться особенно тщательно проверять внутреннее состояние. Любое исключение, возникшее в этом методе, кроме AssertionError или SkipTest, будет считаться дополнительной ошибкой, а не провалом теста (тем самым увеличивая общее число зарегистрированных ошибок). Этот метод вызывается только в том случае, если asyncSetUp() завершился успешно, независимо от результата тестового метода. Реализация по умолчанию ничего не делает.

addAsyncCleanup(function, /, *args, **kwargs)

Этот метод принимает сопрограмму, которую можно использовать в качестве функции очистки.

async enterAsyncContext(cm)

Войдите в предоставленный асинхронный менеджер контекста. Если операция завершилась успешно, также добавьте его метод __aexit__() в качестве функции очистки с помощью addAsyncCleanup() и верните результат метода __aenter__().

Добавлено в версии 3.11.

run(result=None)

Создаёт новый цикл событий для выполнения теста и сохраняет результат в объекте TestResult, переданном в аргументе result. Если result не указан или равен None, создаётся временный объект результата (путём вызова метода defaultTestResult()), который затем используется. Объект результата возвращается вызывающему коду run(). По завершении теста все задачи в цикле событий отменяются.

Пример, иллюстрирующий порядок действий:

from unittest import IsolatedAsyncioTestCase

events = []


class Test(IsolatedAsyncioTestCase):


    def setUp(self):
        events.append("setUp")

    async def asyncSetUp(self):
        self._async_connection = await AsyncConnection()
        events.append("asyncSetUp")

    async def test_response(self):
        events.append("test_response")
        response = await self._async_connection.get("https://example.com")
        self.assertEqual(response.status_code, 200)
        self.addAsyncCleanup(self.on_cleanup)

    def tearDown(self):
        events.append("tearDown")

    async def asyncTearDown(self):
        await self._async_connection.close()
        events.append("asyncTearDown")

    async def on_cleanup(self):
        events.append("cleanup")

if __name__ == "__main__":
    unittest.main()

После выполнения теста events будет содержать ["setUp", "asyncSetUp", "test_response", "asyncTearDown", "tearDown", "cleanup"].

class unittest.FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)

Этот класс реализует ту часть интерфейса TestCase, которая позволяет средству запуска тестов управлять выполнением теста, но не предоставляет методы, с помощью которых тестовый код может проверять и сообщать об ошибках. Этот класс используется для создания тестовых случаев на основе устаревшего тестового кода, что позволяет интегрировать его в тестовую среду на основе unittest.

Группировка тестов

class unittest.TestSuite(tests=())

Этот класс представляет собой объединение отдельных тестовых случаев и наборов тестов. Класс предоставляет интерфейс, необходимый средству запуска тестов, чтобы его можно было выполнять как любой другой тестовый случай. Выполнение экземпляра TestSuite эквивалентно итерации по набору с последовательным запуском каждого теста.

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

Объекты TestSuite во многом похожи на объекты TestCase, за исключением того, что они сами не реализуют тест. Вместо этого они используются для объединения тестов в группы, которые следует запускать вместе. Для добавления тестов в экземпляры TestSuite доступны дополнительные методы:

addTest(test)

Добавляет в набор TestCase или TestSuite.

addTests(tests)

Добавляет в этот набор тестов все тесты из итерируемого объекта, содержащего экземпляры TestCase и TestSuite.

Это эквивалентно итерации по tests с вызовом addTest() для каждого элемента.

Класс TestSuite имеет следующие методы, общие с классом TestCase:

run(result)

Запускает тесты, связанные с этим набором, и сохраняет результат в объекте результата тестирования, переданном в аргументе result. Обратите внимание: в отличие от TestCase.run(), метод TestSuite.run() требует передачи объекта результата.

debug()

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

countTestCases()

Возвращает число тестов, представленных этим объектом тестирования, включая все отдельные тесты и вложенные наборы.

__iter__()

Доступ к тестам, сгруппированным с помощью TestSuite, всегда осуществляется посредством итерации. Подклассы могут предоставлять тесты по запросу, переопределяя __iter__(). Обратите внимание: этот метод может вызываться несколько раз для одного набора (например, при подсчёте тестов или сравнении на равенство), поэтому тесты, возвращаемые при повторных итерациях до вызова TestSuite.run(), должны быть одинаковыми при каждом вызове итерации. После вызова TestSuite.run() вызывающим сторонам не следует полагаться на тесты, возвращаемые этим методом, если только вызывающая сторона не использует подкласс, переопределяющий TestSuite._removeTestAtIndex() для сохранения ссылок на тесты.

Изменено в версии 3.2: В более ранних версиях TestSuite обращался к тестам напрямую, а не посредством итерации, поэтому одного переопределения __iter__() было недостаточно для предоставления тестов.

Изменено в версии 3.4: В более ранних версиях TestSuite сохранял ссылки на каждый объект TestCase после вызова TestSuite.run(). Подклассы могут восстановить такое поведение, переопределив TestSuite._removeTestAtIndex().

При типичном использовании объекта TestSuite метод run() вызывается средством TestRunner, а не пользовательской тестовой оболочкой.

Загрузка и запуск тестов

class unittest.TestLoader

Класс TestLoader используется для создания наборов тестов из классов и модулей. Обычно создавать экземпляр этого класса не требуется; модуль unittest предоставляет экземпляр, которым можно пользоваться совместно: unittest.defaultTestLoader. Однако использование подкласса или экземпляра позволяет настраивать некоторые параметры.

Объекты TestLoader имеют следующие атрибуты:

errors

Список некритических ошибок, возникших при загрузке тестов. Загрузчик не очищает этот список. О критических ошибках вызывающий код узнаёт по исключению, которое выбрасывает соответствующий метод. О некритических ошибках также сообщается с помощью синтетического теста, который при запуске повторно вызовет исходную ошибку.

Добавлено в версии 3.5.

Объекты TestLoader имеют следующие методы:

loadTestsFromTestCase(testCaseClass)

Возвращает набор всех тестовых случаев, содержащихся в testCaseClass, производном от TestCase.

Для каждого метода, имя которого указано в getTestCaseNames(), создаётся экземпляр тестового случая. По умолчанию это имена методов, начинающиеся с test. Если getTestCaseNames() не возвращает ни одного метода, но метод runTest() реализован, вместо этого для него создаётся один тестовый случай.

loadTestsFromModule(module, *, pattern=None)

Возвращает набор всех тестовых случаев, содержащихся в указанном модуле. Метод ищет в module классы, производные от TestCase, и создаёт экземпляр класса для каждого определённого в нём метода тестирования.

Примечание

Иерархия классов, производных от TestCase, может быть удобна для совместного использования фикстур и вспомогательных функций, однако определение методов тестирования в базовых классах, которые не предназначены для создания экземпляров напрямую, плохо сочетается с этим методом. Тем не менее это может быть полезно, если фикстуры различаются и определяются в подклассах.

Если модуль предоставляет функцию load_tests, она будет вызвана для загрузки тестов. Это позволяет модулям настраивать загрузку тестов. Такой механизм называется протоколом load_tests. Аргумент pattern передаётся третьим аргументом в load_tests.

Изменено в версии 3.2: Добавлена поддержка load_tests.

Изменено в версии 3.5: Добавлена поддержка именованного аргумента только для передачи по ключевому слову pattern.

Изменено в версии 3.12: Недокументированный и неофициальный параметр use_load_tests удалён.

loadTestsFromName(name, module=None)

Возвращает набор всех тестовых случаев, заданных строковым спецификатором.

Спецификатор name — это «имя с точками», которое может обозначать модуль, класс тестового случая, метод тестирования в классе тестового случая, экземпляр TestSuite или вызываемый объект, возвращающий экземпляр TestCase или TestSuite. Проверки выполняются в указанном здесь порядке: например, метод возможного класса тестового случая будет распознан как «метод тестирования в классе тестового случая», а не как «вызываемый объект».

Например, если у вас есть модуль SampleTests, содержащий производный от TestCase класс SampleTestCase с тремя методами тестирования (test_one(), test_two() и test_three()), спецификатор 'SampleTests.SampleTestCase' заставит этот метод вернуть набор, запускающий все три метода тестирования. Спецификатор 'SampleTests.SampleTestCase.test_two' заставит его вернуть набор тестов, запускающий только метод тестирования test_two(). Спецификатор может указывать на модули и пакеты, которые ещё не были импортированы; они будут импортированы как побочный эффект.

Метод может разрешать name относительно указанного module.

Изменено в версии 3.5: Если при обходе name возникает ImportError или AttributeError, будет возвращён синтетический тест, который при запуске вызовет эту ошибку. Эти ошибки включаются в список ошибок, накопленных в self.errors.

loadTestsFromNames(names, module=None)

Аналогичен loadTestsFromName(), но принимает последовательность имён, а не одно имя. Возвращаемое значение — набор тестов, включающий все тесты, определённые для каждого имени.

getTestCaseNames(testCaseClass)

Возвращает отсортированную последовательность имён методов, найденных в testCaseClass; это должен быть подкласс TestCase.

discover(start_dir, pattern='test*.py', top_level_dir=None)

Находит все модули тестов, рекурсивно обходя подкаталоги указанного начального каталога, и возвращает объект TestSuite, содержащий их. Загружаются только файлы тестов, соответствующие шаблону pattern (используется сопоставление с шаблонами в стиле оболочки). Загружаются только имена модулей, которые можно импортировать (то есть являющиеся допустимыми идентификаторами Python).

Все модули тестов должны быть доступны для импорта из корневого каталога проекта. Если начальный каталог не является корневым каталогом, необходимо отдельно указать top_level_dir.

Если импорт модуля завершается ошибкой, например из-за синтаксической ошибки, она будет зарегистрирована как одна ошибка, а обнаружение тестов продолжится. Если сбой импорта вызван исключением SkipTest, он будет зарегистрирован как пропуск, а не как ошибка.

Если найден пакет (каталог, содержащий файл с именем __init__.py), в нём будет выполнена проверка наличия функции load_tests. Если она существует, она будет вызвана package.load_tests(loader, tests, pattern). Обнаружение тестов гарантирует, что пакет проверяется на наличие тестов только один раз за один запуск, даже если сама функция load_tests вызывает loader.discover.

Если существует load_tests, обнаружение не выполняет рекурсивный обход пакета; load_tests отвечает за загрузку всех тестов в пакете.

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

top_level_dir сохраняется внутри объекта и используется по умолчанию для всех вложенных вызовов discover(). То есть, если функция load_tests пакета вызывает loader.discover(), ей не нужно передавать этот аргумент.

start_dir может быть как именем модуля с точками, так и каталогом.

Добавлено в версии 3.2.

Изменено в версии 3.4: Модули, которые при импорте вызывают исключение SkipTest, регистрируются как пропущенные, а не как ошибки.

start_dir может быть пакетом пространства имён.

Перед импортом пути сортируются, поэтому порядок выполнения остаётся одинаковым, даже если порядок в базовой файловой системе не зависит от имён файлов.

Изменено в версии 3.5: Найденные пакеты теперь проверяются на наличие load_tests независимо от того, соответствует ли их путь шаблону pattern, поскольку имя пакета не может соответствовать шаблону по умолчанию.

Изменено в версии 3.11: start_dir не может быть пакетом пространства имён. Эта возможность не работала начиная с Python 3.7, а в Python 3.11 была официально удалена.

Изменено в версии 3.13: top_level_dir сохраняется только на время вызова discover.

Изменено в версии 3.14: start_dir снова может быть пакетом пространства имён.

Следующие атрибуты TestLoader можно настроить, создав подкласс или присвоив значения экземпляру:

testMethodPrefix

Строка, задающая префикс имён методов, которые будут считаться методами тестирования. Значение по умолчанию — 'test'.

Это влияет на getTestCaseNames() и все методы loadTestsFrom*.

sortTestMethodsUsing

Функция для сравнения имён методов при их сортировке в getTestCaseNames() и во всех методах loadTestsFrom*.

suiteClass

Вызываемый объект, создающий набор тестов из списка тестов. От результирующего объекта не требуется наличие каких-либо методов. Значение по умолчанию — класс TestSuite.

Это влияет на все методы loadTestsFrom*.

testNamePatterns

Список шаблонов имён тестов с подстановочными знаками в стиле оболочки Unix, которым должны соответствовать методы тестирования, чтобы попасть в наборы тестов (см. параметр -k).

Если этому атрибуту присвоено значение, отличное от None (значение по умолчанию), все методы тестирования, включаемые в наборы тестов, должны соответствовать одному из шаблонов в этом списке. Обратите внимание: сопоставление всегда выполняется с помощью fnmatch.fnmatchcase(), поэтому, в отличие от шаблонов, передаваемых параметру -k, простые шаблоны подстрок необходимо преобразовать с помощью подстановочных знаков *.

Это влияет на все методы loadTestsFrom*.

Добавлено в версии 3.7.

class unittest.TestResult

Этот класс используется для сбора сведений об успешно пройденных и не пройденных тестах.

Объект TestResult хранит результаты набора тестов. Классы TestCase и TestSuite обеспечивают корректную запись результатов; авторам тестов не нужно заботиться о регистрации исходов тестирования.

Средствам тестирования, построенным на основе unittest, может потребоваться доступ к объекту TestResult, созданному при запуске набора тестов, для подготовки отчётов; для этой цели метод TestRunner.run() возвращает экземпляр TestResult.

Экземпляры TestResult имеют следующие атрибуты, полезные при просмотре результатов запуска набора тестов:

errors

Список, содержащий 2-кортежи из экземпляров TestCase и строк с отформатированными трассировками стека. Каждый кортеж соответствует тесту, вызвавшему непредвиденное исключение.

failures

Список, содержащий 2-кортежи из экземпляров TestCase и строк с отформатированными трассировками стека. Каждый кортеж соответствует тесту, в котором о сбое явно сообщено с помощью методов assert*.

skipped

Список, содержащий 2-кортежи из экземпляров TestCase и строк с указанием причины пропуска теста.

Добавлено в версии 3.1.

expectedFailures

Список, содержащий 2-кортежи из экземпляров TestCase и строк с отформатированными трассировками стека. Каждый кортеж соответствует ожидаемому сбою или ошибке тестового случая.

unexpectedSuccesses

Список, содержащий экземпляры TestCase, помеченные как тесты с ожидаемым сбоем, но завершившиеся успешно.

collectedDurations

Список, содержащий 2-кортежи с именами тестовых случаев и числами с плавающей точкой, представляющими время выполнения каждого запущенного теста.

Добавлено в версии 3.12.

shouldStop

Устанавливается в True, когда выполнение тестов следует остановить вызовом stop().

testsRun

Общее число запущенных к этому моменту тестов.

buffer

Если установлено значение «истина», вывод sys.stdout и sys.stderr будет буферизоваться между вызовами startTest() и stopTest(). Собранный вывод будет отображён в настоящих потоках sys.stdout и sys.stderr только в случае сбоя или ошибки теста. Любой вывод также добавляется к сообщению о сбое или ошибке.

Добавлено в версии 3.2.

failfast

Если установлено значение «истина», при первом сбое или ошибке будет вызван stop(), и выполнение набора тестов прекратится.

Добавлено в версии 3.2.

tb_locals

Если установлено значение «истина», в трассировках стека будут отображаться локальные переменные.

Добавлено в версии 3.5.

wasSuccessful()

Возвращает True, если все запущенные к этому моменту тесты прошли успешно; в противном случае возвращает False.

Изменено в версии 3.4: Возвращает False, если среди тестов, помеченных декоратором @expectedFailure, были unexpectedSuccesses.

stop()

Этот метод можно вызвать, чтобы сообщить о необходимости прервать выполняемый набор тестов, установив атрибут shouldStop в True. Объекты TestRunner должны учитывать этот флаг и возвращаться, не запуская дополнительные тесты.

Например, этот механизм используется классом TextTestRunner, чтобы остановить тестовую среду, когда пользователь посылает сигнал прерывания с клавиатуры. Интерактивные инструменты, предоставляющие реализации TestRunner, могут использовать этот механизм аналогичным образом.

Следующие методы класса TestResult используются для поддержки внутренних структур данных; в подклассах их можно расширять для выполнения дополнительных требований к отчётности. Это особенно полезно при создании инструментов, поддерживающих интерактивную отчётность во время выполнения тестов.

startTest(test)

Вызывается, когда тестовый случай test готовится к запуску.

stopTest(test)

Вызывается после выполнения тестового случая test независимо от результата.

startTestRun()

Вызывается один раз перед выполнением любых тестов.

Добавлено в версии 3.1.

stopTestRun()

Вызывается один раз после выполнения всех тестов.

Добавлено в версии 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 экземпляра.

addSubTest(test, subtest, outcome)

Вызывается по завершении подтеста. test — тестовый случай, соответствующий методу тестирования. subtest — пользовательский экземпляр TestCase, описывающий подтест.

Если outcome равен None, подтест завершился успешно. В противном случае он завершился с исключением, а outcome — кортеж в формате, возвращаемом sys.exc_info(): (type, value, traceback).

Реализация по умолчанию ничего не делает в случае успеха и регистрирует сбои подтестов как обычные сбои.

Добавлено в версии 3.4.

addDuration(test, elapsed)

Вызывается по завершении тестового случая. elapsed — время в секундах, включая выполнение функций очистки.

Добавлено в версии 3.12.

class unittest.TextTestResult(stream, descriptions, verbosity, *, durations=None)

Конкретная реализация TestResult, используемая классом TextTestRunner. Для обеспечения совместимости при изменении интерфейса подклассы должны принимать **kwargs.

Добавлено в версии 3.2.

Изменено в версии 3.12: Добавлен именованный параметр durations.

unittest.defaultTestLoader

Экземпляр класса TestLoader, предназначенный для совместного использования. Если настройка TestLoader не требуется, этот экземпляр можно использовать вместо многократного создания новых экземпляров.

class unittest.TextTestRunner(stream=None, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, warnings=None, *, tb_locals=False, durations=None)

Базовая реализация средства запуска тестов, которая выводит результаты в поток. Если stream — None, значение по умолчанию, в качестве выходного потока используется sys.stderr. У этого класса есть несколько настраиваемых параметров, но в целом он очень прост. Графические приложения, запускающие наборы тестов, должны предоставлять альтернативные реализации. Такие реализации должны принимать **kwargs, поскольку интерфейс создания средств запуска меняется при добавлении новых возможностей в unittest.

По умолчанию это средство запуска отображает DeprecationWarning, PendingDeprecationWarning, ResourceWarning и ImportWarning, даже если они по умолчанию игнорируются. Это поведение можно переопределить с помощью параметров -Wd или -Wa Python (см. Управление предупреждениями), оставив warnings равным None.

Изменено в версии 3.2: Добавлен параметр warnings.

Изменено в версии 3.2: Поток по умолчанию теперь задаётся как sys.stderr во время создания экземпляра, а не во время импорта.

Изменено в версии 3.5: Добавлен параметр tb_locals.

Изменено в версии 3.12: Добавлен параметр durations.

_makeResult()

Этот метод возвращает экземпляр TestResult, используемый методом run(). Он не предназначен для прямого вызова, но может быть переопределён в подклассах для предоставления пользовательского TestResult.

Метод _makeResult() создаёт экземпляр класса или вызываемого объекта, переданного в конструктор TextTestRunner в качестве аргумента resultclass. Если resultclass не указан, по умолчанию используется TextTestResult. Класс результата создаётся со следующими аргументами:

stream, descriptions, verbosity
run(test)

Этот метод является основным открытым интерфейсом средства TextTestRunner. Метод принимает экземпляр TestSuite или TestCase. Объект TestResult создаётся вызовом _makeResult(), после чего выполняются тесты и результаты выводятся в stdout.

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() с кодом завершения, который указывает на успешное выполнение (0) или сбой (1) запущенных тестов. Код завершения 5 означает, что тесты не запускались или были пропущены.

Аргумент testLoader должен быть экземпляром TestLoader; по умолчанию используется defaultTestLoader.

Функцию main можно использовать в интерактивном интерпретаторе, передав аргумент exit=False. В этом случае результат выводится в стандартный вывод, а sys.exit() не вызывается:

>>> from unittest import main
>>> main(module='test_module', exit=False)

Параметры failfast, catchbreak и buffer действуют так же, как одноимённые параметры командной строки.

Аргумент warnings задаёт фильтр предупреждений, который следует использовать во время выполнения тестов. Если он не указан, фильтр останется равным None, если при запуске python передан параметр -W (см. Управление предупреждениями); в противном случае ему будет присвоено значение 'default'.

Вызов main возвращает объект с атрибутом result, содержащим результат выполнения тестов в виде объекта unittest.TestResult.

Изменено в версии 3.1: Добавлен параметр exit.

Изменено в версии 3.2: Добавлены параметры verbosity, failfast, catchbreak, buffer и warnings.

Изменено в версии 3.4: Параметр defaultTest теперь также принимает итерируемый объект с именами тестов.

Протокол load_tests

Добавлено в версии 3.2.

Модули или пакеты могут настраивать способ загрузки тестов при обычном запуске или обнаружении тестов, реализовав функцию с именем load_tests.

Если модуль с тестами определяет load_tests, метод TestLoader.loadTestsFromModule() вызовет её со следующими аргументами:

load_tests(loader, standard_tests, pattern)

где pattern напрямую передаётся из loadTestsFromModule. По умолчанию ему присваивается значение 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. Если такой функции нет, поиск продолжится в пакете, как если бы это был обычный каталог. В противном случае обнаружение тестов пакета будет поручено функции load_tests, которая вызывается со следующими аргументами:

load_tests(loader, standard_tests, pattern)

Она должна возвращать объект TestSuite, представляющий все тесты пакета. (standard_tests будет содержать только тесты, собранные из __init__.py.)

Поскольку шаблон передаётся в load_tests, пакет может продолжить обнаружение тестов (и при необходимости изменить его). Функция load_tests для пакета с тестами, которая ничего не делает, может выглядеть так:

def load_tests(loader, standard_tests, pattern):
    # top level directory cached on loader instance
    this_dir = os.path.dirname(__file__)
    package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
    standard_tests.addTests(package_tests)
    return standard_tests

Изменено в версии 3.5: При обнаружении тестов имена пакетов больше не проверяются на соответствие pattern, поскольку имена пакетов не могут соответствовать шаблону по умолчанию.

Фикстуры классов и модулей

Фикстуры уровня класса и модуля реализованы в TestSuite. Когда набор тестов встречает тест из нового класса, вызывается tearDownClass() предыдущего класса (если он был), а затем setUpClass() нового класса.

Аналогично, если тест относится к модулю, отличному от модуля предыдущего теста, сначала выполняется tearDownModule предыдущего модуля, а затем setUpModule нового модуля.

После выполнения всех тестов запускаются заключительные tearDownClass и tearDownModule.

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

По умолчанию средства загрузки тестов unittest группируют все тесты из одних и тех же модулей и классов. Благодаря этому setUpClass / setUpModule (и т. д.) вызываются ровно один раз для каждого класса и модуля. Если изменить порядок так, чтобы тесты из разных модулей и классов шли вперемешку, эти функции общих фикстур могут вызываться несколько раз за один запуск тестов.

Общие фикстуры не предназначены для наборов с нестандартным порядком выполнения. Для фреймворков, которые не хотят поддерживать общие фикстуры, существует BaseTestSuite.

Если во время выполнения одной из функций общих фикстур возникает исключение, тест помечается как завершившийся ошибкой. Поскольку соответствующего экземпляра теста нет, для представления ошибки создаётся объект _ErrorHolder (с тем же интерфейсом, что и у TestCase). Если вы используете стандартное средство запуска тестов unittest, эта подробность не имеет значения, но для автора фреймворка она может быть важна.

setUpClass и 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, класс будет отмечен как пропущенный, а не как завершившийся ошибкой.

setUpModule и tearDownModule

Эти функции должны быть реализованы как обычные функции:

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

Если во время выполнения setUpModule возникает исключение, тесты модуля не запускаются, а tearDownModule не выполняется. Если исключение является исключением SkipTest, модуль будет отмечен как пропущенный, а не как завершившийся ошибкой.

Чтобы добавить код очистки, который должен выполняться даже в случае исключения, используйте addModuleCleanup:

unittest.addModuleCleanup(function, /, *args, **kwargs)

Добавляет функцию, которая будет вызвана после tearDownModule() для очистки ресурсов, использованных во время тестового класса. Функции вызываются в порядке, обратном порядку их добавления (последним добавлен — первым вызван (LIFO)). При вызове им передаются все позиционные и именованные аргументы, переданные в addModuleCleanup() при добавлении.

Если выполнение setUpModule() завершается ошибкой, то есть tearDownModule() не вызывается, все добавленные функции очистки всё равно будут вызваны.

Добавлено в версии 3.8.

unittest.enterModuleContext(cm)

Входит в переданный менеджер контекста. Если вход выполнен успешно, метод __exit__() также добавляется как функция очистки с помощью addModuleCleanup(), а функция возвращает результат метода __enter__().

Добавлено в версии 3.11.

unittest.doModuleCleanups()

Эта функция безусловно вызывается после tearDownModule() или после setUpModule(), если setUpModule() вызывает исключение.

Она отвечает за вызов всех функций очистки, добавленных с помощью addModuleCleanup(). Если функции очистки нужно вызвать до tearDownModule(), можно самостоятельно вызвать doModuleCleanups().

Функция doModuleCleanups() извлекает функции из стека очистки по одной, поэтому её можно вызвать в любое время.

Добавлено в версии 3.8.

Обработка сигналов

Добавлено в версии 3.2.

Параметр командной строки -c/--catch для unittest вместе с параметром catchbreak функции unittest.main() обеспечивают более удобную обработку нажатия Ctrl+C во время выполнения тестов. Если включено поведение catch break, Ctrl+C позволит текущему тесту завершиться, после чего выполнение тестов прекратится и будут выведены все имеющиеся результаты. Повторное нажатие Ctrl+C приведёт к обычному возникновению исключения KeyboardInterrupt.

Обработчик сигнала Ctrl+C старается сохранять совместимость с кодом или тестами, которые устанавливают собственный обработчик signal.SIGINT. Если вызывается обработчик unittest, но он не является установленным обработчиком signal.SIGINT (то есть был заменён тестируемой системой, которая передала ему управление), вызывается обработчик по умолчанию. Обычно именно такого поведения ожидает код, который заменяет установленный обработчик и передаёт ему управление. Для отдельных тестов, которым требуется отключить обработку Ctrl+C unittest, можно использовать декоратор removeHandler().

Для авторов фреймворков предусмотрено несколько вспомогательных функций, позволяющих включить обработку Ctrl+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)

Если вызвать эту функцию без аргументов, она удалит обработчик Ctrl+C, если он был установлен. Функцию также можно использовать как декоратор теста, чтобы временно удалить обработчик на время выполнения теста:

@unittest.removeHandler
def test_signal_handling(self):
    ...

© 2001 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/library/unittest.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API