Spec-Zone.ru › Python 2.7

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

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

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

Фреймворк для модульного тестирования Python, иногда называемый «PyUnit», является версией языка Python фреймворка JUnit от Кента Бека и Эриха Гаммы. JUnit, в свою очередь, представляет собой версию JUnit фреймворка для тестирования Smalltalk от Кента. Каждый из них является фактическим стандартным фреймворком для модульного тестирования для своего языка.

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

Для достижения этого unittest поддерживает некоторые важные концепции:

Тестовое окружение

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

Тест-кейс

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

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

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

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

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

Концепции тест-кейсов и тестового окружения поддерживаются классами TestCase и FunctionTestCase; первый должен использоваться при создании новых тестов, а второй — при интеграции существующего кода тестов с фреймворком, управляемым unittest. При построении тестовых окружений с помощью TestCase, можно переопределить методы setUp() и tearDown() для предоставления инициализации и очистки для окружения. В случае с FunctionTestCase существующие функции могут передаваться в конструктор для этих целей. При выполнении теста сначала выполняется инициализация окружения; если она проходит успешно, метод очистки выполняется после выполнения теста, независимо от результата теста. Каждый экземпляр класса TestCase будет использоваться только для запуска одного метода теста, поэтому для каждого теста создаётся новое окружение.

Тестовые наборы реализованы классом TestSuite. Этот класс позволяет агрегировать отдельные тесты и тестовые наборы; при выполнении набора выполняются все тесты, добавленные непосредственно в набор и в «дочерние» тестовые наборы.

Запускатель тестов — это объект, который предоставляет единственный метод run(), который принимает объект TestCase или TestSuite в качестве параметра и возвращает объект результата. Для использования в качестве объекта результата предоставляется класс TestResult. unittest предоставляет TextTestRunner в качестве примера запускателя тестов, который по умолчанию сообщает о результатах тестов в стандартный поток ошибок. Альтернативные запускатели могут быть реализованы для других сред (например, графических сред) без необходимости наследования от определенного класса.

См. также

Module doctest

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

unittest2: обратная портирование новых функций unittest для Python 2.4-2.6

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

Простой Smalltalk тестирования: С шаблонами

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

Nose и pytest

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

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

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

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

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

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

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

suite = unittest.TestLoader().loadTestsFromTestCase(TestStringMethods)
unittest.TextTestRunner(verbosity=2).run(suite)

Запуск изменённого скрипта из интерпретатора или другого скрипта даст следующий вывод:

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

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

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

python -m unittest -v test_module

Для списка всех командных строк:

python -m unittest -h

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

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

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

-b, --buffer

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

-c, --catch

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

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

-f, --failfast

Прекратить выполнение теста при первой ошибке или неудаче.

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

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

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

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

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

Обнаружение тестов реализовано в TestLoader.discover(), но также может быть использовано из командной строки. Базовый пример использования в командной строке:

cd project_directory
python -m unittest 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.

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

Основными блоками модульного тестирования являются тестовые случаи — отдельные сценарии, которые должны быть настроены и проверены на корректность. В unittest, тестовые случаи представлены экземплярами класса unittest’s TestCase. Для создания собственных тестовых случаев необходимо написать подклассы класса TestCase или использовать FunctionTestCase.

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

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

Простейший подкласс TestCase просто переопределит метод runTest() для выполнения специфического тестового кода:

import unittest

class DefaultWidgetSizeTestCase(unittest.TestCase):
    def runTest(self):
        widget = Widget('The widget')
        self.assertEqual(widget.size(), (50, 50), 'incorrect default size')

Обратите внимание, что для проверки чего-либо используется один из методов assert*(), предоставляемых базовым классом TestCase. Если тест завершается неудачно, будет вызвано исключение, и unittest определит тестовый случай как неудачу. Любые другие исключения будут обрабатываться как ошибки. Это помогает определить, где находится проблема: неудачи вызваны неверными результатами — 5 вместо ожидаемых 6. Ошибки вызваны неправильным кодом — например, TypeError, вызванная неправильным вызовом функции.

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

testCase = DefaultWidgetSizeTestCase()

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

К счастью, мы можем вынести такой код настройки, реализовав метод setUp(), который тестовая система автоматически вызовет при запуске теста:

import unittest

class SimpleWidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):
    def runTest(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

class WidgetResizeTestCase(SimpleWidgetTestCase):
    def runTest(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')

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

Аналогично, мы можем предоставить метод tearDown(), который производит уборку после выполнения метода runTest():

import unittest

class SimpleWidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

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

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

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

Часто многие небольшие тестовые случаи используют одну и ту же фиксатуру. В этом случае мы будем создавать подклассы SimpleWidgetTestCase в виде многих маленьких классов с одним методом, таких как DefaultWidgetSizeTestCase. Это занимает много времени и утомляет, поэтому, аналогично JUnit, unittest предоставляет более простой механизм:

import unittest

class WidgetTestCase(unittest.TestCase):
    def setUp(self):
        self.widget = Widget('The widget')

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

    def test_default_size(self):
        self.assertEqual(self.widget.size(), (50,50),
                         'incorrect default size')

    def test_resize(self):
        self.widget.resize(100,150)
        self.assertEqual(self.widget.size(), (100,150),
                         'wrong size after resize')

Здесь мы не предоставляем метод runTest(), но вместо этого предоставили два разных тестовых метода. Экземпляры классов теперь будут выполнять один из методов test_*(), а self.widget создается и уничтожается отдельно для каждого экземпляра. При создании экземпляра нам необходимо указать тестовый метод, который он должен выполнить. Мы делаем это, передавая имя метода в конструктор:

defaultSizeTestCase = WidgetTestCase('test_default_size')
resizeTestCase = WidgetTestCase('test_resize')

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

widgetTestSuite = unittest.TestSuite()
widgetTestSuite.addTest(WidgetTestCase('test_default_size'))
widgetTestSuite.addTest(WidgetTestCase('test_resize'))

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

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

или даже:

def suite():
    tests = ['test_default_size', 'test_resize']

    return unittest.TestSuite(map(WidgetTestCase, tests))

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

suite = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)

создаст набор тестов, которые будут выполняться WidgetTestCase.test_default_size() и WidgetTestCase.test_resize. TestLoader использует префикс имени метода 'test' для автоматической идентификации тестовых методов.

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

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

suite1 = module1.TheTestSuite()
suite2 = module2.TheTestSuite()
alltests = unittest.TestSuite([suite1, suite2])

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

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

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

Чтобы облегчить миграцию существующих наборов тестов, unittest поддерживает тесты, которые поднимают AssertionError, чтобы указать на сбой теста. Однако рекомендуется использовать явные методы TestCase.fail*() и TestCase.assert*() вместо этого, так как будущие версии unittest могут обращаться с AssertionError по-другому.

Примечание

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

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

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

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

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() вокруг них.

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

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

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

class unittest.TestCase(methodName='runTest')

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

Каждый экземпляр TestCase будет запускать один метод теста: метод с именем methodName. Если вы помните, ранее был пример, похожий на этот:

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

Здесь мы создаём два экземпляра WidgetTestCase, каждый из которых выполняет один тест.

methodName по умолчанию равен runTest().

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

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

setUp()

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

tearDown()

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

setUpClass()

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

@classmethod
def setUpClass(cls):
    ...

См. Фикстуры классов и модулей для получения более подробной информации.

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

tearDownClass()

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

@classmethod
def tearDownClass(cls):
    ...

См. Фикстуры классов и модулей для получения более подробной информации.

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

run(result=None)

Запустить тест, собрав результат в объект результатов теста, переданный как result. Если result опущен или None, создаётся временный объект результатов (вызывая метод defaultTestResult()) и используется. Объект результата не возвращается вызывающей стороне метода run().

Тот же эффект может быть получен простым вызовом экземпляра TestCase.

skipTest(reason)

Вызов этого метода во время метода теста или setUp() пропускает текущий тест. См. Пропуск тестов и ожидаемые ошибки для получения дополнительной информации.

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

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

2.7

assertIsNot(a, b)

a is not b

2.7

assertIsNone(x)

x is None

2.7

assertIsNotNone(x)

x is not None

2.7

assertIn(a, b)

a in b

2.7

assertNotIn(a, b)

a not in b

2.7

assertIsInstance(a, b)

isinstance(a, b)

2.7

assertNotIsInstance(a, b)

not isinstance(a, b)

2.7

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

assertEqual(first, second, msg=None)

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

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

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

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 оцениваются (или не оцениваются) как один и тот же объект.

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

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

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

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

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

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

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

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

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

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

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

Метод

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

Новая в

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

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

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

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

2.7

assertRaises(exception, callable, *args, **kwds)
assertRaises(exception)

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

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

with self.assertRaises(SomeException):
    do_something()

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

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

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

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

assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
assertRaisesRegexp(exception, regexp)

Аналогично assertRaises(), но также проверяет, что regexp соответствует строковому представлению поднятого исключения. regexp может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодное для использования в re.search(). Примеры:

self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$",
                        int, 'XYZ')

или:

with self.assertRaisesRegexp(ValueError, 'literal'):
   int('XYZ')

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

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

Метод

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

Новая в

assertAlmostEqual(a, b)

round(a-b, 7) == 0

assertNotAlmostEqual(a, b)

round(a-b, 7) != 0

assertGreater(a, b)

a > b

2.7

assertGreaterEqual(a, b)

a >= b

2.7

assertLess(a, b)

a < b

2.7

assertLessEqual(a, b)

a <= b

2.7

assertRegexpMatches(s, r)

r.search(s)

2.7

assertNotRegexpMatches(s, r)

not r.search(s)

2.7

assertItemsEqual(a, b)

sorted(a) == sorted(b) и работает с объектами, не поддерживающими хэширование

2.7

assertDictContainsSubset(a, b)

все пары ключ/значение в a существуют в b

2.7

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.

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

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

assertRegexpMatches(text, regexp, msg=None)

Проверка, что поиск regexp соответствует text. В случае неудачи сообщение об ошибке будет содержать шаблон и text (или шаблон и часть text, которая неожиданно совпала). regexp может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодное для использования в re.search().

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

assertNotRegexpMatches(text, regexp, msg=None)

Проверяет, что поиск regexp не соответствует text. Возвращает ошибку с сообщением, включающим шаблон и часть text, которая совпала. regexp может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодное для использования в re.search().

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

assertItemsEqual(actual, expected, msg=None)

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

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

В Python 3 этот метод называется assertCountEqual.

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

assertDictContainsSubset(expected, actual, msg=None)

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

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

Устарело начиная с версии 3.2.

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

addTypeEqualityFunc(typeobj, function)

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

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

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

Метод

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

Новое в

assertMultiLineEqual(a, b)

строки

2.7

assertSequenceEqual(a, b)

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

2.7

assertListEqual(a, b)

списки

2.7

assertTupleEqual(a, b)

кортежи

2.7

assertSetEqual(a, b)

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

2.7

assertDictEqual(a, b)

словари

2.7

assertMultiLineEqual(first, second, msg=None)

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

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

assertSequenceEqual(seq1, seq2, msg=None, seq_type=None)

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

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

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

assertListEqual(list1, list2, msg=None)
assertTupleEqual(tuple1, tuple2, msg=None)

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

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

assertSetEqual(set1, set2, msg=None)

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

Возникает ошибка, если у set1 или set2 отсутствует метод set.difference().

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

assertDictEqual(expected, actual, msg=None)

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

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

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

fail(msg=None)

Безусловно сигнализирует об ошибке теста с сообщением msg или None.

failureException

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

longMessage

Если установлено в True, любое явное сообщение об ошибке, которое вы передаете методам assert methods, будет добавляться в конец обычного сообщения об ошибке. Обычные сообщения содержат полезную информацию об участвующих объектах, например, сообщение от assertEqual показывает вам repr двух неравных объектов. Установка этого атрибута в True позволяет вам иметь пользовательское сообщение об ошибке в дополнение к обычному.

По умолчанию этот атрибут равен False, что означает, что пользовательское сообщение, переданное методу assert, отключит обычное сообщение.

Настройка класса может быть переопределена в отдельных тестах путем назначения атрибута экземпляра True или True перед вызовом методов assert.

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

maxDiff

Этот атрибут контролирует максимальную длину различий, выводимых методами assert, которые сообщают о различиях при ошибках. По умолчанию он равен 80*8 символов. На методы assert, на которые влияет этот атрибут, влияют assertSequenceEqual() (включая все методы сравнения последовательностей, которые делегируют ему), assertDictEqual() и assertMultiLineEqual().

Установка maxDiff в None означает, что максимальной длины различий нет.

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

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

countTestCases()

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

defaultTestResult()

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

Для экземпляров TestCase, это всегда будет экземпляр TestResult; подклассы TestCase должны переопределять это по мере необходимости.

id()

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

shortDescription()

Возвращает описание теста или None, если описание не было предоставлено. По умолчанию этот метод возвращает первую строку docstring тестового метода, если она доступна, или None.

addCleanup(function, *args, **kwargs)

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

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

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

doCleanups()

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

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

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

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

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

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

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

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

Имя метода

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

assertEqual()

failUnlessEqual, assertEquals

assertNotEqual()

failIfEqual

assertTrue()

failUnless, assert_

assertFalse()

failIf

assertRaises()

failUnlessRaises

assertAlmostEqual()

failUnlessAlmostEqual

assertNotAlmostEqual()

failIfAlmostEqual

Устарело начиная с версии 2.7: указанные в правом столбце псевдонимы

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

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

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

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

class unittest.TestLoader

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

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

loadTestsFromTestCase(testCaseClass)

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

loadTestsFromModule(module)

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

Примечание

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

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

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

loadTestsFromName(name, module=None)

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

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

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

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

loadTestsFromNames(names, module=None)

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

getTestCaseNames(testCaseClass)

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

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

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

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

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

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

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

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

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

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

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

testMethodPrefix

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

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

sortTestMethodsUsing

Функция, которая используется для сравнения имён методов при сортировке их в getTestCaseNames() и всех методах loadTestsFrom*(). Значение по умолчанию — встроенная функция cmp(); атрибут также можно установить в None для отключения сортировки.

suiteClass

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

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

class unittest.TestResult

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

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

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

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

errors

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

Изменено в версии 2.2: Содержит отформатированные трассировки стека вместо результатов sys.exc_info().

failures

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

Изменено в версии 2.2: Содержит отформатированные трассировки стека вместо результатов sys.exc_info().

skipped

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

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

expectedFailures

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

unexpectedSuccesses

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

shouldStop

Устанавливается в True при завершении выполнения тестов с помощью stop().

testsRun

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

buffer

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

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

failfast

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

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

wasSuccessful()

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

stop()

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

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

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

startTest(test)

Вызывается, когда тест-кейс test собирается выполняться.

stopTest(test)

Вызывается после выполнения тест-кейса test, независимо от результата.

startTestRun()

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

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

stopTestRun()

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

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

addError(test, err)

Вызывается, когда тест-кейс test поднимает непредвиденное исключение. err — это кортеж, возвращаемый sys.exc_info(): (type, value, traceback).

Встроенное реализация добавляет кортеж (test, formatted_err) к атрибуту экземпляра errors, где formatted_err — отформатированная трассировка стека, полученная из err.

addFailure(test, err)

Вызывается, когда тест-кейс test сигнализирует об ошибке. err — это кортеж, возвращаемый sys.exc_info(): (type, value, traceback).

Встроенное реализация добавляет кортеж (test, formatted_err) к атрибуту экземпляра failures, где formatted_err — отформатированная трассировка стека, полученная из err.

addSuccess(test)

Вызывается, когда тест-кейс test проходит успешно.

Встроенное реализация ничего не делает.

addSkip(test, reason)

Вызывается, когда тест-кейс test пропущен. reason — причина пропуска теста.

Встроенное реализация добавляет кортеж (test, reason) к атрибуту экземпляра skipped.

addExpectedFailure(test, err)

Вызывается, когда тест-кейс test терпит неудачу, но был помечен декоратором expectedFailure().

Встроенное реализация добавляет кортеж (test, formatted_err) к атрибуту экземпляра expectedFailures, где formatted_err — отформатированная трассировка стека, полученная из err.

addUnexpectedSuccess(test)

Вызывается, когда тест-кейс test был помечен декоратором expectedFailure(), но завершился успешно.

Встроенное реализация добавляет тест к атрибуту экземпляра unexpectedSuccesses.

class unittest.TextTestResult(stream, descriptions, verbosity)

Конкретная реализация TestResult, используемая в TextTestRunner.

Новая в версии 2.7: Этот класс ранее назывался _TextTestResult. Старое имя по-прежнему существует как псевдоним, но устарело.

unittest.defaultTestLoader

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

class unittest.TextTestRunner(stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None)

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

_makeResult()

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

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

stream, descriptions, verbosity
unittest.main([module[, defaultTest[, argv[, testRunner[, testLoader[, exit[, verbosity[, failfast[, catchbreak[, buffer]]]]]]]]]])

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

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 имеют тот же эффект, что и одноимённые параметры параметров командной строки.

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

Изменено в версии 2.7: Были добавлены параметры exit, verbosity, failfast, catchbreak и buffer.

7.3.1. Протокол load_tests

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

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

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

load_tests(loader, standard_tests, None)

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

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

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

test_cases = (TestCase1, TestCase2, TestCase3)

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

Если обнаружение запускается, либо из командной строки, либо вызывая TestLoader.discover(), с шаблоном, соответствующим имени пакета, то пакет __init__.py будет проверен на наличие load_tests.

Примечание

Шаблон по умолчанию — 'test*.py'. Он соответствует всем файлам Python, начинающимся с 'test' , но не будет соответствовать никаким тестовым каталогам.

Шаблон, подобный 'test*' , будет соответствовать тестовым пакетам и модулям.

Если пакет __init__.py определяет load_tests , он будет вызван, и обнаружение не продолжится в пакет. load_tests вызывается со следующими аргументами:

load_tests(loader, standard_tests, pattern)

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

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

def load_tests(loader, standard_tests, pattern):
    # 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

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

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

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

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

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

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

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

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

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

8.2. setUpModule и tearDownModule

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

def setUpModule():
    createConnection()

def tearDownModule():
    closeConnection()

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

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

Опция командной строки -c/--catch для unittest вместе с параметром catchbreak для unittest.main() обеспечивают более удобную обработку нажатия Ctrl+C во время выполнения теста. При включенном поведениe перехвата 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().

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

unittest.registerResult(result)

Зарегистрировать объект TestResult для обработки Ctrl+C. Регистрация результата сохраняет слабую ссылку на него, поэтому она не препятствует сборке мусора результата.

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

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

unittest.removeResult(result)

Удалить зарегистрированный результат. После удаления результата, stop() больше не будет вызываться для этого объекта результата в ответ на Ctrl+C.

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

unittest.removeHandler(function=None)

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

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

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

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

Spec-Zone.ru

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