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

unittest.md

1390 строк · 131.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/2.7/library/unittest.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 25.3. [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) – фреймворк для модульного тестирования89Новое в версии 2.1.1011(Если вы уже знакомы с основными понятиями тестирования, можете перейти к [списку методов assert](https://python-all.ru/2.7/library/unittest.html#assert-methods).)1213Среда модульного тестирования Python, иногда называемая «PyUnit», является реализацией JUnit на языке Python, созданной Кентом Беком и Эрихом Гаммой. JUnit, в свою очередь, представляет собой Java-версию среды тестирования Smalltalk Кента Бека. Каждая из них является фактическим стандартом модульного тестирования для своего языка.1415[`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) поддерживает автоматизацию тестов, совместное использование кода настройки и завершения для тестов, объединение тестов в наборы и независимость тестов от фреймворка отчётности. Модуль [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет классы, упрощающие поддержку этих качеств для набора тестов.1617Для этого [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) поддерживает несколько важных концепций:1819**тестовая фикстура**2021*Тестовая фикстура* представляет собой подготовку, необходимую для выполнения одного или нескольких тестов, и любые сопутствующие действия по очистке. Это может включать, например, создание временных или прокси-баз данных, каталогов или запуск серверного процесса.2223**тестовый случай**2425*тестовый сценарий* – это наименьшая единица тестирования. Он проверяет определённую реакцию на конкретный набор входных данных. [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет базовый класс [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), который можно использовать для создания новых тестовых сценариев.2627**набор тестов**2829*Набор тестов* – это совокупность тестовых случаев, наборов тестов или и того, и другого. Он используется для объединения тестов, которые должны выполняться вместе.3031**исполнитель тестов**3233*Исполнитель тестов* – это компонент, который управляет выполнением тестов и предоставляет результат пользователю. Исполнитель может использовать графический интерфейс, текстовый интерфейс или возвращать специальное значение, указывающее на результаты выполнения тестов.3435Концепции тестового сценария и тестового окружения поддерживаются через классы [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и [`FunctionTestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.FunctionTestCase); первый следует использовать при создании новых тестов, а второй – при интеграции существующего тестового кода с фреймворком, управляемым [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest). При построении тестовых окружений с помощью [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) методы [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) и [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown) можно переопределить для инициализации и очистки окружения. С [`FunctionTestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.FunctionTestCase) существующие функции можно передавать конструктору для этих целей. При запуске теста сначала выполняется инициализация окружения; если она прошла успешно, метод очистки запускается после выполнения теста, независимо от его результата. Каждый экземпляр [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) будет использоваться только для запуска одного тестового метода, поэтому для каждого теста создаётся новое окружение.3637Тестовые наборы реализуются классом [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite). Этот класс позволяет объединять отдельные тесты и тестовые наборы; при выполнении набора запускаются все тесты, добавленные непосредственно в набор и в «дочерние» тестовые наборы.3839Тестовый раннер – это объект, предоставляющий единственный метод `run()`, который принимает объект [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) или [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) в качестве параметра и возвращает объект результата. Класс [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult) предоставляется для использования в качестве объекта результата. [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет [`TextTestRunner`](https://python-all.ru/2.7/library/unittest.html#unittest.TextTestRunner) в качестве примера тестового раннера, который по умолчанию выводит результаты тестов в стандартный поток ошибок. Альтернативные раннеры могут быть реализованы для других сред (например, графических) без необходимости наследования от какого-либо конкретного класса.4041> **См. также**42>43> **Модуль [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest)**44>45> Ещё один модуль поддержки тестирования с совершенно другим подходом.46>47> **[unittest2: обратный порт новых возможностей unittest для Python 2.4–2.6](https://python-all.ru/2.7/library/unittest.html)**48>49> В Python 2.7 в unittest было добавлено много новых возможностей, включая обнаружение тестов. unittest2 позволяет использовать эти возможности в более ранних версиях Python.50>51> **[Простое тестирование в Smalltalk: с шаблонами](https://python-all.ru/2.7/library/unittest.html)**52>53> Оригинальная статья Кента Бека о фреймворках тестирования, в которых используется тот же шаблон, что и в [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest).54>55> **[Nose](https://python-all.ru/2.7/library/unittest.html) и [pytest](https://python-all.ru/2.7/library/unittest.html)**56>57> Сторонние фреймворки для unittest с более лёгким синтаксисом написания тестов. Например, `assert func(10) == 42`.58>59> **[Таксономия инструментов тестирования Python](https://python-all.ru/2.7/library/unittest.html)**60>61> Обширный список инструментов тестирования Python, включая фреймворки функционального тестирования и библиотеки имитационных объектов (mock).62>63> **[Список рассылки по тестированию в Python](https://python-all.ru/2.7/library/unittest.html)**64>65> Группа по интересам для обсуждения тестирования и инструментов тестирования в Python.6667## 25.3.1. Простой пример6869Модуль [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет богатый набор инструментов для создания и запуска тестов. В этом разделе показано, что небольшого подмножества этих инструментов достаточно для удовлетворения потребностей большинства пользователей.7071Вот короткий скрипт для тестирования трёх строковых методов:7273```python74import unittest7576class TestStringMethods(unittest.TestCase):7778    def test_upper(self):79        self.assertEqual('foo'.upper(), 'FOO')8081    def test_isupper(self):82        self.assertTrue('FOO'.isupper())83        self.assertFalse('Foo'.isupper())8485    def test_split(self):86        s = 'hello world'87        self.assertEqual(s.split(), ['hello', 'world'])88        # проверить, что s.split завершается ошибкой, если разделитель не строка89        with self.assertRaises(TypeError):90            s.split(2)9192if __name__ == '__main__':93    unittest.main()94```9596Тестовый случай создаётся созданием подкласса [`unittest.TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase). Три отдельных теста определяются методами, имена которых начинаются с букв `test`. Это соглашение об именовании сообщает тестовому раннеру, какие методы являются тестами.9798Суть каждого теста – вызов [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual) для проверки ожидаемого результата; [`assertTrue()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertTrue) или [`assertFalse()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertFalse) для проверки условия; или [`assertRaises()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises) для проверки того, что возбуждается определённое исключение. Эти методы используются вместо оператора [`assert`](https://python-all.ru/2.7/reference/simple_stmts.html#assert), чтобы исполнитель тестов мог накапливать все результаты тестов и формировать отчёт.99100Методы [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) и [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown) позволяют определить инструкции, которые будут выполняться до и после каждого метода теста. Они подробнее рассматриваются в разделе [Организация тестового кода](https://python-all.ru/2.7/library/unittest.html#organizing-tests).101102В последнем блоке показан простой способ запуска тестов. [`unittest.main()`](https://python-all.ru/2.7/library/unittest.html#unittest.main) предоставляет интерфейс командной строки для тестового скрипта. При запуске из командной строки приведённый выше скрипт выдаёт вывод, который выглядит так:103104```python105...106----------------------------------------------------------------------107Ran 3 tests in 0.000s108109OK110```111112Вместо [`unittest.main()`](https://python-all.ru/2.7/library/unittest.html#unittest.main) существуют другие способы запуска тестов с более тонким контролем, менее кратким выводом и без необходимости запуска из командной строки. Например, последние две строки можно заменить на:113114```python115suite = unittest.TestLoader().loadTestsFromTestCase(TestStringMethods)116unittest.TextTestRunner(verbosity=2).run(suite)117```118119Запуск изменённого скрипта из интерпретатора или другого скрипта приводит к следующему выводу:120121```python122test_isupper (__main__.TestStringMethods) ... ok123test_split (__main__.TestStringMethods) ... ok124test_upper (__main__.TestStringMethods) ... ok125126----------------------------------------------------------------------127Ran 3 tests in 0.001s128129OK130```131132Представленные выше примеры демонстрируют наиболее часто используемые возможности [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), которых достаточно для многих повседневных задач тестирования. Оставшаяся часть документации рассматривает полный набор функций с самого начала.133134## 25.3.2. Интерфейс командной строки135136Модуль unittest можно использовать из командной строки для запуска тестов из модулей, классов или даже отдельных тестовых методов:137138```python139python -m unittest test_module1 test_module2140python -m unittest test_module.TestClass141python -m unittest test_module.TestClass.test_method142```143144Можно передать список с любой комбинацией имён модулей, а также полных имён классов или методов.145146Можно запускать тесты с большей детализацией (повышенной подробностью), передав флаг -v:147148```python149python -m unittest -v test_module150```151152Чтобы получить список всех параметров командной строки:153154```python155python -m unittest -h156```157158Изменено в версии 2.7: В более ранних версиях можно было запускать только отдельные тестовые методы, а не модули или классы.159160### 25.3.2.1. Параметры командной строки161162**unittest** поддерживает следующие параметры командной строки:163164#### `-b, --buffer`165166Потоки стандартного вывода и стандартной ошибки буферизируются во время выполнения теста. Вывод при успешном тесте отбрасывается. При ошибке или провале теста вывод выводится обычным образом и добавляется к сообщениям о неудаче.167168#### `-c, --catch`169170`Control-C` во время выполнения теста ожидает завершения текущего теста, а затем выводит все результаты, полученные на данный момент. Повторное нажатие `Control-C` вызывает обычное исключение [`KeyboardInterrupt`](https://python-all.ru/2.7/library/exceptions.html#exceptions.KeyboardInterrupt).171172См. раздел [Обработка сигналов](https://python-all.ru/2.7/library/unittest.html#signal-handling) с описанием функций, предоставляющих эту возможность.173174#### `-f, --failfast`175176Остановить выполнение теста при первой же ошибке или неудаче.177178Новое в версии 2.7: Были добавлены параметры командной строки `-b`, `-c` и `-f`.179180Командная строка также может использоваться для автоматического обнаружения тестов, для запуска всех тестов в проекте или только их части.181182## 25.3.3. Обнаружение тестов183184Новое в версии 2.7.185186Unittest поддерживает простое обнаружение тестов. Чтобы быть совместимыми с обнаружением тестов, все тестовые файлы должны быть [модулями](https://python-all.ru/2.7/tutorial/modules.html#tut-modules) или [пакетами](https://python-all.ru/2.7/tutorial/modules.html#tut-packages), импортируемыми из корневого каталога проекта (это означает, что их имена файлов должны быть валидными [идентификаторами](https://python-all.ru/2.7/reference/lexical_analysis.html#identifiers)).187188Обнаружение тестов реализовано в [`TestLoader.discover()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader.discover), но также может использоваться из командной строки. Основное использование командной строки:189190```python191cd project_directory192python -m unittest discover193```194195Подкоманда `discover` имеет следующие опции:196197#### `-v, --verbose`198199Подробный вывод200201#### `-s, --start-directory directory`202203Каталог для начала обнаружения (по умолчанию `.`)204205#### `-p, --pattern pattern`206207Шаблон для сопоставления тестовых файлов (по умолчанию `test*.py`)208209#### `-t, --top-level-directory directory`210211Корневой каталог проекта (по умолчанию – каталог начала поиска)212213Параметры [`-s`](https://python-all.ru/2.7/library/unittest.html#cmdoption-unittest-discover-s), [`-p`](https://python-all.ru/2.7/library/unittest.html#cmdoption-unittest-discover-p) и [`-t`](https://python-all.ru/2.7/library/unittest.html#cmdoption-unittest-discover-t) можно передавать в качестве позиционных аргументов в указанном порядке. Следующие две командные строки эквивалентны:214215```python216python -m unittest discover -s project_directory -p "*_test.py"217python -m unittest discover project_directory "*_test.py"218```219220Помимо пути, в качестве начального каталога можно передать имя пакета, например `myproject.subpackage.test`. Указанное имя пакета будет импортировано, и его расположение в файловой системе будет использоваться в качестве начального каталога.221222> **Внимание**223>224> Обнаружение тестов загружает тесты путём их импорта. После того как обнаружение тестов находит все тестовые файлы из указанного начального каталога, оно преобразует пути в имена пакетов для импорта. Например, `foo/bar/baz.py` будет импортирован как `foo.bar.baz`.225>226> Если пакет установлен глобально, и предпринимается попытка обнаружения тестов в другой копии пакета, то импорт *может* произойти из неправильного места. Если это произойдет, обнаружение тестов выдаст предупреждение и завершится.227>228> Если указать начальный каталог как имя пакета, а не путь к каталогу, то discover считает, что местоположение, из которого он импортирует, и есть то, которое вы имели в виду, поэтому предупреждение не появится.229230Тестовые модули и пакеты могут настраивать загрузку и обнаружение тестов с помощью [протокола load\_tests](https://python-all.ru/2.7/library/unittest.html#load-tests-protocol).231232## 25.3.4. Организация тестового кода233234Основными строительными блоками модульного тестирования являются *тестовые сценарии* – отдельные сценарии, которые необходимо настроить и проверить на корректность. В [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) тестовые сценарии представлены экземплярами класса [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) из модуля [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest). Чтобы создать собственные тестовые сценарии, необходимо написать подклассы [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) или использовать [`FunctionTestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.FunctionTestCase).235236Экземпляр класса, производного от [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), – это объект, который может полностью выполнить один тестовый метод вместе с необязательным кодом настройки и завершения.237238Тестовый код экземпляра [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) должен быть полностью самодостаточным, чтобы его можно было запускать как изолированно, так и в произвольной комбинации с любым количеством других тестовых случаев.239240Простейший подкласс [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) просто переопределяет метод `runTest()` для выполнения конкретного тестового кода:241242```python243import unittest244245class DefaultWidgetSizeTestCase(unittest.TestCase):246    def runTest(self):247        widget = Widget('The widget')248        self.assertEqual(widget.size(), (50, 50), 'incorrect default size')249```250251Обратите внимание: для проверки чего-либо используется один из методов `assert*()`, предоставляемых базовым классом [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase). Если тест не пройден, будет возбуждено исключение, и [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) идентифицирует тестовый сценарий как *неудачу*. Любые другие исключения будут расценены как *ошибки*. Это помогает определить, в чём проблема: *неудачи* вызваны неверными результатами – например, получено 5 вместо ожидаемых 6. *Ошибки* вызваны неверным кодом – например, [`TypeError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.TypeError) из-за неправильного вызова функции.252253Способ запуска тестового примера будет описан позже. Пока обратите внимание, что для создания экземпляра такого тестового примера мы вызываем его конструктор без аргументов:254255```python256testCase = DefaultWidgetSizeTestCase()257```258259Таких тестовых сценариев может быть много, и их настройка может повторяться. В приведённом выше случае создание `Widget` в каждом из 100 подклассов тестовых сценариев Widget означало бы неприглядное дублирование.260261К счастью, мы можем вынести такой код настройки, реализовав метод [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp), который тестовый фреймворк автоматически вызовет при запуске теста:262263```python264import unittest265266class SimpleWidgetTestCase(unittest.TestCase):267    def setUp(self):268        self.widget = Widget('The widget')269270class DefaultWidgetSizeTestCase(SimpleWidgetTestCase):271    def runTest(self):272        self.assertEqual(self.widget.size(), (50,50),273                         'incorrect default size')274275class WidgetResizeTestCase(SimpleWidgetTestCase):276    def runTest(self):277        self.widget.resize(100,150)278        self.assertEqual(self.widget.size(), (100,150),279                         'wrong size after resize')280```281282Если метод [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) возбуждает исключение во время выполнения теста, фреймворк сочтёт, что в тесте произошла ошибка, и метод `runTest()` не будет выполнен.283284Аналогично, мы можем предоставить метод [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown), который выполняет завершающие действия после выполнения метода `runTest()`:285286```python287import unittest288289class SimpleWidgetTestCase(unittest.TestCase):290    def setUp(self):291        self.widget = Widget('The widget')292293    def tearDown(self):294        self.widget.dispose()295        self.widget = None296```297298Если [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) выполнился успешно, метод [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown) будет запущен независимо от того, успешно ли выполнился `runTest()`.299300Такое рабочее окружение для тестового кода называется *фикстурой*.301302Часто множество небольших тестовых сценариев используют одно и то же окружение. В этом случае нам пришлось бы создавать подклассы `SimpleWidgetTestCase` во множество мелких классов с одним методом, таких как `DefaultWidgetSizeTestCase`. Это отнимает много времени и демотивирует, поэтому, в духе JUnit, [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет более простой механизм:303304```python305import unittest306307class WidgetTestCase(unittest.TestCase):308    def setUp(self):309        self.widget = Widget('The widget')310311    def tearDown(self):312        self.widget.dispose()313        self.widget = None314315    def test_default_size(self):316        self.assertEqual(self.widget.size(), (50,50),317                         'incorrect default size')318319    def test_resize(self):320        self.widget.resize(100,150)321        self.assertEqual(self.widget.size(), (100,150),322                         'wrong size after resize')323```324325Здесь мы не предоставили метод `runTest()`, а вместо этого предоставили два разных тестовых метода. Теперь каждый экземпляр класса будет запускать один из методов `test_*()`, при этом `self.widget` создаётся и уничтожается отдельно для каждого экземпляра. При создании экземпляра необходимо указать тестовый метод, который он будет запускать. Это делается путём передачи имени метода в конструктор:326327```python328defaultSizeTestCase = WidgetTestCase('test_default_size')329resizeTestCase = WidgetTestCase('test_resize')330```331332Экземпляры тестовых сценариев группируются вместе в соответствии с тестируемыми функциями. [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет для этого механизм: *тестовый набор*, представленный классом [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) модуля [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest):333334```python335widgetTestSuite = unittest.TestSuite()336widgetTestSuite.addTest(WidgetTestCase('test_default_size'))337widgetTestSuite.addTest(WidgetTestCase('test_resize'))338```339340Для удобства запуска тестов, как мы увидим далее, рекомендуется предоставлять в каждом тестовом модуле вызываемый объект, возвращающий предварительно собранный набор тестов:341342```python343def suite():344    suite = unittest.TestSuite()345    suite.addTest(WidgetTestCase('test_default_size'))346    suite.addTest(WidgetTestCase('test_resize'))347    return suite348```349350или даже:351352```python353def suite():354    tests = ['test_default_size', 'test_resize']355356    return unittest.TestSuite(map(WidgetTestCase, tests))357```358359Поскольку распространённым паттерном является создание подкласса [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) со множеством однотипно названных тестовых функций, [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет класс [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader), который можно использовать для автоматизации процесса создания тестового набора и заполнения его отдельными тестами. Например,360361```python362suite = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase)363```364365создаст тестовый набор, который запустит `WidgetTestCase.test_default_size()` и `WidgetTestCase.test_resize`. [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader) использует префикс имени метода `'test'` для автоматической идентификации тестовых методов.366367Обратите внимание, что порядок выполнения различных тестовых случаев определяется сортировкой имён тестовых функций в соответствии со встроенным порядком строк.368369Часто требуется группировать наборы тестовых сценариев вместе, чтобы запускать тесты для всей системы сразу. Это легко, поскольку экземпляры [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) можно добавлять в [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) так же, как экземпляры [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) можно добавлять в [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite):370371```python372suite1 = module1.TheTestSuite()373suite2 = module2.TheTestSuite()374alltests = unittest.TestSuite([suite1, suite2])375```376377Определения тестовых случаев и наборов тестов можно размещать в тех же модулях, что и тестируемый код (например, `widget.py`), но есть несколько преимуществ в размещении тестового кода в отдельном модуле, например, `test_widget.py`:378379- Тестовый модуль можно запускать автономно из командной строки.380- Тестовый код проще отделить от поставляемого кода.381- Меньше соблазна изменять тестовый код, чтобы подогнать его под тестируемый код, без веской причины.382- Тестовый код должен изменяться гораздо реже, чем тестируемый код.383- Тестируемый код проще поддаётся рефакторингу.384- Тесты для модулей, написанных на C, всё равно должны быть в отдельных модулях – так почему бы не придерживаться этого подхода?385- Если стратегия тестирования меняется, нет необходимости изменять исходный код.386387## 25.3.5. Повторное использование старого тестового кода388389Некоторые пользователи могут иметь существующий тестовый код, который они хотели бы запускать из [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), не преобразовывая каждую старую тестовую функцию в подкласс [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase).390391По этой причине [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет класс [`FunctionTestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.FunctionTestCase). Этот подкласс [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) можно использовать для обёртывания существующей тестовой функции. Также можно предоставить функции настройки (set-up) и завершения (tear-down).392393Рассмотрим следующую тестовую функцию:394395```python396def testSomething():397    something = makeSomething()398    assert something.name is not None399    # ...400```401402можно создать эквивалентный экземпляр тестового случая следующим образом:403404```python405testcase = unittest.FunctionTestCase(testSomething)406```407408Если есть дополнительные методы настройки и очистки, которые должны вызываться в рамках работы тестового случая, их также можно предоставить следующим образом:409410```python411testcase = unittest.FunctionTestCase(testSomething,412                                     setUp=makeSomethingDB,413                                     tearDown=deleteSomethingDB)414```415416Чтобы упростить миграцию существующих тестовых наборов, [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) поддерживает тесты, возбуждающие [`AssertionError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.AssertionError) для указания неудачи теста. Однако рекомендуется вместо этого использовать явные методы `TestCase.fail*()` и `TestCase.assert*()`, поскольку будущие версии [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) могут обрабатывать [`AssertionError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.AssertionError) иначе.417418> **Примечание**419>420> Хотя [`FunctionTestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.FunctionTestCase) можно использовать для быстрого преобразования существующей тестовой базы в систему на основе [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), этот подход не рекомендуется. Затрата времени на создание правильных подклассов [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) значительно упростит будущий рефакторинг тестов.421422В некоторых случаях существующие тесты могли быть написаны с использованием модуля [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest). В этом случае [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest) предоставляет класс `DocTestSuite`, который может автоматически создавать экземпляры [`unittest.TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) из существующих тестов на основе [`doctest`](https://python-all.ru/2.7/library/doctest.html#module-doctest).423424## 25.3.6. Пропуск тестов и ожидаемые сбои425426Новое в версии 2.7.427428Unittest поддерживает пропуск отдельных тестовых методов и даже целых классов тестов. Кроме того, он поддерживает пометку теста как «ожидаемый сбой» – тест, который сломан и завершится неудачей, но не должен засчитываться как сбой в [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult).429430Пропустить тест можно просто с помощью [`skip()`](https://python-all.ru/2.7/library/unittest.html#unittest.skip) [декоратора](https://python-all.ru/2.7/glossary.html#term-decorator) или одного из его условных вариантов.431432Базовый пропуск выглядит так:433434```python435class MyTestCase(unittest.TestCase):436437    @unittest.skip("demonstrating skipping")438    def test_nothing(self):439        self.fail("shouldn't happen")440441    @unittest.skipIf(mylib.__version__ < (1, 3),442                     "not supported in this library version")443    def test_format(self):444        # Тесты, которые работают только для определённой версии библиотеки.445        pass446447    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")448    def test_windows_support(self):449        # код тестирования для Windows450        pass451```452453Это вывод приведённого выше примера в подробном режиме:454455```python456test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'457test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'458test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'459460----------------------------------------------------------------------461Ran 3 tests in 0.005s462463OK (skipped=3)464```465466Классы можно пропускать так же, как методы:467468```python469@unittest.skip("showing class skipping")470class MySkippedTestCase(unittest.TestCase):471    def test_not_run(self):472        pass473```474475[`TestCase.setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) также может пропустить тест. Это полезно, когда ресурс, который необходимо настроить, недоступен.476477Для ожидаемых сбоев используется декоратор [`expectedFailure()`](https://python-all.ru/2.7/library/unittest.html#unittest.expectedFailure).478479```python480class ExpectedFailureTestCase(unittest.TestCase):481    @unittest.expectedFailure482    def test_fail(self):483        self.assertEqual(1, 0, "broken")484```485486Легко создать собственные декораторы пропуска, создав декоратор, который вызывает [`skip()`](https://python-all.ru/2.7/library/unittest.html#unittest.skip) для теста, когда нужно его пропустить. Этот декоратор пропускает тест, если только переданный объект не имеет определённого атрибута:487488```python489def skipUnlessHasattr(obj, attr):490    if hasattr(obj, attr):491        return lambda func: func492    return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))493```494495Следующие декораторы реализуют пропуск тестов и ожидаемые сбои:496497#### `unittest.skip(reason)`498499Безусловно пропускает декорированный тест. Параметр *reason* должен описывать причину пропуска теста.500501#### `unittest.skipIf(condition, reason)`502503Пропустить декорированный тест, если *condition* истинно.504505#### `unittest.skipUnless(condition, reason)`506507Пропустить декорированный тест, если *condition* не истинно.508509#### `unittest.expectedFailure()`510511Помечает тест как ожидаемый сбой. Если тест завершается ошибкой при запуске, он не учитывается как сбой.512513#### `exception unittest.SkipTest(reason)`514515Это исключение возбуждается для пропуска теста.516517Обычно можно использовать [`TestCase.skipTest()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.skipTest) или один из декораторов пропуска, вместо того чтобы возбуждать его напрямую.518519Пропущенные тесты не будут иметь запуска `setUp()` или `tearDown()` вокруг них. Пропущенные классы не будут иметь запуска `setUpClass()` или `tearDownClass()`.520521## 25.3.7. Классы и функции522523В этом разделе подробно описывается API [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest).524525### 25.3.7.1. Тестовые случаи526527#### `class unittest.TestCase(methodName='runTest')`528529Экземпляры класса [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) представляют наименьшие тестируемые единицы во вселенной [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest). Этот класс предназначен для использования в качестве базового класса, при этом конкретные тесты реализуются конкретными подклассами. Класс реализует интерфейс, необходимый тестовому раннеру для управления тестом, а также методы, которые тестовый код может использовать для проверки и сообщения о различных видах неудач.530531Каждый экземпляр [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) выполняет один тестовый метод – метод с именем *methodName*. Ранее был пример, который выглядел примерно так:532533```python534def suite():535    suite = unittest.TestSuite()536    suite.addTest(WidgetTestCase('test_default_size'))537    suite.addTest(WidgetTestCase('test_resize'))538    return suite539```540541Здесь создаются два экземпляра `WidgetTestCase`, каждый из которых выполняет один тест.542543*methodName* по умолчанию равен `runTest()`.544545Экземпляры [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) предоставляют три группы методов: одна группа используется для выполнения теста, другая – реализацией теста для проверки условий и сообщения о сбоях, и несколько запросных методов, позволяющих собирать информацию о самом тесте.546547Методы первой группы (выполнение теста):548549#### `setUp()`550551Метод, вызываемый для подготовки тестовой фикстуры. Он вызывается непосредственно перед вызовом тестового метода; за исключением [`AssertionError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.AssertionError) или [`SkipTest`](https://python-all.ru/2.7/library/unittest.html#unittest.SkipTest), любое исключение, возбуждённое этим методом, будет считаться ошибкой, а не сбоем теста. Реализация по умолчанию ничего не делает.552553#### `tearDown()`554555Метод, вызываемый сразу после вызова тестового метода и записи результата. Он вызывается, даже если тестовый метод возбудил исключение, поэтому реализация в подклассах должна быть особенно осторожна при проверке внутреннего состояния. Любое исключение, кроме [`AssertionError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.AssertionError) или [`SkipTest`](https://python-all.ru/2.7/library/unittest.html#unittest.SkipTest), возбуждённое этим методом, будет считаться дополнительной ошибкой, а не сбоем теста (таким образом увеличивая общее количество сообщённых ошибок). Этот метод будет вызван только если [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) выполнится успешно, независимо от результата тестового метода. Реализация по умолчанию ничего не делает.556557#### `setUpClass()`558559Метод класса, вызываемый перед выполнением тестов в отдельном классе. `setUpClass` вызывается с классом в качестве единственного аргумента и должен быть декорирован как [`classmethod()`](https://python-all.ru/2.7/library/functions.html#classmethod):560561```python562@classmethod563def setUpClass(cls):564    ...565```566567См. [Фикстуры классов и модулей](https://python-all.ru/2.7/library/unittest.html#class-and-module-fixtures) для получения дополнительных сведений.568569Новое в версии 2.7.570571#### `tearDownClass()`572573Метод класса, вызываемый после выполнения тестов в отдельном классе. `tearDownClass` вызывается с классом в качестве единственного аргумента и должен быть декорирован как [`classmethod()`](https://python-all.ru/2.7/library/functions.html#classmethod):574575```python576@classmethod577def tearDownClass(cls):578    ...579```580581См. [Фикстуры классов и модулей](https://python-all.ru/2.7/library/unittest.html#class-and-module-fixtures) для получения дополнительных сведений.582583Новое в версии 2.7.584585#### `run(result=None)`586587Запускает тест, собирая результат в объект результата теста, переданный как *result*. Если *result* опущен или равен `None`, создаётся временный объект результата (вызовом метода [`defaultTestResult()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.defaultTestResult)) и используется. Объект результата не возвращается вызвавшему [`run()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.run).588589Того же эффекта можно добиться простым вызовом экземпляра [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase).590591#### `skipTest(reason)`592593Вызов этого метода внутри тестового метода или [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) пропускает текущий тест. Подробнее см. [Пропуск тестов и ожидаемые сбои](https://python-all.ru/2.7/library/unittest.html#unittest-skipping).594595Новое в версии 2.7.596597#### `debug()`598599Запускает тест без сбора результата. Это позволяет исключениям, возникшим в тесте, распространяться до вызывающего кода, и может использоваться для поддержки запуска тестов под отладчиком.600601Класс [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) предоставляет несколько методов assert для проверки и сообщения об ошибках. В следующей таблице перечислены наиболее часто используемые методы (см. таблицы ниже для получения дополнительных методов assert):602603| Метод | Проверяет, что | Новое в |604| --- | --- | --- |605| [`assertEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual) | `a == b` |  |606| [`assertNotEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotEqual) | `a != b` |  |607| [`assertTrue(x)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertTrue) | `bool(x) is True` |  |608| [`assertFalse(x)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertFalse) | `bool(x) is False` |  |609| [`assertIs(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIs) | `a is b` | 2.7 |610| [`assertIsNot(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIsNot) | `a is not b` | 2.7 |611| [`assertIsNone(x)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIsNone) | `x is None` | 2.7 |612| [`assertIsNotNone(x)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIsNotNone) | `x is not None` | 2.7 |613| [`assertIn(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIn) | `a in b` | 2.7 |614| [`assertNotIn(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotIn) | `a not in b` | 2.7 |615| [`assertIsInstance(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIsInstance) | `isinstance(a, b)` | 2.7 |616| [`assertNotIsInstance(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotIsInstance) | `not isinstance(a, b)` | 2.7 |617618Все assert-методы (кроме [`assertRaises()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises), [`assertRaisesRegexp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaisesRegexp)) принимают аргумент *msg*, который, если указан, используется как сообщение об ошибке в случае неудачи (см. также [`longMessage`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.longMessage)).619620#### `assertEqual(first, second, msg=None)`621622Проверяет, что *first* и *second* равны. Если значения не равны, тест завершится неудачей.623624Кроме того, если *first* и *second* одного и того же типа и этот тип – list, tuple, dict, set, frozenset, unicode или любой тип, который подкласс регистрирует с помощью [`addTypeEqualityFunc()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.addTypeEqualityFunc), то будет вызвана типозависимая функция сравнения, чтобы сформировать более полезное сообщение об ошибке по умолчанию (см. также [список типозависимых методов](https://python-all.ru/2.7/library/unittest.html#type-specific-methods)).625626Изменено в версии 2.7: Добавлен автоматический вызов типозависимой функции сравнения.627628#### `assertNotEqual(first, second, msg=None)`629630Проверяет, что *first* и *second* не равны. Если значения равны, тест завершится неудачей.631632#### `assertTrue(expr, msg=None)`633634#### `assertFalse(expr, msg=None)`635636Проверяет, что *expr* истинно (или ложно).637638Обратите внимание, что это эквивалентно `bool(expr) is True`, а не `expr is True` (для последнего используйте `assertIs(expr, True)`). Этот метод также следует избегать, если доступны более специфические методы (например, `assertEqual(a, b)` вместо `assertTrue(a == b)`), потому что они предоставляют более информативное сообщение об ошибке в случае сбоя.639640#### `assertIs(first, second, msg=None)`641642#### `assertIsNot(first, second, msg=None)`643644Проверяет, что *first* и *second* являются (или не являются) одним и тем же объектом.645646Новое в версии 2.7.647648#### `assertIsNone(expr, msg=None)`649650#### `assertIsNotNone(expr, msg=None)`651652Проверяет, что *expr* является (или не является) `None`.653654Новое в версии 2.7.655656#### `assertIn(first, second, msg=None)`657658#### `assertNotIn(first, second, msg=None)`659660Проверяет, находится ли *first* в *second* (или не находится).661662Новое в версии 2.7.663664#### `assertIsInstance(obj, cls, msg=None)`665666#### `assertNotIsInstance(obj, cls, msg=None)`667668Проверяет, что *obj* является (или не является) экземпляром *cls* (который может быть классом или кортежем классов, как поддерживается [`isinstance()`](https://python-all.ru/2.7/library/functions.html#isinstance)). Для проверки точного типа используйте [`assertIs(type(obj), cls)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertIs).669670Новое в версии 2.7.671672Также можно проверить, что исключения и предупреждения возбуждаются с помощью следующих методов:673674| Метод | Проверяет, что | Новое в |675| --- | --- | --- |676| [`assertRaises(exc, fun, *args, **kwds)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises) | `fun(*args, **kwds)` возбуждает *exc* |  |677| [`assertRaisesRegexp(exc, r, fun, *args, **kwds)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaisesRegexp) | `fun(*args, **kwds)` возбуждает *exc* и сообщение соответствует регулярному выражению *r* | 2.7 |678679#### `assertRaises(exception, callable, *args, **kwds)`680681#### `assertRaises(exception)`682683Проверяет, что исключение возбуждается, когда *callable* вызывается с любыми позиционными или именованными аргументами, которые также передаются в [`assertRaises()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises). Тест проходит, если возбуждается *исключение*, считается ошибкой, если возбуждается другое исключение, или не проходит, если исключение не возбуждается. Чтобы перехватить любое из группы исключений, можно передать кортеж, содержащий классы исключений, как *исключение*.684685Если указан только аргумент *исключение*, возвращается контекстный менеджер, так что тестируемый код можно писать встроенно, а не в виде функции:686687```python688with self.assertRaises(SomeException):689    do_something()690```691692Менеджер контекста сохраняет перехваченный объект исключения в своём атрибуте `exception`. Это может быть полезно, если нужно выполнить дополнительные проверки возникшего исключения:693694```python695with self.assertRaises(SomeException) as cm:696    do_something()697698the_exception = cm.exception699self.assertEqual(the_exception.error_code, 3)700```701702Изменено в версии 2.7: Добавлена возможность использовать [`assertRaises()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises) в качестве менеджера контекста.703704#### `assertRaisesRegexp(exception, regexp, callable, *args, **kwds)`705706#### `assertRaisesRegexp(exception, regexp)`707708Как [`assertRaises()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises), но также проверяет, что *regexp* соответствует строковому представлению возбуждённого исключения. *regexp* может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, подходящей для использования с [`re.search()`](https://python-all.ru/2.7/library/re.html#re.search). Примеры:709710```python711self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$",712                        int, 'XYZ')713```714715или:716717```python718with self.assertRaisesRegexp(ValueError, 'literal'):719   int('XYZ')720```721722Новое в версии 2.7.723724Существуют также другие методы для выполнения более специфических проверок, например:725726| Метод | Проверяет, что | Новое в |727| --- | --- | --- |728| [`assertAlmostEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertAlmostEqual) | `round(a-b, 7) == 0` |  |729| [`assertNotAlmostEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotAlmostEqual) | `round(a-b, 7) != 0` |  |730| [`assertGreater(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertGreater) | `a > b` | 2.7 |731| [`assertGreaterEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertGreaterEqual) | `a >= b` | 2.7 |732| [`assertLess(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertLess) | `a < b` | 2.7 |733| [`assertLessEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertLessEqual) | `a <= b` | 2.7 |734| [`assertRegexpMatches(s, r)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRegexpMatches) | `r.search(s)` | 2.7 |735| [`assertNotRegexpMatches(s, r)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotRegexpMatches) | `not r.search(s)` | 2.7 |736| [`assertItemsEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertItemsEqual) | sorted(a) == sorted(b) и работает с нехешируемыми объектами | 2.7 |737| [`assertDictContainsSubset(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertDictContainsSubset) | все пары ключ/значение в *a* присутствуют в *b* | 2.7 |738739#### `assertAlmostEqual(first, second, places=7, msg=None, delta=None)`740741#### `assertNotAlmostEqual(first, second, places=7, msg=None, delta=None)`742743Проверяет, что *first* и *second* приблизительно равны (или не равны), вычисляя разность, округляя до заданного числа десятичных знаков *places* (по умолчанию 7) и сравнивая с нулём. Обратите внимание, что эти методы округляют значения до заданного числа *десятичных знаков* (т.е. как функция [`round()`](https://python-all.ru/2.7/library/functions.html#round)), а не до *значащих цифр*.744745Если указан *delta* вместо *places*, то разность между *first* и *second* должна быть меньше или равна (или больше) *delta*.746747Одновременная передача *delta* и *places* вызывает `TypeError`.748749Изменено в версии 2.7: [`assertAlmostEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertAlmostEqual) автоматически считает почти равными объекты, которые сравниваются как равные. [`assertNotAlmostEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotAlmostEqual) автоматически завершается неудачей, если объекты сравниваются как равные. Добавлен именованный аргумент *delta*.750751#### `assertGreater(first, second, msg=None)`752753#### `assertGreaterEqual(first, second, msg=None)`754755#### `assertLess(first, second, msg=None)`756757#### `assertLessEqual(first, second, msg=None)`758759Проверяет, что *first* соответственно \>, \>=, \< или \<= по отношению к *second* в зависимости от имени метода. Если это не так, тест завершается ошибкой:760761```python762>>> self.assertGreaterEqual(3, 4)763AssertionError: "3" unexpectedly not greater than or equal to "4"764```765766Новое в версии 2.7.767768#### `assertRegexpMatches(text, regexp, msg=None)`769770Проверяет, что поиск по *regexp* соответствует *text*. В случае неудачи сообщение об ошибке будет содержать шаблон и *text* (или шаблон и ту часть *text*, которая неожиданно совпала). *regexp* может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодное для использования с [`re.search()`](https://python-all.ru/2.7/library/re.html#re.search).771772Новое в версии 2.7.773774#### `assertNotRegexpMatches(text, regexp, msg=None)`775776Проверяет, что поиск по *regexp* не соответствует *text*. Завершается с ошибкой, сообщение которой содержит шаблон и ту часть *text*, которая совпала. *regexp* может быть объектом регулярного выражения или строкой, содержащей регулярное выражение, пригодное для использования с [`re.search()`](https://python-all.ru/2.7/library/re.html#re.search).777778Новое в версии 2.7.779780#### `assertItemsEqual(actual, expected, msg=None)`781782Проверяет, что последовательность *expected* содержит те же элементы, что и *actual*, независимо от их порядка. Если это не так, будет сгенерировано сообщение об ошибке, перечисляющее различия между последовательностями.783784Дублирующиеся элементы *не* игнорируются при сравнении *actual* и *expected*. Проверяется, что каждый элемент встречается одинаковое количество раз в обеих последовательностях. Это эквивалент `assertEqual(sorted(expected), sorted(actual))`, но работает также с последовательностями нехешируемых объектов.785786В Python 3 этот метод называется `assertCountEqual`.787788Новое в версии 2.7.789790#### `assertDictContainsSubset(expected, actual, msg=None)`791792Проверяет, являются ли пары ключ/значение в словаре *actual* надмножеством пар в *expected*. Если нет, создаётся сообщение об ошибке со списком отсутствующих ключей и несовпадающих значений.793794Новое в версии 2.7.795796Устарело с версии 3.2.797798Метод [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual) направляет проверку равенства для объектов одного типа к различным методам, специфичным для типа. Эти методы уже реализованы для большинства встроенных типов, но также можно зарегистрировать новые методы с помощью [`addTypeEqualityFunc()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.addTypeEqualityFunc):799800#### `addTypeEqualityFunc(typeobj, function)`801802Регистрирует метод, специфичный для типа, вызываемый с помощью [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual) для проверки, равны ли два объекта одного и того же *typeobj* (не подклассы). *function* должен принимать два позиционных аргумента и третий именованный аргумент msg=None, как и [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual). Он должен вызывать [`self.failureException(msg)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.failureException) при обнаружении неравенства между первыми двумя параметрами – возможно, предоставляя полезную информацию и подробно объясняя неравенства в сообщении об ошибке.803804Новое в версии 2.7.805806Список типовых методов, автоматически используемых [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual), приведён в следующей таблице. Обратите внимание, что обычно нет необходимости вызывать эти методы напрямую.807808| Метод | Используется для сравнения | Новое в |809| --- | --- | --- |810| [`assertMultiLineEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertMultiLineEqual) | строки | 2.7 |811| [`assertSequenceEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertSequenceEqual) | последовательности | 2.7 |812| [`assertListEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertListEqual) | списки | 2.7 |813| [`assertTupleEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertTupleEqual) | кортежи | 2.7 |814| [`assertSetEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertSetEqual) | множества или неизменяемые множества | 2.7 |815| [`assertDictEqual(a, b)`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertDictEqual) | словари | 2.7 |816817#### `assertMultiLineEqual(first, second, msg=None)`818819Проверяет, что многострочная строка *first* равна строке *second*. Если строки не равны, в сообщение об ошибке будет включена разница между двумя строками с подсветкой различий. Этот метод используется по умолчанию при сравнении строк Unicode с [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual).820821Новое в версии 2.7.822823#### `assertSequenceEqual(seq1, seq2, msg=None, seq_type=None)`824825Проверяет, что две последовательности равны. Если указан *seq\_type*, то и *seq1*, и *seq2* должны быть экземплярами *seq\_type*, иначе возникнет ошибка. Если последовательности различаются, формируется сообщение об ошибке, показывающее разницу между ними.826827Этот метод не вызывается напрямую методом [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual), но используется для реализации [`assertListEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertListEqual) и [`assertTupleEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertTupleEqual).828829Новое в версии 2.7.830831#### `assertListEqual(list1, list2, msg=None)`832833#### `assertTupleEqual(tuple1, tuple2, msg=None)`834835Проверяет, что два списка или кортежа равны. Если нет, формируется сообщение об ошибке, показывающее только различия между ними. Ошибка также возникает, если один из параметров имеет неверный тип. Эти методы используются по умолчанию при сравнении списков или кортежей с помощью [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual).836837Новое в версии 2.7.838839#### `assertSetEqual(set1, set2, msg=None)`840841Проверяет, что два множества равны. Если нет, формируется сообщение об ошибке, перечисляющее различия между множествами. Этот метод используется по умолчанию при сравнении множеств или неизменяемых множеств с помощью [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual).842843Завершается ошибкой, если хотя бы одно из *set1* или *set2* не имеет метода `set.difference()`.844845Новое в версии 2.7.846847#### `assertDictEqual(expected, actual, msg=None)`848849Проверяет, что два словаря равны. Если нет, формируется сообщение об ошибке, показывающее различия в словарях. Этот метод будет использоваться по умолчанию для сравнения словарей в вызовах [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual).850851Новое в версии 2.7.852853Наконец, [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) предоставляет следующие методы и атрибуты:854855#### `fail(msg=None)`856857Безусловно сигнализирует о сбое теста, используя *msg* или `None` в качестве сообщения об ошибке.858859#### `failureException`860861Этот атрибут класса задаёт исключение, которое вызывается тестовым методом. Если тестовому фреймворку требуется использовать специализированное исключение, возможно, для передачи дополнительной информации, он должен создать подкласс этого исключения, чтобы «честно играть» с фреймворком. Начальное значение этого атрибута – [`AssertionError`](https://python-all.ru/2.7/library/exceptions.html#exceptions.AssertionError).862863#### `longMessage`864865Если установлено в `True`, то любое явное сообщение об ошибке, переданное в [методы assert](https://python-all.ru/2.7/library/unittest.html#assert-methods), будет добавлено в конец обычного сообщения об ошибке. Обычные сообщения содержат полезную информацию об объектах, например, сообщение от assertEqual показывает repr двух неравных объектов. Установка этого атрибута в `True` позволяет иметь собственное сообщение об ошибке в дополнение к обычному.866867По умолчанию этот атрибут равен `False`, что означает, что собственное сообщение, переданное в метод assert, подавляет обычное сообщение.868869Настройку класса можно переопределить в отдельных тестах, присвоив атрибуту экземпляра значение `True` или `False` перед вызовом методов assert.870871Новое в версии 2.7.872873#### `maxDiff`874875Этот атрибут управляет максимальной длиной вывода различий, выводимых методами утверждения, которые сообщают о различиях при неудаче. По умолчанию – 80\*8 символов. Методы утверждения, на которые влияет этот атрибут: [`assertSequenceEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertSequenceEqual) (включая все методы сравнения последовательностей, которые делегируют ему), [`assertDictEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertDictEqual) и [`assertMultiLineEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertMultiLineEqual).876877Установка `maxDiff` в `None` означает, что максимальная длина различий не ограничена.878879Новое в версии 2.7.880881Тестовые фреймворки могут использовать следующие методы для сбора информации о тесте:882883#### `countTestCases()`884885Возвращает количество тестов, представленных этим тестовым объектом. Для экземпляров [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) это всегда будет `1`.886887#### `defaultTestResult()`888889Возвращает экземпляр класса результата теста, который следует использовать для данного класса тестового случая (если ни один другой экземпляр результата не был передан методу [`run()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.run)).890891Для экземпляров [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) это всегда будет экземпляр [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult); подклассы [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) должны при необходимости переопределять это.892893#### `id()`894895Возвращает строку, идентифицирующую конкретный тестовый случай. Обычно это полное имя тестового метода, включая имя модуля и класса.896897#### `shortDescription()`898899Возвращает описание теста или `None`, если описание не было предоставлено. Реализация по умолчанию этого метода возвращает первую строку докстринга тестового метода, если он доступен, или [`None`](https://python-all.ru/2.7/library/constants.html#None).900901#### `addCleanup(function, *args, **kwargs)`902903Добавляет функцию, которая будет вызвана после [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown) для освобождения ресурсов, используемых во время теста. Функции вызываются в порядке, обратном порядку их добавления (LIFO). Они вызываются с теми аргументами и именованными аргументами, которые были переданы в [`addCleanup()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.addCleanup) при добавлении.904905Если [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) завершается неудачей, то есть [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown) не вызывается, любые добавленные функции очистки всё равно будут вызваны.906907Новое в версии 2.7.908909#### `doCleanups()`910911Этот метод вызывается безусловно после [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown) или после [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp), если [`setUp()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.setUp) вызывает исключение.912913Он отвечает за вызов всех функций очистки, добавленных с помощью [`addCleanup()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.addCleanup). Если необходимо, чтобы функции очистки вызывались *до* [`tearDown()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.tearDown), то можно вызвать [`doCleanups()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.doCleanups) самостоятельно.914915[`doCleanups()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.doCleanups) извлекает методы из стека функций очистки по одному, поэтому его можно вызывать в любой момент.916917Новое в версии 2.7.918919#### `class unittest.FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)`920921Этот класс реализует ту часть интерфейса [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), которая позволяет исполнителю тестов управлять тестом, но не предоставляет методов, которые тестовый код может использовать для проверки и сообщения об ошибках. Это используется для создания тестовых примеров с использованием устаревшего тестового кода, что позволяет интегрировать его в тестовую среду на основе [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest).922923#### 25.3.7.1.1. Устаревшие псевдонимы924925По историческим причинам некоторые методы [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) имели один или несколько псевдонимов, которые сейчас устарели. В следующей таблице приведены корректные названия вместе с их устаревшими псевдонимами:926927> | Имя метода | Устаревшие псевдонимы |928> | --- | --- |929> | [`assertEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertEqual) | failUnlessEqual, assertEquals |930> | [`assertNotEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotEqual) | failIfEqual |931> | [`assertTrue()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertTrue) | failUnless, assert\_ |932> | [`assertFalse()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertFalse) | failIf |933> | [`assertRaises()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertRaises) | failUnlessRaises |934> | [`assertAlmostEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertAlmostEqual) | failUnlessAlmostEqual |935> | [`assertNotAlmostEqual()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.assertNotAlmostEqual) | failIfAlmostEqual |936>937> Устарело с версии 2.7: псевдонимы, перечисленные во втором столбце938939### 25.3.7.2. Группировка тестов940941#### `class unittest.TestSuite(tests=())`942943Этот класс представляет собой агрегацию отдельных тестовых примеров и тестовых наборов. Класс предоставляет интерфейс, необходимый исполнителю тестов, чтобы его можно было запускать как любой другой тестовый пример. Запуск экземпляра [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) равносилен итерации по набору с запуском каждого теста по отдельности.944945Если задан *tests*, он должен быть итерабельным объектом, содержащим отдельные тестовые примеры или другие тестовые наборы, которые будут использоваться для первоначального построения набора. Дополнительные методы предоставляются для добавления тестовых примеров и наборов в коллекцию позже.946947Объекты [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) ведут себя во многом как объекты [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), за исключением того, что они не реализуют фактический тест. Вместо этого они используются для объединения тестов в группы, которые должны запускаться вместе. Некоторые дополнительные методы доступны для добавления тестов в экземпляры [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite):948949#### `addTest(test)`950951Добавляет [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) или [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) в набор.952953#### `addTests(tests)`954955Добавляет все тесты из итерабельного объекта, содержащего экземпляры [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite), в этот тестовый набор.956957Это эквивалентно итерации по *tests* с вызовом [`addTest()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite.addTest) для каждого элемента.958959[`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) разделяет следующие методы с [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase):960961#### `run(result)`962963Запускает тесты, связанные с этим набором, собирая результат в объект результата теста, переданный как *result*. Обратите внимание, что, в отличие от [`TestCase.run()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase.run), [`TestSuite.run()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite.run) требует, чтобы объект результата был передан.964965#### `debug()`966967Запускает тесты, связанные с этим набором, без сбора результата. Это позволяет исключениям, возбуждённым тестом, распространяться до вызывающего кода и может использоваться для поддержки запуска тестов под отладчиком.968969#### `countTestCases()`970971Возвращает количество тестов, представленных этим тестовым объектом, включая все отдельные тесты и поднаборы.972973#### `__iter__()`974975Тесты, сгруппированные с помощью [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite), всегда доступны через итерацию. Подклассы могут лениво предоставлять тесты, переопределяя [`__iter__()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite.__iter__). Обратите внимание, что этот метод может быть вызван несколько раз для одного набора тестов (например, при подсчёте тестов или сравнении на равенство), поэтому возвращаемые тесты должны быть одинаковыми при повторных итерациях.976977Изменено в версии 2.7: В более ранних версиях [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) обращался к тестам напрямую, а не через итерацию, поэтому переопределения [`__iter__()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite.__iter__) было недостаточно для предоставления тестов.978979При типичном использовании объекта [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) метод [`run()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite.run) вызывается с помощью `TestRunner`, а не через тестовую оболочку конечного пользователя.980981### 25.3.7.3. Загрузка и запуск тестов982983#### `class unittest.TestLoader`984985Класс [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader) используется для создания тестовых наборов из классов и модулей. Обычно нет необходимости создавать экземпляр этого класса; модуль [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest) предоставляет экземпляр, который можно использовать совместно как [`unittest.defaultTestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.defaultTestLoader). Однако использование подкласса или экземпляра позволяет настраивать некоторые конфигурируемые свойства.986987Объекты [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader) имеют следующие методы:988989#### `loadTestsFromTestCase(testCaseClass)`990991Возвращает набор всех тестов, содержащихся в `testCaseClass`, производном от [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase).992993#### `loadTestsFromModule(module)`994995Возвращает набор всех тестовых случаев, содержащихся в данном модуле. Этот метод ищет в *module* классы, производные от [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), и создаёт экземпляр класса для каждого тестового метода, определённого для этого класса.996997> **Примечание**998>999> Хотя использование иерархии классов, производных от [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), может быть удобным для совместного использования фикстур и вспомогательных функций, определение тестовых методов в базовых классах, которые не предназначены для прямого создания экземпляров, плохо сочетается с этим методом. Однако это может быть полезно, когда фикстуры различаются и определены в подклассах.10001001Если модуль предоставляет функцию `load_tests`, она будет вызвана для загрузки тестов. Это позволяет модулям настраивать загрузку тестов. Это [протокол load\_tests](https://python-all.ru/2.7/library/unittest.html#load-tests-protocol).10021003Изменено в версии 2.7: Добавлена поддержка `load_tests`.10041005#### `loadTestsFromName(name, module=None)`10061007Возвращает набор всех тестовых случаев по заданному строковому спецификатору.10081009Спецификатор *name* – это «точечное имя», которое может указывать на модуль, класс тестового случая, тестовый метод внутри класса тестового случая, экземпляр [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) или вызываемый объект, возвращающий экземпляр [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) или [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite). Эти проверки применяются в указанном порядке; то есть метод в возможном классе тестового случая будет распознан как «тестовый метод внутри класса тестового случая», а не как «вызываемый объект».10101011Например, если у вас есть модуль `SampleTests`, содержащий класс `SampleTestCase`, производный от [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), с тремя тестовыми методами (`test_one()`, `test_two()` и `test_three()`), спецификатор `'SampleTests.SampleTestCase'` заставит этот метод вернуть набор, который выполнит все три тестовых метода. Использование спецификатора `'SampleTests.SampleTestCase.test_two'` приведёт к возврату тестового набора, который выполнит только тестовый метод `test_two()`. Спецификатор может ссылаться на модули и пакеты, которые не были импортированы; они будут импортированы как побочный эффект.10121013Метод опционально разрешает *name* относительно заданного *module*.10141015#### `loadTestsFromNames(names, module=None)`10161017Аналогичен [`loadTestsFromName()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader.loadTestsFromName), но принимает последовательность имён, а не одно имя. Возвращаемое значение – тестовый набор, который включает все тесты, определённые для каждого имени.10181019#### `getTestCaseNames(testCaseClass)`10201021Возвращает отсортированную последовательность имён методов, найденных в *testCaseClass*; это должен быть подкласс [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase).10221023#### `discover(start_dir, pattern='test*.py', top_level_dir=None)`10241025Находит все тестовые модули, рекурсивно обходя подкаталоги, начиная с указанного каталога, и возвращает объект TestSuite, содержащий их. Будут загружены только тестовые файлы, соответствующие *pattern*. (Используется сопоставление с образцом в стиле shell.) Будут загружены только имена модулей, которые можно импортировать (т.е. являются допустимыми идентификаторами Python).10261027Все тестовые модули должны быть импортируемыми из корневого каталога проекта. Если стартовый каталог не является корневым, то корневой каталог необходимо указать отдельно.10281029Если импорт модуля завершается неудачей, например из-за синтаксической ошибки, то это будет записано как одна ошибка, и обнаружение продолжится.10301031Если имя тестового пакета (каталог с `__init__.py`) соответствует шаблону, то пакет проверяется на наличие функции `load_tests`. Если она существует, то она вызывается с *loader*, *tests*, *pattern*.10321033Если load\_tests существует, то обнаружение *не* рекурсивно обходит пакет, `load_tests` отвечает за загрузку всех тестов в пакете.10341035Шаблон намеренно не хранится как атрибут загрузчика, чтобы пакеты могли продолжать самостоятельное обнаружение. *top\_level\_dir* сохраняется, поэтому `load_tests` не нужно передавать этот аргумент в `loader.discover()`.10361037*start\_dir* может быть как точечным именем модуля, так и каталогом.10381039Новое в версии 2.7.10401041Следующие атрибуты [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader) можно настроить либо через наследование, либо через присваивание экземпляру:10421043#### `testMethodPrefix`10441045Строка, задающая префикс имён методов, которые будут интерпретироваться как тестовые методы. Значение по умолчанию – `'test'`.10461047Это влияет на [`getTestCaseNames()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader.getTestCaseNames) и все методы `loadTestsFrom*()`.10481049#### `sortTestMethodsUsing`10501051Функция для сравнения имён методов при их сортировке в [`getTestCaseNames()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader.getTestCaseNames) и во всех методах `loadTestsFrom*()`. Значение по умолчанию – встроенная функция [`cmp()`](https://python-all.ru/2.7/library/functions.html#cmp); атрибут также может быть установлен в [`None`](https://python-all.ru/2.7/library/constants.html#None) для отключения сортировки.10521053#### `suiteClass`10541055Вызываемый объект, который создаёт тестовый набор из списка тестов. Никакие методы результирующего объекта не требуются. Значение по умолчанию – класс [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite).10561057Это влияет на все методы `loadTestsFrom*()`.10581059#### `class unittest.TestResult`10601061Этот класс используется для сбора информации о том, какие тесты прошли успешно, а какие завершились неудачей.10621063Объект [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult) хранит результаты набора тестов. Классы [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite) обеспечивают правильную запись результатов; авторам тестов не нужно беспокоиться о записи результатов тестов.10641065Тестовые фреймворки, построенные на базе [`unittest`](https://python-all.ru/2.7/library/unittest.html#module-unittest), могут нуждаться в доступе к объекту [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult), созданному при запуске набора тестов для целей отчетности; для этого метод `TestRunner.run()` возвращает экземпляр [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult).10661067Экземпляры [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult) имеют следующие атрибуты, которые будут интересны при проверке результатов запуска набора тестов:10681069#### `errors`10701071Список, содержащий 2-кортежи экземпляров [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и строк с форматированными трассировками. Каждый кортеж представляет тест, вызвавший неожиданное исключение.10721073Изменено в версии 2.2: Содержит форматированные трассировки стека вместо результатов [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info).10741075#### `failures`10761077Список, содержащий кортежи из двух элементов: экземпляры [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и строки с форматированными трассировками стека. Каждый кортеж соответствует тесту, в котором сбой был явно зафиксирован с помощью методов `TestCase.assert*()`.10781079Изменено в версии 2.2: Содержит форматированные трассировки стека вместо результатов [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info).10801081#### `skipped`10821083Список, содержащий 2-кортежи экземпляров [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и строк с причиной пропуска теста.10841085Новое в версии 2.7.10861087#### `expectedFailures`10881089Список, содержащий кортежи из двух элементов: экземпляров [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) и строк с форматированными трассировками. Каждый кортеж представляет ожидаемый сбой тестового случая.10901091#### `unexpectedSuccesses`10921093Список, содержащий экземпляры [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), которые были помечены как ожидаемые сбои, но завершились успешно.10941095#### `shouldStop`10961097Устанавливается в `True`, когда выполнение тестов должно быть остановлено с помощью [`stop()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.stop).10981099#### `testsRun`11001101Общее количество запущенных на данный момент тестов.11021103#### `buffer`11041105Если установлено в true, `sys.stdout` и `sys.stderr` будут буферизироваться между вызовами [`startTest()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.startTest) и [`stopTest()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.stopTest). Собранный вывод будет передаваться на реальные `sys.stdout` и `sys.stderr` только в случае сбоя или ошибки теста. Любой вывод также прикрепляется к сообщению о сбое/ошибке.11061107Новое в версии 2.7.11081109#### `failfast`11101111Если установлено в true, [`stop()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.stop) будет вызван при первой ошибке или сбое, останавливая выполнение теста.11121113Новое в версии 2.7.11141115#### `wasSuccessful()`11161117Возвращает `True`, если все запущенные на данный момент тесты пройдены, в противном случае возвращает `False`.11181119#### `stop()`11201121Этот метод может быть вызван, чтобы указать, что выполняемый набор тестов должен быть прерван установкой атрибута [`shouldStop`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.shouldStop) в `True`. Объекты `TestRunner` должны учитывать этот флаг и возвращаться без запуска дополнительных тестов.11221123Например, эта возможность используется классом [`TextTestRunner`](https://python-all.ru/2.7/library/unittest.html#unittest.TextTestRunner) для остановки тестового фреймворка, когда пользователь подает сигнал прерывания с клавиатуры. Интерактивные инструменты, предоставляющие реализации `TestRunner`, могут использовать это аналогичным образом.11241125Следующие методы класса [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult) используются для поддержки внутренних структур данных и могут быть расширены в подклассах для поддержки дополнительных требований к отчетности. Это особенно полезно при создании инструментов, поддерживающих интерактивную отчетность во время выполнения тестов.11261127#### `startTest(test)`11281129Вызывается перед запуском тестового сценария *test*.11301131#### `stopTest(test)`11321133Вызывается после выполнения тестового сценария *test*, независимо от результата.11341135#### `startTestRun()`11361137Вызывается один раз перед выполнением любых тестов.11381139Новое в версии 2.7.11401141#### `stopTestRun()`11421143Вызывается один раз после выполнения всех тестов.11441145Новое в версии 2.7.11461147#### `addError(test, err)`11481149Вызывается, когда тестовый сценарий *test* порождает неожиданное исключение. *err* – кортеж вида, возвращаемого [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info): `(type, value, traceback)`.11501151Реализация по умолчанию добавляет кортеж `(test, formatted_err)` к атрибуту [`errors`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.errors) экземпляра, где *formatted\_err* – форматированная трассировка, полученная из *err*.11521153#### `addFailure(test, err)`11541155Вызывается, когда тестовый сценарий *test* сигнализирует о сбое. *err* – кортеж вида, возвращаемого [`sys.exc_info()`](https://python-all.ru/2.7/library/sys.html#sys.exc_info): `(type, value, traceback)`.11561157Реализация по умолчанию добавляет кортеж `(test, formatted_err)` к атрибуту [`failures`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.failures) экземпляра, где *formatted\_err* – форматированная трассировка, полученная из *err*.11581159#### `addSuccess(test)`11601161Вызывается, когда тестовый сценарий *test* завершается успешно.11621163Реализация по умолчанию ничего не делает.11641165#### `addSkip(test, reason)`11661167Вызывается, когда тестовый сценарий *test* пропускается. *reason* – причина, которую тест указал для пропуска.11681169Реализация по умолчанию добавляет кортеж `(test, reason)` к атрибуту [`skipped`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.skipped) экземпляра.11701171#### `addExpectedFailure(test, err)`11721173Вызывается, когда тестовый случай *test* завершается ошибкой, но был помечен декоратором [`expectedFailure()`](https://python-all.ru/2.7/library/unittest.html#unittest.expectedFailure).11741175Реализация по умолчанию добавляет кортеж `(test, formatted_err)` к атрибуту [`expectedFailures`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.expectedFailures) экземпляра, где *formatted\_err* – форматированная трассировка, полученная из *err*.11761177#### `addUnexpectedSuccess(test)`11781179Вызывается, когда тестовый сценарий *test* был помечен декоратором [`expectedFailure()`](https://python-all.ru/2.7/library/unittest.html#unittest.expectedFailure), но завершился успешно.11801181Реализация по умолчанию добавляет тест к атрибуту [`unexpectedSuccesses`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.unexpectedSuccesses) экземпляра.11821183#### `class unittest.TextTestResult(stream, descriptions, verbosity)`11841185Конкретная реализация [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult), используемая [`TextTestRunner`](https://python-all.ru/2.7/library/unittest.html#unittest.TextTestRunner).11861187Новое в версии 2.7: Ранее этот класс назывался `_TextTestResult`. Старое имя всё ещё существует как псевдоним, но является устаревшим.11881189#### `unittest.defaultTestLoader`11901191Экземпляр класса [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader), предназначенный для совместного использования. Если настройка [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader) не требуется, можно использовать этот экземпляр вместо повторного создания новых.11921193#### `class unittest.TextTestRunner(stream=sys.stderr, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None)`11941195Базовая реализация средства запуска тестов, которая выводит результаты в стандартный поток ошибок. У неё есть несколько настраиваемых параметров, но в целом она очень проста. Графические приложения, запускающие тестовые наборы, должны предоставлять альтернативные реализации.11961197#### `_makeResult()`11981199Этот метод возвращает экземпляр `TestResult`, используемый `run()`. Он не предназначен для прямого вызова, но может быть переопределён в подклассах для предоставления собственного `TestResult`.12001201`_makeResult()` создаёт экземпляр класса или вызываемого объекта, переданного в конструктор `TextTestRunner` как аргумент `resultclass`. По умолчанию используется [`TextTestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TextTestResult), если `resultclass` не предоставлен. Класс результата создаётся со следующими аргументами:12021203```python1204stream, descriptions, verbosity1205```12061207#### `unittest.main([module[, defaultTest[, argv[, testRunner[, testLoader[, exit[, verbosity[, failfast[, catchbreak[, buffer]]]]]]]]]])`12081209Программа командной строки, которая загружает набор тестов из *module* и запускает их; это в первую очередь для удобного выполнения тестовых модулей. Простейший способ использования этой функции – добавить следующую строку в конец тестового скрипта:12101211```python1212if __name__ == '__main__':1213    unittest.main()1214```12151216Можно запускать тесты с более подробной информацией, передав аргумент verbosity:12171218```python1219if __name__ == '__main__':1220    unittest.main(verbosity=2)1221```12221223Аргумент *defaultTest* – это имя теста, который будет запущен, если имена тестов не указаны через *argv*. Если он не указан или равен `None` и имена тестов не переданы через *argv*, то запускаются все тесты, найденные в *module*.12241225Аргумент *argv* может быть списком параметров, переданных программе, где первый элемент – имя программы. Если он не задан или равен `None`, используются значения [`sys.argv`](https://python-all.ru/2.7/library/sys.html#sys.argv).12261227Аргумент *testRunner* может быть либо классом исполнителя тестов, либо уже созданным экземпляром этого класса. По умолчанию `main` вызывает [`sys.exit()`](https://python-all.ru/2.7/library/sys.html#sys.exit) с кодом возврата, указывающим на успех или неудачу выполнения тестов.12281229Аргумент *testLoader* должен быть экземпляром [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader) и по умолчанию равен [`defaultTestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.defaultTestLoader).12301231`main` поддерживает использование из интерактивного интерпретатора при передаче аргумента `exit=False`. При этом результат выводится в стандартный вывод без вызова [`sys.exit()`](https://python-all.ru/2.7/library/sys.html#sys.exit):12321233```python1234>>> from unittest import main1235>>> main(module='test_module', exit=False)1236```12371238Параметры *failfast*, *catchbreak* и *buffer* имеют тот же эффект, что и одноимённые [параметры командной строки](https://python-all.ru/2.7/library/unittest.html#command-line-options).12391240Вызов `main` на самом деле возвращает экземпляр класса `TestProgram`. Этот экземпляр сохраняет результат выполнения тестов в атрибуте `result`.12411242Изменено в версии 2.7: Были добавлены параметры *exit*, *verbosity*, *failfast*, *catchbreak* и *buffer*.12431244#### 25.3.7.3.1. load\_tests Протокол12451246Новое в версии 2.7.12471248Модули или пакеты могут настраивать загрузку тестов из себя во время обычного запуска тестов или их обнаружения, реализуя функцию с именем `load_tests`.12491250Если тестовый модуль определяет `load_tests`, то он будет вызван функцией [`TestLoader.loadTestsFromModule()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader.loadTestsFromModule) со следующими аргументами:12511252```python1253load_tests(loader, standard_tests, None)1254```12551256Она должна возвращать объект [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite).12571258*loader* – это экземпляр [`TestLoader`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader), выполняющий загрузку. *standard\_tests* – это тесты, которые будут загружены по умолчанию из модуля. Часто тестовые модули хотят только добавить или удалить тесты из стандартного набора. Третий аргумент используется при загрузке пакетов в рамках обнаружения тестов.12591260Типичная функция `load_tests`, загружающая тесты из определённого набора классов [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase), может выглядеть так:12611262```python1263test_cases = (TestCase1, TestCase2, TestCase3)12641265def load_tests(loader, tests, pattern):1266    suite = TestSuite()1267    for test_class in test_cases:1268        tests = loader.loadTestsFromTestCase(test_class)1269        suite.addTests(tests)1270    return suite1271```12721273Если обнаружение запускается из командной строки или вызовом [`TestLoader.discover()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestLoader.discover) с шаблоном, соответствующим имени пакета, то пакет `__init__.py` проверяется на `load_tests`.12741275> **Примечание**1276>1277> Шаблон по умолчанию – `'test*.py'`. Он соответствует всем файлам Python, которые начинаются с `'test'`, но *не* соответствует тестовым каталогам.1278>1279> Шаблон вида `'test*'` будет соответствовать как тестовым пакетам, так и модулям.12801281Если пакет `__init__.py` определяет `load_tests`, то она будет вызвана, и обнаружение не продолжается внутрь пакета. `load_tests` вызывается со следующими аргументами:12821283```python1284load_tests(loader, standard_tests, pattern)1285```12861287Она должна возвращать объект [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite), представляющий все тесты из пакета. (`standard_tests` будет содержать только тесты, собранные из `__init__.py`.)12881289Поскольку шаблон передаётся в `load_tests`, пакет может продолжить (и, возможно, изменить) обнаружение тестов. Функция `load_tests`, которая ничего не делает, для тестового пакета может выглядеть так:12901291```python1292def load_tests(loader, standard_tests, pattern):1293    # корневой каталог, кэшированный на экземпляре загрузчика1294    this_dir = os.path.dirname(__file__)1295    package_tests = loader.discover(start_dir=this_dir, pattern=pattern)1296    standard_tests.addTests(package_tests)1297    return standard_tests1298```12991300## 25.3.8. Фикстуры классов и модулей13011302Фикстуры уровня класса и модуля реализуются в [`TestSuite`](https://python-all.ru/2.7/library/unittest.html#unittest.TestSuite). Когда набор тестов встречает тест из нового класса, вызывается `tearDownClass()` из предыдущего класса (если он есть), а затем `setUpClass()` из нового класса.13031304Аналогично, если тест из другого модуля, отличного от предыдущего, то запускается `tearDownModule` предыдущего модуля, а затем `setUpModule` нового модуля.13051306После выполнения всех тестов запускаются финальные `tearDownClass` и `tearDownModule`.13071308Обратите внимание, что общие фикстуры плохо совместимы с такими возможностями, как параллельное выполнение тестов, и нарушают изоляцию тестов. Их следует использовать с осторожностью.13091310Упорядочивание тестов по умолчанию, создаваемое загрузчиками тестов unittest, группирует все тесты из одних и тех же модулей и классов вместе. Это приводит к тому, что `setUpClass` / `setUpModule` (и т.д.) вызываются ровно один раз на класс и модуль. Если изменить порядок случайным образом, так что тесты из разных модулей и классов будут соседствовать друг с другом, то эти общие фикстуры могут вызываться несколько раз за один прогон тестов.13111312Общие фикстуры не предназначены для работы с наборами тестов, имеющими нестандартный порядок. `BaseTestSuite` всё ещё существует для фреймворков, которые не хотят поддерживать общие фикстуры.13131314Если во время выполнения одной из общих фикстур возникает исключение, тест помечается как ошибочный. Поскольку нет соответствующего экземпляра теста, создаётся объект `_ErrorHolder` (имеющий тот же интерфейс, что и [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase)) для представления ошибки. Если вы просто используете стандартный исполнитель тестов unittest, эта деталь не имеет значения, но если вы разработчик фреймворка, это может быть актуально.13151316### 25.3.8.1. setUpClass и tearDownClass13171318Они должны быть реализованы как методы класса:13191320```python1321import unittest13221323class Test(unittest.TestCase):1324    @classmethod1325    def setUpClass(cls):1326        cls._connection = createExpensiveConnectionObject()13271328    @classmethod1329    def tearDownClass(cls):1330        cls._connection.destroy()1331```13321333Если нужно, чтобы `setUpClass` и `tearDownClass` базовых классов вызывались, необходимо вызвать их самостоятельно. Реализации в [`TestCase`](https://python-all.ru/2.7/library/unittest.html#unittest.TestCase) пусты.13341335Если во время выполнения `setUpClass` возникает исключение, тесты в классе не запускаются, и `tearDownClass` не выполняется. Пропущенные классы не будут выполнять `setUpClass` или `tearDownClass`. Если исключением является [`SkipTest`](https://python-all.ru/2.7/library/unittest.html#unittest.SkipTest), то класс будет помечен как пропущенный, а не как ошибочный.13361337### 25.3.8.2. setUpModule и tearDownModule13381339Их следует реализовывать как функции:13401341```python1342def setUpModule():1343    createConnection()13441345def tearDownModule():1346    closeConnection()1347```13481349Если в `setUpModule` возникает исключение, то ни один тест в модуле не будет запущен, и `tearDownModule` не будет выполнен. Если исключением является [`SkipTest`](https://python-all.ru/2.7/library/unittest.html#unittest.SkipTest), то модуль будет помечен как пропущенный, а не как ошибочный.13501351## 25.3.9. Обработка сигналов13521353Параметр командной строки [`-c/--catch`](https://python-all.ru/2.7/library/unittest.html#cmdoption-unittest-c) для unittest вместе с параметром `catchbreak` для [`unittest.main()`](https://python-all.ru/2.7/library/unittest.html#unittest.main) обеспечивают более удобную обработку control-C во время выполнения тестов. Когда поведение catch-break включено, control-C позволяет завершить текущий тест, после чего выполнение тестов завершается и выводятся все результаты на данный момент. Повторное нажатие control-C вызовет исключение [`KeyboardInterrupt`](https://python-all.ru/2.7/library/exceptions.html#exceptions.KeyboardInterrupt) обычным образом.13541355Обработчик сигнала control-c старается оставаться совместимым с кодом или тестами, которые устанавливают собственный обработчик `signal.SIGINT`. Если обработчик `unittest` вызывается, но *не является* установленным обработчиком `signal.SIGINT`, то есть был заменён тестируемой системой и делегирован, то он вызывает стандартный обработчик. Обычно это ожидаемое поведение для кода, который заменяет установленный обработчик и делегирует ему. Для отдельных тестов, где требуется `unittest` отключить обработку control-c, можно использовать декоратор [`removeHandler()`](https://python-all.ru/2.7/library/unittest.html#unittest.removeHandler).13561357Существует несколько вспомогательных функций для разработчиков фреймворков, позволяющих включить обработку control-c в тестовых фреймворках.13581359#### `unittest.installHandler()`13601361Устанавливает обработчик control-c. Когда получен сигнал `signal.SIGINT` (обычно в ответ на нажатие пользователем control-c), у всех зарегистрированных результатов вызывается [`stop()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.stop).13621363Новое в версии 2.7.13641365#### `unittest.registerResult(result)`13661367Регистрирует объект [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult) для обработки control-c. При регистрации результата сохраняется слабая ссылка на него, поэтому это не препятствует сборке мусора объекта результата.13681369Регистрация объекта [`TestResult`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult) не имеет побочных эффектов, если обработка control-c не включена, поэтому тестовые фреймворки могут безусловно регистрировать все создаваемые ими результаты, независимо от того, включена обработка или нет.13701371Новое в версии 2.7.13721373#### `unittest.removeResult(result)`13741375Удаляет зарегистрированный результат. После удаления результата [`stop()`](https://python-all.ru/2.7/library/unittest.html#unittest.TestResult.stop) больше не будет вызываться для этого объекта результата в ответ на control-c.13761377Новое в версии 2.7.13781379#### `unittest.removeHandler(function=None)`13801381При вызове без аргументов эта функция удаляет обработчик control-c, если он был установлен. Эту функцию также можно использовать как тестовый декоратор для временного удаления обработчика на время выполнения теста:13821383```python1384@unittest.removeHandler1385def test_signal_handling(self):1386    ...1387```13881389Новое в версии 2.7.1390