Spec-Zone.ru › Python 3.6

unittest — Фреймворк для модульного тестирования

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

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

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

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

тестовая настройка

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

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

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

тестовый набор

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

запускатель тестов

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

См. также

Module doctest

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

Simple Smalltalk Testing: With Patterns

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

Nose и pytest

Фреймворки тестирования сторонних разработчиков с более лёгким синтаксисом для написания тестов. Например, assert func(10) == 42.

Классификация инструментов тестирования Python

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

Список рассылки по тестированию в Python

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

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

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

Модуль 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) ... ok
test_split (__main__.TestStringMethods) ... ok
test_upper (__main__.TestStringMethods) ... ok

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

OK

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

26.4.2. Командная строка

Модуль unittest можно использовать из командной строки для запуска тестов из модулей, классов или даже отдельных методов тестов:

python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

Вы можете передать список с любой комбинацией имён модулей и полных имён классов или методов.

Тестовые модули также могут быть указаны путём файла:

python -m unittest tests/test_something.py

Это позволяет использовать автодополнение имён файлов в оболочке для указания тестового модуля. Указанный файл по-прежнему должен быть импортируем как модуль. Путь преобразуется в имя модуля путём удаления ‘.py’ и преобразования разделителей путей в ‘.’. Если вы хотите выполнить файл теста, который не импортируется как модуль, вы должны выполнить файл напрямую.

Вы можете запустить тесты с большей детализацией (более высоким уровнем подробности), передав флаг -v:

python -m unittest -v test_module

При выполнении без аргументов запускается Обнаружение тестов:

python -m unittest

Для получения списка всех опций командной строки:

python -m unittest -h

Изменено в версии 3.2: В предыдущих версиях можно было запускать только отдельные методы тестов, а не модули или классы.

26.4.2.1. Опции командной строки

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

-b, --buffer

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

-c, --catch

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

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

-f, --failfast

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

--locals

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

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

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

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

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

Новое в версии 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.

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

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

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

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

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

Основными строительными блоками модульного тестирования являются тестовые случаи — отдельные сценарии, которые должны быть настроены и проверены на корректность. В 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() и __init__() будут вызваны один раз на тест.

Рекомендуется использовать реализации TestCase для группировки тестов по тестируемым функциям. unittest предоставляет механизм для этого: тестовый набор, представленный классом unittest’s 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, должны быть в отдельных модулях, так что почему бы не быть последовательными?
  • Если стратегия тестирования меняется, нет необходимости изменять исходный код.

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

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

По этой причине unittest предоставляет класс FunctionTestCase. Этот подкласс TestCase может быть использован для обертывания существующей тестовой функции. Также можно предоставить функции настройки и разборки.

Учитывая следующую тестовую функцию:

def testSomething():
    something = makeSomething()
    assert something.name is not None
    # ...

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

testcase = unittest.FunctionTestCase(testSomething,
                                     setUp=makeSomethingDB,
                                     tearDown=deleteSomethingDB)

Примечание

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

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

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

Новое в версии 3.1.

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

Пропуск теста осуществляется с помощью декоратора skip() или одного из его условных вариантов.

Базовый пропуск выглядит так:

class MyTestCase(unittest.TestCase):

    @unittest.skip("demonstrating skipping")
    def test_nothing(self):
        self.fail("shouldn't happen")

    @unittest.skipIf(mylib.__version__ < (1, 3),
                     "not supported in this library version")
    def test_format(self):
        # 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

Это вывод выполнения приведенного выше примера в подробном режиме:

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

----------------------------------------------------------------------
Ran 3 tests in 0.005s

OK (skipped=3)

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

@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
    def test_not_run(self):
        pass

TestCase.setUp() также может пропустить тест. Это полезно, когда ресурс, который нужно настроить, недоступен.

Ожидаемые ошибки используют декоратор expectedFailure().

class ExpectedFailureTestCase(unittest.TestCase):
    @unittest.expectedFailure
    def test_fail(self):
        self.assertEqual(1, 0, "broken")

Вы легко можете создать свои собственные декораторы пропуска, создав декоратор, который вызывает skip() для теста, когда нужно его пропустить. Этот декоратор пропускает тест, если у переданного объекта есть определённый атрибут:

def skipUnlessHasattr(obj, attr):
    if hasattr(obj, attr):
        return lambda func: func
    return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))

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

@unittest.skip(reason)

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

@unittest.skipIf(condition, reason)

Пропустить декорированный тест, если condition истинно.

@unittest.skipUnless(condition, reason)

Пропустить декорированный тест, если condition ложно.

@unittest.expectedFailure

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

exception unittest.SkipTest(reason)

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

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

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

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

Новое в версии 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) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "subtests.py", line 32, in test_even
    self.assertEqual(i % 2, 0)
AssertionError: 1 != 0

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

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

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

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

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

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

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

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

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

assertEqual(first, second, msg=None)

Проверка, что first и second равны. Если значения не равны, тест завершится с ошибкой.

Кроме того, если first и second имеют ровно один и тот же тип, и являются списком, кортежем, словарем, множеством, неизменяемым множеством или строкой, или любым типом, который подкласс регистрирует с помощью addTypeEqualityFunc(), то функция равенства для данного типа будет вызвана для генерации более полезного сообщения об ошибке (см. также список методов для конкретных типов).

Изменено в версии 3.1: Добавлена автоматическая вызов функция равенства для конкретных типов.

Изменено в версии 3.2: assertMultiLineEqual() добавлена в качестве функции проверки равенства строк по умолчанию.

assertNotEqual(first, second, msg=None)

Проверка, что first и second не равны. Если значения равны, тест завершится с ошибкой.

assertTrue(expr, msg=None)
assertFalse(expr, msg=None)

Проверка, что expr истинно (или ложно).

Обратите внимание, что это эквивалентно bool(expr) is True и не эквивалентно expr is True (используйте assertIs(expr, True) для последнего). Этот метод также следует избегать, когда доступны более специфические методы (например, assertEqual(a, b) вместо assertTrue(a == b)), поскольку они предоставляют более информативное сообщение об ошибке в случае неудачи.

assertIs(first, second, msg=None)
assertIsNot(first, second, msg=None)

Проверка, что first и second оцениваются (или не оцениваются) как один и тот же объект.

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

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

Проверка, что expr равен (или не равен) None.

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

assertIn(first, second, msg=None)
assertNotIn(first, second, msg=None)

Проверка, что first содержится (или не содержится) в second.

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

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

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

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

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

Метод

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

Добавлена в

assertRaises(exc, fun, *args, **kwds)

fun(*args, **kwds) вызывает exc

assertRaisesRegex(exc, r, fun, *args, **kwds)

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

3.1

assertWarns(warn, fun, *args, **kwds)

fun(*args, **kwds) вызывает warn

3.2

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

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

3.2

assertLogs(logger, level)

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

3.4

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)

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

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

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

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

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

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.

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

Метод

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

Добавлен в

assertAlmostEqual(a, b)

round(a-b, 7) == 0

assertNotAlmostEqual(a, b)

round(a-b, 7) != 0

assertGreater(a, b)

a > b

3.1

assertGreaterEqual(a, b)

a >= b

3.1

assertLess(a, b)

a < b

3.1

assertLessEqual(a, b)

a <= b

3.1

assertRegex(s, r)

r.search(s)

3.1

assertNotRegex(s, r)

not r.search(s)

3.2

assertCountEqual(a, b)

элементы в a и b совпадают по количеству, независимо от их порядка

3.2

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

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

Если вместо 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().

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

assertCountEqual(first, second, msg=None)

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

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

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

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

addTypeEqualityFunc(typeobj, function)

Регистрирует метод, специфичный для типа, вызываемый assertEqual(), для проверки, равны ли два объекта точно одного и того же типа typeobj (а не подклассов). function должен принимать два позиционных аргумента и необязательный ключевой аргумент msg=None так же, как и assertEqual(). Он должен вызывать исключение self.failureException(msg), когда обнаруживается неравенство между первыми двумя параметрами, — возможно, предоставляя полезную информацию и объясняя неравенства подробно в сообщении об ошибке.

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

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

Метод

Используется для сравнения

Новая версия

assertMultiLineEqual(a, b)

строки

3.1

assertSequenceEqual(a, b)

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

3.1

assertListEqual(a, b)

списки

3.1

assertTupleEqual(a, b)

кортежи

3.1

assertSetEqual(a, b)

множества или неизменяемые множества

3.1

assertDictEqual(a, b)

словари

3.1

assertMultiLineEqual(first, second, msg=None)

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

Новая версия 3.1.

assertSequenceEqual(first, second, msg=None, seq_type=None)

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

Этот метод не вызывается напрямую assertEqual(), но он используется для реализации assertListEqual() и assertTupleEqual().

Новая версия 3.1.

assertListEqual(first, second, msg=None)
assertTupleEqual(first, second, msg=None)

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

Новая версия 3.1.

assertSetEqual(first, second, msg=None)

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

Возникает ошибка, если у first или second нет метода 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, пользовательское сообщение заменяет стандартное сообщение.

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

doCleanups()

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

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

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

Введено в версии 3.1.

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

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

26.4.8.1.1. Устаревшие алиасы

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

Имя метода

Устаревший алиас

Устаревший алиас

assertEqual()

failUnlessEqual

assertEquals

assertNotEqual()

failIfEqual

assertNotEquals

assertTrue()

failUnless

assert_

assertFalse()

failIf

assertRaises()

failUnlessRaises

assertAlmostEqual()

failUnlessAlmostEqual

assertAlmostEquals

assertNotAlmostEqual()

failIfAlmostEqual

assertNotAlmostEquals

assertRegex()

assertRegexpMatches

assertNotRegex()

assertNotRegexpMatches

assertRaisesRegex()

assertRaisesRegexp

Устарело начиная с версии 3.1: алиасы fail* в столбце "Устаревший алиас".

Устарело начиная с версии 3.2: алиасы assert* в столбце "Устаревший алиас".

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

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

26.4.8.2. Группирование тестов

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

26.4.8.3. Загрузка и выполнение тестов

class unittest.TestLoader

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

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

errors

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

Новое в версии 3.5.

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

loadTestsFromTestCase(testCaseClass)

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

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

loadTestsFromModule(module, pattern=None)

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

Примечание

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

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

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

Изменено в версии 3.5: Недокументированный и неофициальный необязательный аргумент use_load_tests устарел и игнорируется, хотя он всё ещё принимается для обратной совместимости. Метод также теперь принимает аргумент только с ключевым словом pattern, который передаётся функции 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() . Спецификатор может ссылаться на модули и пакеты, которые ещё не импортированы; они будут импортированы в качестве побочного эффекта.

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

Изменено в версии 3.5: Если при прохождении имени произошла ошибка 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).

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

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

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

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

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

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

Новое в версии 3.2.

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

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

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

testMethodPrefix

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

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

sortTestMethodsUsing

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

suiteClass

Вызываемый объект, который создаёт набор тестов из списка тестов. Методы в результирующем объекте не нужны. Значение по умолчанию — класс TestSuite.

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

class unittest.TestResult

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

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

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

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

errors

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

failures

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

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 пропущен. 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.

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)

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

По умолчанию, этот исполнитель отображает DeprecationWarning, PendingDeprecationWarning, ResourceWarning и ImportWarning, даже если они игнорируются по умолчанию. Предупреждения об устаревании, вызванные устаревшими методами unittest, также обрабатываются особым образом, и, когда фильтры предупреждений 'default' или 'always', они будут отображаться только один раз на модуль, чтобы избежать слишком большого количества сообщений об ошибках. Это поведение можно изменить, используя параметры Python -Wd или -Wa (см. Управление предупреждениями) и оставляя warnings равным 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)

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

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

Вы можете запустить тесты с более подробной информацией, передав аргумент verbosity:

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

Аргумент defaultTest — это либо имя одного теста, либо итерируемый объект имён тестов для запуска, если имена тестов не указаны через argv. Если не указан или None и имена тестов не указаны через argv, запускаются все тесты, найденные в модуле.

Аргумент argv может быть списком опций, переданных программе, где первый элемент — имя программы. Если не указан или None, используются значения sys.argv.

Аргумент testRunner может быть классом исполнителя тестов или уже созданным экземпляром. По умолчанию main вызывает sys.exit() с кодом завершения, указывающим на успех или неудачу проведённых тестов.

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

main поддерживает использование из интерактивного интерпретатора, передавая аргумент exit=False. Это отображает результат в стандартном выводе без вызова sys.exit():

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

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

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

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

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

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

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

26.4.8.3.1. Протокол загрузки тестов

Новое в версии 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: Обнаружение больше не проверяет имена пакетов на соответствие шаблону из-за невозможности соответствия имён пакетов по умолчанию.

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

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

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

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

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

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

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

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

26.4.9.1. 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 исключение, то класс будет сообщаться о пропуске, а не об ошибке.

26.4.9.2. setUpModule и tearDownModule

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

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

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

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

Новое в версии 3.2.

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

Обработчик сигнала обработки Ctrl+C пытается оставаться совместимым с кодом или тестами, которые устанавливают собственный обработчик signal.SIGINT. Если обработчик unittest вызывается, но не является установленным обработчиком signal.SIGINT , т. е. он был заменён системой под тестом и делегирован, то он вызовет обработчик по умолчанию. Обычно это ожидаемое поведение кода, который заменяет установленный обработчик и делегирует ему. Для отдельных тестов, которым нужно отключить обработку Ctrl+C, декоратор 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–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/unittest.html

Spec-Zone.ru

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