Документация Python неофициальный перевод
Содержание страницы

unittest – фреймворк модульного тестированияunittest – Unit testing framework

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

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

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

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

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

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

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

См. также

Модуль doctest
Ещё один модуль поддержки тестирования с совершенно другим подходом.
Простое тестирование в Smalltalk: с шаблонами
Оригинальная статья Кента Бека о тестовых фреймворках, использующих шаблон, общий для unittest.

Простой примерBasic example

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

Вот короткий скрипт для тестирования трёх функций из модуля random:

import random
import unittest

class TestSequenceFunctions(unittest.TestCase):

    def setUp(self):
        self.seq = range(10)

    def testshuffle(self):
        # make sure the shuffled sequence does not lose any elements
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, range(10))

    def testchoice(self):
        element = random.choice(self.seq)
        self.assert_(element in self.seq)

    def testsample(self):
        self.assertRaises(ValueError, random.sample, self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assert_(element in self.seq)

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

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

Суть каждого теста – вызов assertEqual() для проверки ожидаемого результата; assert_() для проверки условия; или assertRaises() для проверки возбуждения ожидаемого исключения. Эти методы используются вместо инструкции assert, чтобы тестовый раннер мог накопить все результаты тестов и сформировать отчёт.

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

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

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

OK

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

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

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

testchoice (__main__.TestSequenceFunctions) ... ok
testsample (__main__.TestSequenceFunctions) ... ok
testshuffle (__main__.TestSequenceFunctions) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.110s

OK

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

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

Основными строительными блоками модульного тестирования являются тестовые примеры – отдельные сценарии, которые необходимо настроить и проверить на корректность. В unittest тестовые примеры представлены экземплярами класса unittest::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*() или fail*(), предоставляемые базовым классом 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.failUnless(self.widget.size() == (50,50),
                        'incorrect default size')

class WidgetResizeTestCase(SimpleWidgetTestCase):
    def runTest(self):
        self.widget.resize(100,150)
        self.failUnless(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 testDefaultSize(self):
        self.failUnless(self.widget.size() == (50,50),
                        'incorrect default size')

    def testResize(self):
        self.widget.resize(100,150)
        self.failUnless(self.widget.size() == (100,150),
                        'wrong size after resize')

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

defaultSizeTestCase = WidgetTestCase('testDefaultSize')
resizeTestCase = WidgetTestCase('testResize')

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

widgetTestSuite = unittest.TestSuite()
widgetTestSuite.addTest(WidgetTestCase('testDefaultSize'))
widgetTestSuite.addTest(WidgetTestCase('testResize'))

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

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('testDefaultSize'))
    suite.addTest(WidgetTestCase('testResize'))
    return suite

или даже:

def suite():
    tests = ['testDefaultSize', 'testResize']

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

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

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

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

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

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

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

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

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

Повторное использование старого тестового кодаRe-using old test code

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

Классы и функцииClasses and functions

class unittest.TestCase([methodName])

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

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

def suite():
    suite = unittest.TestSuite()
    suite.addTest(WidgetTestCase('testDefaultSize'))
    suite.addTest(WidgetTestCase('testResize'))
    return suite

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

methodName по умолчанию равно 'runTest'.

class unittest.FunctionTestCase(testFunc[, setUp[, tearDown[, description]]])
Этот класс реализует часть интерфейса TestCase, позволяющую тестовому раннеру управлять тестом, но не предоставляет методов, которые тестовый код может использовать для проверки и сообщения об ошибках. Это используется для создания тестовых примеров с использованием устаревшего тестового кода, что позволяет интегрировать его в тестовый фреймворк на основе unittest.
class unittest.TestSuite([tests])

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

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

class unittest.TestLoader
Этот класс отвечает за загрузку тестов в соответствии с различными критериями и возврат их упакованными в TestSuite. Он может загрузить все тесты в заданном модуле или подклассе TestCase.
class unittest.TestResult
Этот класс используется для сбора информации о том, какие тесты прошли успешно, а какие – нет.
unittest.defaultTestLoader
Экземпляр класса TestLoader, предназначенный для совместного использования. Если настройка TestLoader не требуется, можно использовать этот экземпляр вместо многократного создания новых.
class unittest.TextTestRunner([stream[, descriptions[, verbosity]]])
Базовая реализация исполнителя тестов, которая выводит результаты в стандартный поток ошибок. Она имеет несколько настраиваемых параметров, но в целом очень проста. Графические приложения, запускающие тестовые наборы, должны предоставлять альтернативные реализации.
unittest.main([module[, defaultTest[, argv[, testRunner[, testLoader]]]]])

Командная программа, которая запускает набор тестов; это в первую очередь для того, чтобы сделать tестовые модули удобно исполняемыми. Простейшее использование этой функции – добавить следующую строку в конец тестового скрипта:

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

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

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

Объекты TestCaseTestCase Objects

Каждый экземпляр TestCase представляет отдельный тест, но каждый конкретный подкласс может использоваться для определения нескольких тестов – конкретный класс представляет отдельную тестовую фикстуру. Фикстура создаётся и очищается для каждого тестового случая.

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

Методы первой группы (выполнение теста):

TestCase.setUp()
Метод, вызываемый для подготовки тестовой фикстуры. Он вызывается непосредственно перед вызовом тестового метода; любое исключение, возбуждённое этим методом, будет считаться ошибкой, а не неудачей теста. Реализация по умолчанию ничего не делает.
TestCase.tearDown()
Метод, вызываемый сразу после того, как тестовый метод был вызван и результат записан. Он вызывается, даже если тестовый метод возбудил исключение, поэтому реализация в подклассах должна быть особенно внимательной при проверке внутреннего состояния. Любое исключение, возбуждённое этим методом, будет считаться ошибкой, а не неудачей теста. Этот метод будет вызван только в случае успеха setUp(), независимо от результата тестового метода. Реализация по умолчанию ничего не делает.
TestCase.run([result])

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

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

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

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

TestCase.assert_(expr[, msg])
TestCase.failUnless(expr[, msg])
TestCase.assertTrue(expr[, msg])
Сигнализирует о неудаче теста, если expr ложно; пояснение к ошибке будет msg, если указано, иначе None.
TestCase.assertEqual(first, second[, msg])
TestCase.failUnlessEqual(first, second[, msg])
Проверяет, что first и second равны. Если значения не равны, тест завершится ошибкой с пояснением, заданным в msg, или None. Обратите внимание, что использование failUnlessEqual() предпочтительнее, чем сравнение в качестве первого параметра failUnless(): значение по умолчанию для msg может быть вычислено так, чтобы включать представления обоих first и second.
TestCase.assertNotEqual(first, second[, msg])
TestCase.failIfEqual(first, second[, msg])
Проверяет, что first и second не равны. Если значения равны, тест завершится ошибкой с пояснением, заданным в msg, или None. Обратите внимание, что использование failIfEqual() предпочтительнее, чем сравнение в качестве первого параметра failUnless(), поскольку значение по умолчанию для msg может быть вычислено так, чтобы включать представления обоих first и second.
TestCase.assertAlmostEqual(first, second[, places[, msg]])
TestCase.failUnlessAlmostEqual(first, second[, places[, msg]])
Проверяет, что first и second приблизительно равны, вычисляя разность, округляя до заданного числа десятичных знаков (places) (по умолчанию 7) и сравнивая с нулём. Обратите внимание, что сравнение с заданным числом десятичных знаков – это не то же самое, что сравнение с заданным числом значащих цифр. Если значения не равны, тест завершится ошибкой с пояснением, заданным в msg, или None.
TestCase.assertNotAlmostEqual(first, second[, places[, msg]])
TestCase.failIfAlmostEqual(first, second[, places[, msg]])
Проверяет, что first и second не являются приблизительно равными, вычисляя разность, округляя до заданного числа десятичных знаков (places) (по умолчанию 7) и сравнивая с нулём. Обратите внимание, что сравнение с заданным числом десятичных знаков – это не то же самое, что сравнение с заданным числом значащих цифр. Если значения не сравниваются как равные, тест завершится ошибкой с пояснением, заданным в msg, или None.
TestCase.assertRaises(exception, callable, ...)
TestCase.failUnlessRaises(exception, callable, ...)
Проверяет, что исключение возбуждается при вызове callable с любыми позиционными или именованными аргументами, которые также передаются в assertRaises(). Тест проходит, если возбуждается исключение, считается ошибкой, если возбуждается другое исключение, или завершается неудачей, если не возбуждается ни одного исключения. Для перехвата любого из группы исключений в качестве исключение можно передать кортеж, содержащий классы исключений.
TestCase.failIf(expr[, msg])
TestCase.assertFalse(expr[, msg])
Методом, обратным к failUnless(), является метод failIf(). Он сигнализирует о сбое теста, если expr истинно, с msg или None в качестве сообщения об ошибке.
TestCase.fail([msg])
Сигнализирует о сбое теста безусловно, с msg или None в качестве сообщения об ошибке.
TestCase.failureException
Этот атрибут класса задаёт исключение, вызываемое методом test(). Если тестовый фреймворк должен использовать специализированное исключение, возможно, для передачи дополнительной информации, он должен создать подкласс этого исключения, чтобы «играть по правилам» с фреймворком. Начальное значение этого атрибута – AssertionError.

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

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

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

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

TestCase.id()
Возвращает строку, идентифицирующую конкретный тестовый случай. Обычно это полное имя тестового метода, включая имя модуля и класса.
TestCase.shortDescription()
Возвращает однострочное описание теста или None, если описание не было предоставлено. Реализация по умолчанию этого метода возвращает первую строку docstring тестового метода, если она доступна, или None.

Объекты TestSuiteTestSuite Objects

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

TestSuite.addTest(test)
Добавляет объект TestCase или TestSuite в набор.
TestSuite.addTests(tests)

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

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

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

TestSuite.run(result)
Запускает тесты, связанные с этим набором, собирая результат в объект результата теста, переданный как result. Обратите внимание, что в отличие от TestCase.run(), TestSuite.run() требует передачи объекта результата.
TestSuite.debug()
Запускает тесты, связанные с этим набором, без сбора результата. Это позволяет исключениям, вызванным тестом, распространяться до вызывающей стороны и может использоваться для поддержки запуска тестов под отладчиком.
TestSuite.countTestCases()
Возвращает количество тестов, представленных этим тестовым объектом, включая все отдельные тесты и поднаборы.

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

Объекты TestResultTestResult Objects

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

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

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

TestResult.errors
Список, содержащий кортежи из двух элементов: экземпляры TestCase и строки с форматированными трассировками. Каждый кортеж представляет тест, вызвавший неожиданное исключение.
TestResult.failures
Список, содержащий кортежи из двух элементов: экземпляры TestCase и строки с отформатированными трассировками. Каждый кортеж представляет тест, в котором сбой был явно обозначен с помощью методов TestCase.fail*() или TestCase.assert*().
TestResult.testsRun
Общее количество запущенных на данный момент тестов.
TestResult.wasSuccessful()
Возвращает True, если все выполненные на данный момент тесты пройдены, иначе возвращает False.
TestResult.stop()

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

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

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

TestResult.startTest(test)

Вызывается перед запуском тестового сценария test.

Реализация по умолчанию просто увеличивает счётчик testsRun экземпляра.

TestResult.stopTest(test)

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

Реализация по умолчанию ничего не делает.

TestResult.addError(test, err)

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

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

TestResult.addFailure(test, err)

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

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

TestResult.addSuccess(test)

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

Реализация по умолчанию ничего не делает.

Объекты TestLoaderTestLoader Objects

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

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

TestLoader.loadTestsFromTestCase(testCaseClass)
Возвращает набор всех тестовых случаев, содержащихся в классе testCaseClass, производном от TestCase.
TestLoader.loadTestsFromModule(module)

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

Предупреждение

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

TestLoader.loadTestsFromName(name[, module])

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

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

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

Метод опционально разрешает name относительно заданного module.

TestLoader.loadTestsFromNames(names[, module])
Аналогично loadTestsFromName(), но принимает последовательность имён, а не одно имя. Возвращаемое значение – это набор тестов, который поддерживает все тесты, определённые для каждого имени.
TestLoader.getTestCaseNames(testCaseClass)
Возвращает отсортированную последовательность имён методов, найденных в testCaseClass; это должен быть подкласс TestCase.

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

TestLoader.testMethodPrefix

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

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

TestLoader.sortTestMethodsUsing
Функция для сравнения имён методов при сортировке в getTestCaseNames() и во всех методах loadTestsFrom*(). Эта функция должна принимать два аргумента: self и other, и возвращать -1, если self предшествует other в заданном порядке, 1, если other предшествует self, и 0, если self и other равны. По умолчанию используется встроенная сортировка строк. Этот атрибут также можно установить в None, чтобы отключить сортировку.
TestLoader.suiteClass

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

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