Spec-Zone.ru › Python 3.5

unittest — Фреймворк для юнит-тестирования

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

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

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

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

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

См. также

Module doctest
Другой модуль поддержки тестирования с совершенно другим функционалом.
Простой тест Smalltalk: С паттернами
Оригинальная статья Кента Бека о фреймворках тестирования, использующих паттерн, применяемый в unittest.
Nose и py.test
Фреймворки для юнит-тестирования сторонних разработчиков с более лёгким синтаксисом для написания тестов. Например, assert func(10) == 42.
Классификация инструментов для тестирования Python
Подробный список инструментов для тестирования Python, включая фреймворки функционального тестирования и библиотеки для создания имитационных объектов.
Список рассылки по тестированию в Python
Группа по интересам для обсуждения тестирования и инструментов тестирования в Python.

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

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

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

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

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

-b, --buffer

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

-c, --catch

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

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

-f, --failfast

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

--locals

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

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

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

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

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: Открытие тестов поддерживает пакеты именованных пространств.

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() будет выполнен независимо от того, выполнился ли успешно тестовый метод или нет.

Такая рабочая среда для кода тестирования называется фиксатурой.

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

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

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('test_default_size'))
    suite.addTest(WidgetTestCase('test_resize'))
    return suite

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

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

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.

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().

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

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

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

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

Метод Проверяет, что Введено в
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b 3.1
assertIsNot(a, b) a is not b 3.1
assertIsNone(x) x is None 3.1
assertIsNotNone(x) x is not None 3.1
assertIn(a, b) a in b 3.1
assertNotIn(a, b) a not in b 3.1
assertIsInstance(a, b) isinstance(a, b) 3.2
assertNotIsInstance(a, b) not isinstance(a, b) 3.2

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

assertEqual(first, second, msg=None)

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

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

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

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

assertNotEqual(first, second, msg=None)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Метод Проверяет, что Введено в
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) вызывает exc
assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) вызывает exc и сообщение соответствует регулярному выражению r 3.1
assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) вызывает warn 3.2
assertWarnsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) вызывает warn и сообщение соответствует регулярному выражению r 3.2
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()), а не до значимых цифр.

Если вместо разрядов указан delta, то разница между first и second должна быть меньше или равна (или больше) delta.

Если указаны и delta, и разряды, возникает 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.

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().

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

class unittest.TestSuite(tests=())

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

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

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

addTest(test)

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

addTests(tests)

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

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

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(). Спецификатор может ссылаться на модули и пакеты, которые не были импортированы; они будут импортированы как побочный эффект.

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

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

loadTestsFromNames(names, module=None)

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

getTestCaseNames(testCaseClass)

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

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

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

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

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

unittest.main(module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None)

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

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

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

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

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

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

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

Аргумент 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 изменён на также приём итерируемого списка имён тестов.

8.3.1. Протокол load_tests

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

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

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

load_tests(loader, standard_tests, pattern)

где pattern передаётся непосредственно из loadTestsFromModule. По умолчанию он равен None.

Он должен вернуть TestSuite.

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

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

test_cases = (TestCase1, TestCase2, TestCase3)

def load_tests(loader, tests, pattern):
    suite = TestSuite()
    for test_class in test_cases:
        tests = loader.loadTestsFromTestCase(test_class)
        suite.addTests(tests)
    return suite

Если обнаружение запускается в каталоге, содержащем пакет, либо из командной строки, либо вызывая TestLoader.discover(), то пакет __init__.py будет проверен на наличие load_tests. Если эта функция не существует, обнаружение будет рекурсивно переходить в пакет, как если бы это был просто другой каталог. В противном случае обнаружение тестов пакета будет оставлено load_tests, который вызывается со следующими аргументами:

load_tests(loader, standard_tests, pattern)

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

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

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

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

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

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

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

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

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

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

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

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

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

9.2. setUpModule и tearDownModule

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

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

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

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.5/library/unittest.html

Spec-Zone.ru

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