unittest — Платформа модульного тестирования

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


(Если вы уже знакомы с основными концепциями тестирования, возможно, вы захотите перейти к the list of assert methods.)

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

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

испытательное приспособление

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

тестовый пример

test case - это отдельная единица тестирования. Она проверяет конкретный ответ на определенный набор входных данных. unittest предоставляет базовый класс TestCase, который может использоваться для создания новых тестовых примеров.

набор тестов

test suite - это набор тестовых примеров, наборов тестов или того и другого. Он используется для объединения тестов, которые должны выполняться вместе.

испытательный стенд

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

См.также

Модуль doctest

Еще один модуль поддержки тестирования с совершенно другим дизайном.

Simple Smalltalk Testing: With Patterns

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

pytest

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

The Python Testing Tools Taxonomy

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

Testing in Python Mailing List

Группа по интересам для обсуждения тестирования и инструментов тестирования на 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 функции, которых достаточно для удовлетворения многих повседневных потребностей в тестировании. В оставшейся части документации рассматривается полный набор функций из first principles.

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

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

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

-b, --buffer

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

-c, --catch

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

Функции, обеспечивающие эту функциональность, приведены в разделе Signal Handling.

-f, --failfast

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

-k

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

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

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

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

--locals

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

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

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

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

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

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

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

Unittest поддерживает простое обнаружение тестов. Для обеспечения совместимости с test discovery все тестовые файлы должны быть modules или packages, которые можно импортировать из каталога верхнего уровня проекта (это означает, что их имена файлов должны быть допустимыми identifiers).

Обнаружение тестов реализовано в 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. Указанное вами имя пакета будет импортировано, а его местоположение в файловой системе будет использоваться в качестве начального каталога.

Осторожно

Test discovery загружает тесты, импортируя их. Как только test discovery найдет все тестовые файлы из указанного вами начального каталога, он преобразует пути в имена пакетов для импорта. Например, foo/bar/baz.py будет импортирован как foo.bar.baz.

Если у вас есть пакет, установленный глобально, и вы пытаетесь выполнить тестовое обнаружение в другой копии пакета, то импорт может произойти не из того места. Если это произойдет, test discovery предупредит вас и завершит работу.

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

Тестовые модули и пакеты могут настраивать загрузку и обнаружение тестов с помощью load_tests protocol.

Изменено в версии 3.4: Обнаружение тестов поддерживает namespace packages для начального каталога. Обратите внимание, что вам также необходимо указать каталог верхнего уровня (например, python -m unittest discover -s root/namespace -t root).

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

Каталоги, содержащие start directory, по-прежнему могут быть пакетами пространства имен. В этом случае вам нужно указать start directory в качестве имени пакета, обозначенного пунктиром, и явно указать целевой каталог. Например:

# proj/  <-- current directory
#   namespace/
#     mypkg/
#       __init__.py
#       test_mypkg.py

python -m unittest discover -s namespace.mypkg -t .

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

Основными компонентами модульного тестирования являются test cases — отдельные сценарии, которые необходимо настроить и проверить на корректность. В 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* methods, предоставляемых базовым классом TestCase. Если тест не пройден, будет создано исключение с пояснительным сообщением, и unittest идентифицирует тестовый пример как failure. Любые другие исключения будут рассматриваться как errors.

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

Такая рабочая среда для тестируемого кода называется test fixture. Новый экземпляр тестового примера создается как уникальный тестовый инструментарий, используемый для выполнения каждого отдельного метода тестирования. Таким образом, setUp(), tearDown(), и __init__() будут вызываться один раз за тест.

Рекомендуется использовать реализации тестовых наборов для группировки тестов в соответствии с функциями, которые они тестируют. unittest предоставляет механизм для этого: test suite, представленный unittest классом TestSuite. В большинстве случаев вызов 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() decorator или один из его условных вариантов, вызвать 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)

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

@unittest.skipIf(condition, reason)

Пропустите оформленный тест, если условие истинно.

@unittest.skipUnless(condition, reason)

Пропустите оформленный тест, если только условие не является истинным.

@unittest.expectedFailure

Отметьте тест как ожидаемый сбой или ошибку. Если тест завершился неудачно или возникли ошибки в самой тестовой функции (а не в одном из методов test fixture), это будет считаться успешным. Если тест прошел успешно, это будет считаться неудачным.

exception unittest.SkipTest(reason)

Это исключение создается для пропуска теста.

Обычно вы можете использовать TestCase.skipTest() или один из пропускающих декораторов вместо того, чтобы вызывать это напрямую.

Пропущенные тесты не будут содержать setUp() или tearDown(). Пропущенные классы не будут содержать setUpClass() или tearDownClass(). Пропущенные модули не будут запускаться setUpModule() или tearDownModule().

Различение итераций тестирования с использованием субтестов

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

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

Смотрите Class and Module Fixtures для получения более подробной информации.

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

tearDownClass()

Метод класса, вызываемый после выполнения тестов в отдельном классе. tearDownClass вызывается с использованием класса в качестве единственного аргумента и должен быть оформлен как classmethod():

@classmethod
def tearDownClass(cls):
    ...

Смотрите Class and Module Fixtures для получения более подробной информации.

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

run(result=None)

Запустите тест, собирая результат в объект TestResult, передаваемый как result. Если значение result опущено или None, создается временный объект result (путем вызова метода 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

Все методы assert принимают аргумент msg, который, если указан, используется в качестве сообщения об ошибке при сбое (смотрите также longMessage). Обратите внимание, что аргумент ключевого слова msg может быть передан в assertRaises(), assertRaisesRegex(), assertWarns(), assertWarnsRegex() только в том случае, если они используются в качестве контекстного менеджера.

assertEqual(first, second, msg=None)

Проверьте, равны ли значения first и second. Если значения не совпадают, тест не будет выполнен.

Кроме того, если first и second имеют один и тот же тип и относятся к list, tuple, dict, set, frozenset или str или любому другому типу, который подкласс регистрирует с помощью addTypeEqualityFunc(), будет вызвана функция равенства, зависящая от типа, чтобы сгенерировать более полезное сообщение об ошибке по умолчанию (смотрите также list of type-specific methods).

Изменено в версии 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)

Проверьте, являются ли первый и второй одним и тем же объектом (или нет).

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

assertIsNone(expr, msg=None)
assertIsNotNone(expr, msg=None)

Проверьте, является ли expr значением (или нет) None.

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

assertIn(member, container, msg=None)
assertNotIn(member, container, msg=None)

Проверьте, находится ли элемент в контейнере (или его нет).

Добавлено в версии 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) вызывает предупреждение

3.2

assertWarnsRegex(warn, r, fun, *args, **kwds)

fun(*args, **kwds) выдает warn, и сообщение соответствует регулярному выражению r

3.2

assertLogs(logger, level)

Блок with регистрирует логгер с минимальным уровнем

3.4

assertNoLogs(logger, level)

Блок with не выполняет вход в систему

регистратор с минимальным уровнем

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

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

Если указано, то 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

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

Проверьте, что первый и второй приблизительно (или не приблизительно) равны, вычислив разницу, округлив ее до заданного числа десятичных знаков (по умолчанию 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 может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, подходящее для использования re.search().

Добавлено в версии 3.1: Добавлен под названием assertRegexpMatches.

Изменено в версии 3.2: Метод assertRegexpMatches() был переименован в assertRegex().

Добавлено в версии 3.2: assertNotRegex().

Добавлено в версии 3.5: Имя assertNotRegexpMatches является устаревшим псевдонимом для assertNotRegex().

assertCountEqual(first, second, msg=None)

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

Повторяющиеся элементы не игнорируются при сравнении первого и второго. Это проверяет, имеет ли каждый элемент одинаковое количество в обеих последовательностях. Эквивалентно: assertEqual(Counter(list(first)), Counter(list(second))), но также работает с последовательностями объектов, которые невозможно удалить.

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

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

addTypeEqualityFunc(typeobj, function)

Регистрирует специфичный для типа метод, вызываемый assertEqual(), чтобы проверить, являются ли два объекта абсолютно одинакового typeobj (не подкласса) одинаковыми. функция должна принимать два позиционных аргумента и третий аргумент ключевого слова 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().

Завершается ошибкой, если ни в одном из первых или вторых методов нет set.difference().

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

assertDictEqual(first, second, msg=None)

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

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

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

fail(msg=None)

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

failureException

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

longMessage

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

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

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

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

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

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

enterContext(cm)

Введите указанный context manager. В случае успеха также добавьте его метод __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)

Введите указанный context manager. В случае успеха также добавьте его метод __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.

coroutine asyncSetUp()

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

coroutine asyncTearDown()

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

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

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

coroutine enterAsyncContext(cm)

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

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

run(result=None)

Настраивает новый цикл обработки событий для запуска теста, собирая результат в объект TestResult, передаваемый как result. Если значение result опущено или None, создается временный объект result (путем вызова метода defaultTestResult()) и используется. Объект result возвращается вызывающей стороне 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.

Устаревшие псевдонимы

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

Название метода

Устаревший псевдоним

Устаревший псевдоним

assertEqual()

Равный без сбоев

Равные утверждения

assertNotEqual()

Неудача, равная

Assertне имеет равных значений

assertTrue()

Безотказный

утверждать_

assertFalse()

Неудача, если

assertRaises()

Безотказные подъемы

assertAlmostEqual()

Безотказный, максимально равный

Утверждайте наибольшие значения

assertNotAlmostEqual()

Сбой максимально возможный

Утверждайте, что нет наибольших значений

assertRegex()

Assertregexpматчи

assertNotRegex()

Assertnotregexp соответствует

assertRaisesRegex()

assertRaisesRegexp Утверждение

Не рекомендуется, начиная с версии 3.1: Псевдонимы fail*, перечисленные во втором столбце, устарели.

Не рекомендуется, начиная с версии 3.2: Псевдонимы assert*, перечисленные в третьем столбце, устарели.

Не рекомендуется, начиная с версии 3.2: assertRegexpMatches и assertRaisesRegexp были переименованы в assertRegex() и assertRaisesRegex().

Не рекомендуется, начиная с версии 3.5: Имя assertNotRegexpMatches устарело в пользу assertNotRegex().

Групповые тесты

class unittest.TestSuite(tests=())

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

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

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

addTest(test)

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

addTests(tests)

Добавьте в этот набор тестов все тесты из итерационного набора экземпляров TestCase и TestSuite.

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

TestSuite использует следующие методы совместно с TestCase:

run(result)

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

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)

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

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

loadTestsFromModule(module, pattern=None)

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

Примечание

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

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

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

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

loadTestsFromName(name, module=None)

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

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

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

Метод необязательно разрешает имя относительно данного модуля.

Изменено в версии 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, содержащий их. Будут загружены только те тестовые файлы, которые соответствуют шаблону. (Используя сопоставление с шаблоном в стиле оболочки). Будут загружены только те имена модулей, которые можно импортировать (т.е. которые являются действительными идентификаторами Python).

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

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

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

Если load_tests существует, то discovery не выполняет рекурсию в пакет, load_tests отвечает за загрузку всех тестов в пакет.

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

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

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

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

Изменено в версии 3.4: start_dir может быть namespace packages.

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

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

Изменено в версии 3.11: start_dir не может быть namespace packages. Он был нарушен с тех пор, как Python 3.7 и Python 3.11 официально удалили его.

Следующие атрибуты 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 объект, возникших в результате выполнения набора тестов для целей отчетности; а TestResult экземпляр возвращается TestRunner.run() метод для этой цели.

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

errors

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

failures

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

skipped

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

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

expectedFailures

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

unexpectedSuccesses

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

shouldStop

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

testsRun

Общее количество проведенных на данный момент тестов.

buffer

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

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

failfast

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

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

tb_locals

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

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

wasSuccessful()

Возвращает True, если все тесты, выполненные до сих пор, пройдены, в противном случае возвращает False.

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

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. причина - это причина, по которой тест был пропущен.

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

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

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

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

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, *, tb_locals=False)

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

По умолчанию в этом бегуне отображаются DeprecationWarning, PendingDeprecationWarning, ResourceWarning и ImportWarning, даже если они равны ignored by default. Предупреждения об устаревании, вызванные deprecated unittest methods, также имеют специальный регистр, и если фильтры предупреждений 'default' или 'always', они будут отображаться только один раз для каждого модуля, чтобы избежать слишком большого количества предупреждающих сообщений. Это поведение можно переопределить, используя опции Python -Wd или -Wa (см. Warning control) и оставив предупреждения в None.

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

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

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

_makeResult()

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

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

stream, descriptions, verbosity
run(test)

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

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 может быть либо класс 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 имеют тот же эффект, что и одноименные command-line options.

Аргумент warnings указывает значение warning filter, которое следует использовать при выполнении тестов. Если это значение не указано, оно останется None, если для параметра -W будет передано значение python (см. Warning control), в противном случае оно будет равно 'default'.

Вызов main фактически возвращает экземпляр класса TestProgram. При этом сохраняется результат выполнения тестов в виде атрибута result.

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

Изменено в версии 3.2: Были добавлены параметры детализация, устойчивость к сбоям, перехват, буфер и предупреждения.

Изменено в версии 3.4: Параметр defaultTest был изменен, чтобы также принимать повторяющиеся имена тестов.

протокол load_tests

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

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

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

load_tests(loader, standard_tests, 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: Discovery больше не проверяет имена пакетов на соответствие шаблону из-за невозможности соответствия имен пакетов шаблону по умолчанию.

Классовые и модульные приспособления

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

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

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

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

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

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

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

Класс настройки и класс демонтажа

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

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

Модуль настройки и модуль демонтажа

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

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

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

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

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

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

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

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

classmethod unittest.enterModuleContext(cm)

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

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

unittest.doModuleCleanups()

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

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

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

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

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

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

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

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

Для авторов фреймворка существует несколько полезных функций, позволяющих включить функциональность управления c в тестовых фреймворках.

unittest.installHandler()

Установите средство управления. При получении signal.SIGINT (обычно в ответ на нажатие пользователем клавиши control-c) для всех зарегистрированных результатов вызывается stop().

unittest.registerResult(result)

Зарегистрируйте объект TestResult для обработки на языке control-c. При регистрации результата сохраняется слабая ссылка на него, поэтому это не предотвращает сборку мусора в результате.

Регистрация объекта TestResult не имеет побочных эффектов, если не включена обработка control-c, поэтому тестовые платформы могут безоговорочно регистрировать все результаты, которые они создают, независимо от того, включена обработка или нет.

unittest.removeResult(result)

Удалите зарегистрированный результат. Как только результат будет удален, stop() больше не будет вызываться для этого объекта result в ответ на команду control-c.

unittest.removeHandler(function=None)

При вызове без аргументов эта функция удаляет обработчик control-c, если он был установлен. Эту функцию также можно использовать в качестве декоратора теста для временного удаления обработчика во время выполнения теста:

@unittest.removeHandler
def test_signal_handling(self):
    ...
Вернуться на верх