Учебники

UnitTest Framework — Краткое руководство

UnitTest Framework — Обзор

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

Модульное тестирование может быть выполнено следующими двумя способами:

Ручное тестирование Автоматизированное тестирование

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

  • Поскольку тестовые случаи выполняются человеческими ресурсами, это очень трудоемко и утомительно .

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

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

  • Никакое программирование не может быть сделано, чтобы написать сложные тесты, которые выбирают скрытую информацию.

Получение поддержки инструмента и выполнение тестовых случаев с использованием инструмента автоматизации называется автоматизацией тестирования.

  • Fast Automation выполняет тесты значительно быстрее, чем человеческие ресурсы.

  • Инвестиции в человеческие ресурсы меньше, так как тестовые случаи выполняются с использованием инструмента автоматизации.

  • Автоматизированные тесты выполняют точно одну и ту же операцию при каждом запуске и являются более надежными .

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

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

Поскольку тестовые случаи выполняются человеческими ресурсами, это очень трудоемко и утомительно .

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

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

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

Получение поддержки инструмента и выполнение тестовых случаев с использованием инструмента автоматизации называется автоматизацией тестирования.

Fast Automation выполняет тесты значительно быстрее, чем человеческие ресурсы.

Инвестиции в человеческие ресурсы меньше, так как тестовые случаи выполняются с использованием инструмента автоматизации.

Автоматизированные тесты выполняют точно одну и ту же операцию при каждом запуске и являются более надежными .

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

JUnit является структурой модульного тестирования для языка программирования Java. JUnit сыграл важную роль в разработке управляемой тестами разработки и является одной из семейства платформ модульного тестирования, известных под общим названием xUnit, которые возникли в JUnit. Вы можете найти JUnit Tutorial здесь.

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

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

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

Вы должны иметь достаточный опыт в разработке программного обеспечения с использованием языка Python. Наш учебник по Python — хорошее место для начала изучения Python. Знание основ тестирования программного обеспечения также желательно.

Настройка среды

Классы, необходимые для написания тестов, находятся в модуле unittest. Если вы используете более старые версии Python (до Python 2.1), модуль можно загрузить с http://pyunit.sourceforge.net/ . Тем не менее, модуль unittest теперь является частью стандартного дистрибутива Python; следовательно, он не требует отдельной установки.

UnitTest Framework — Фреймворк

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

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

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

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

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

  • Набор тестов — это набор тестов, наборов тестов или обоих. Это используется для объединения тестов, которые должны выполняться вместе. Наборы тестов реализуются классом TestSuite.

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

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

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

Набор тестов — это набор тестов, наборов тестов или обоих. Это используется для объединения тестов, которые должны выполняться вместе. Наборы тестов реализуются классом TestSuite.

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

Создание модульного теста

В написании простого модульного теста участвуют следующие шаги:

Шаг 1 — Импортируйте модуль unittest в вашу программу.

Шаг 2 — Определите функцию для тестирования. В следующем примере функция add () должна быть проверена.

Шаг 3 — Создайте тестовый сценарий путем создания подкласса unittest.TestCase.

Шаг 4 — Определите тест как метод внутри класса. Название метода должно начинаться с «test».

Шаг 5 — Каждый тест вызывает функцию assert класса TestCase. Есть много типов утверждений. В следующем примере вызывается функция assertEquals ().

Шаг 6 — функция assertEquals () сравнивает результат функции add () с аргументом arg2 и выдает assertionError, если сравнение не удается.

Шаг 7 — Наконец, вызовите метод main () из модуля unittest.

import unittest
def add(x,y):
   return x + y
   
class SimpleTest(unittest.TestCase):
   def testadd1(self):
      self.assertEquals(add(4,5),9)
      
if __name__ == '__main__':
   unittest.main()

Шаг 8 — Запустите приведенный выше скрипт из командной строки.

C:\Python27>python SimpleTest.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

Шаг 9 — Следующие три могут быть возможными результатами теста —

Sr.No Сообщение и описание
1

Хорошо

Тест проходит. «A» отображается на консоли.

2

ПОТЕРПЕТЬ ПОРАЖЕНИЕ

Тест не проходит и вызывает исключение AssertionError. «F» отображается на консоли.

3

ОШИБКА

Тест вызывает исключение, отличное от AssertionError. «E» отображается на консоли.

Хорошо

Тест проходит. «A» отображается на консоли.

ПОТЕРПЕТЬ ПОРАЖЕНИЕ

Тест не проходит и вызывает исключение AssertionError. «F» отображается на консоли.

ОШИБКА

Тест вызывает исключение, отличное от AssertionError. «E» отображается на консоли.

Эти результаты отображаются на консоли как ‘.’, ‘F’ и ‘E’ соответственно.

Интерфейс командной строки

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

python -m unittest test1
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

unittest поддерживает следующие параметры командной строки. Чтобы получить список всех параметров командной строки, используйте следующую команду —

Python –m unittest -h

Sr.No Вариант и описание
1

-h, —help

Показать это сообщение

2

v, —verbose

Подробный вывод

3

-q, —quiet

Минимальный выход

4

-f, —failfast

Остановка при первом сбое

5

-c, —catch

Catch control-C и отображать результаты

6

-b, —buffer

Буфер stdout и stderr во время тестовых прогонов

-h, —help

Показать это сообщение

v, —verbose

Подробный вывод

-q, —quiet

Минимальный выход

-f, —failfast

Остановка при первом сбое

-c, —catch

Catch control-C и отображать результаты

-b, —buffer

Буфер stdout и stderr во время тестовых прогонов

UnitTest Framework — API

В этой главе рассматриваются классы и методы, определенные в модуле unittest. В этом модуле пять основных классов.

TestCase Class

Объект этого класса представляет собой наименьшую тестируемую единицу. Он содержит тестовые процедуры и предоставляет крючки для подготовки каждой процедуры и последующей очистки.

Следующие методы определены в классе TestCase —

Sr.No Метод и описание
1

настроить()

Метод вызывается для подготовки тестового прибора. Это вызывается непосредственно перед вызовом тестового метода

2

срывать()

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

3

setUpClass ()

Метод класса, вызываемый перед тестами в отдельном запуске класса.

4

tearDownClass ()

Метод класса, вызываемый после выполнения тестов в отдельном классе.

5

запустить (результат = нет)

Запустите тест, собирая результат в объект результата теста, переданный как результат .

6

skipTest (причина)

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

7

отладки ()

Запустите тест, не собирая результат.

8

Краткое описание()

Возвращает однострочное описание теста.

настроить()

Метод вызывается для подготовки тестового прибора. Это вызывается непосредственно перед вызовом тестового метода

срывать()

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

setUpClass ()

Метод класса, вызываемый перед тестами в отдельном запуске класса.

tearDownClass ()

Метод класса, вызываемый после выполнения тестов в отдельном классе.

запустить (результат = нет)

Запустите тест, собирая результат в объект результата теста, переданный как результат .

skipTest (причина)

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

отладки ()

Запустите тест, не собирая результат.

Краткое описание()

Возвращает однострочное описание теста.

арматура

В классе TestCase могут быть написаны многочисленные тесты. Эти методы тестирования могут потребовать подключения к базе данных, временных файлов или других ресурсов для инициализации. Это так называемые светильники. TestCase включает специальный хук для настройки и очистки любых приборов, необходимых для ваших тестов. Чтобы настроить приборы, переопределите setUp (). Чтобы очистить, переопределите tearDown ().

В следующем примере два теста написаны внутри класса TestCase. Они проверяют результат сложения и вычитания двух значений. Метод setup () инициализирует аргументы на основе shortDescription () каждого теста. Метод teardown () будет выполняться в конце каждого теста.

import unittest

class simpleTest2(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      if name == "Add":
         self.a = 10
         self.b = 20
         print name, self.a, self.b
      if name == "sub":
         self.a = 50
         self.b = 60
         print name, self.a, self.b
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertTrue(result == 100)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
      
if __name__ == '__main__':
   unittest.main()

Запустите приведенный выше код из командной строки. Это дает следующий вывод —

C:\Python27>python test2.py
Add 10 20
F
end of test Add
sub 50 60
end of test sub
.
================================================================
FAIL: testadd (__main__.simpleTest2)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
   File "test2.py", line 21, in testadd
      self.assertTrue(result == 100)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.015s

FAILED (failures = 1)

Класс Крепеж

Класс TestCase имеет метод setUpClass (), который можно переопределить для выполнения перед выполнением отдельных тестов внутри класса TestCase. Аналогично, метод tearDownClass () будет выполнен после всех тестов в классе. Оба метода являются методами класса. Следовательно, они должны быть украшены директивой @classmethod.

В следующем примере демонстрируется использование этих методов класса —

import unittest

class TestFixtures(unittest.TestCase):

   @classmethod
   def setUpClass(cls):
      print 'called once before any tests in class'

   @classmethod
   def tearDownClass(cls):
      print '\ncalled once after all tests in class'

   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      print '\n',name
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def test1(self):
      """One"""
      result = self.a+self.b
      self.assertTrue(True)
   def test2(self):
      """Two"""
      result = self.a-self.b
      self.assertTrue(False)
      
if __name__ == '__main__':
unittest.main()

TestSuite Class

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

Следующие шаги участвуют в создании и запуске набора тестов.

Шаг 1 — Создайте экземпляр класса TestSuite.

suite = unittest.TestSuite()

Шаг 2 — Добавьте тесты внутри класса TestCase в комплекте.

suite.addTest(testcase class)

Шаг 3 — Вы также можете использовать метод makeSuite () для добавления тестов из класса

suite = unittest.makeSuite(test case class)

Шаг 4 — Индивидуальные тесты также могут быть добавлены в комплект.

suite.addTest(testcaseclass(""testmethod")

Шаг 5 — Создайте объект класса TestTestRunner.

runner = unittest.TextTestRunner()

Шаг 6 — Вызовите метод run (), чтобы запустить все тесты в комплекте

runner.run (suite)

Следующие методы определены в классе TestSuite —

Sr.No Метод и описание
1

addTest ()

Добавляет метод теста в набор тестов.

2

addTests ()

Добавляет тесты из нескольких классов TestCase.

3

бежать()

Запускает тесты, связанные с этим пакетом, собирая результат в объект результата теста

4

отладки ()

Запускает тесты, связанные с этим набором, без сбора результатов.

5

countTestCases ()

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

addTest ()

Добавляет метод теста в набор тестов.

addTests ()

Добавляет тесты из нескольких классов TestCase.

бежать()

Запускает тесты, связанные с этим пакетом, собирая результат в объект результата теста

отладки ()

Запускает тесты, связанные с этим набором, без сбора результатов.

countTestCases ()

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

В следующем примере показано, как использовать класс TestSuite —

import unittest
class suiteTest(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      
   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertTrue(result == 100)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
      
def suite():
   suite = unittest.TestSuite()
##   suite.addTest (simpleTest3("testadd"))
##   suite.addTest (simpleTest3("testsub"))
   suite.addTest(unittest.makeSuite(simpleTest3))
   return suite
   
if __name__ == '__main__':
   runner = unittest.TextTestRunner()
   test_suite = suite()
   runner.run (test_suite)

Вы можете поэкспериментировать с методом addTest (), раскомментировав строки и комментарий, используя метод makeSuite ().

TestLoader Class

Пакет unittest имеет класс TestLoader, который используется для создания наборов тестов из классов и модулей. По умолчанию экземпляр unittest.defaultTestLoader создается автоматически при вызове метода unittest.main (0. Явный экземпляр, однако, позволяет настраивать определенные свойства.

В следующем коде тесты из двух классов собираются в список с помощью объекта TestLoader.

import unittest
testList = [Test1, Test2]
testLoad = unittest.TestLoader()

TestList = []
for testCase in testList:
   testSuite = testLoad.loadTestsFromTestCase(testCase)
   TestList.append(testSuite)
   
newSuite = unittest.TestSuite(TestList)
runner = unittest.TextTestRunner()
runner.run(newSuite)

В следующей таблице приведен список методов в классе TestLoader —

S.No Метод и описание
1

loadTestsFromTestCase ()

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

2

loadTestsFromModule ()

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

3

loadTestsFromName ()

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

4

обнаружить()

Найдите все тестовые модули, вернувшись в подкаталоги из указанного начального каталога, и верните объект TestSuite.

loadTestsFromTestCase ()

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

loadTestsFromModule ()

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

loadTestsFromName ()

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

обнаружить()

Найдите все тестовые модули, вернувшись в подкаталоги из указанного начального каталога, и верните объект TestSuite.

TestResult Class

Этот класс используется для компиляции информации о тестах, которые были успешными, и тестах, которые потерпели неудачу. Объект TestResult хранит результаты набора тестов. Экземпляр TestResult возвращается методом TestRunner.run ().

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

Sr.No Атрибут и описание
1

ошибки

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

2

Отказы

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

3

Пропущенные

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

4

Был успешен()

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

5

стоп()

Этот метод может быть вызван, чтобы сигнализировать, что набор тестов должен быть прерван.

6

startTestRun ()

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

7

stopTestRun ()

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

8

testsRun

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

9

буфер

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

ошибки

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

Отказы

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

Пропущенные

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

Был успешен()

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

стоп()

Этот метод может быть вызван, чтобы сигнализировать, что набор тестов должен быть прерван.

startTestRun ()

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

stopTestRun ()

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

testsRun

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

буфер

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

Следующий код выполняет набор тестов —

if __name__ == '__main__':
   runner = unittest.TextTestRunner()
   test_suite = suite()
   result = runner.run (test_suite)
   
   print "---- START OF TEST RESULTS"
   print result

   print "result::errors"
   print result.errors

   print "result::failures"
   print result.failures

   print "result::skipped"
   print result.skipped

   print "result::successful"
   print result.wasSuccessful()
   
   print "result::test-run"
   print result.testsRun
   print "---- END OF TEST RESULTS"

Код при выполнении отображает следующий вывод —

---- START OF TEST RESULTS
<unittest.runner.TextTestResult run = 2 errors = 0 failures = 1>
result::errors
[]
result::failures
[(<__main__.suiteTest testMethod = testadd>, 'Traceback (most recent call last):\n
   File "test3.py", line 10, in testadd\n 
   self.assertTrue(result == 100)\nAssert
   ionError: False is not true\n')]
result::skipped
[]
result::successful
False
result::test-run
2
---- END OF TEST RESULTS

UnitTest Framework — Утверждение

Среда тестирования Python использует встроенную в Python функцию assert (), которая проверяет определенное условие. Если утверждение не выполнено, возникает ошибка AssertionError. Затем структура тестирования идентифицирует тест как «Отказ». Другие исключения рассматриваются как ошибки.

Следующие три набора функций утверждения определены в модуле unittest —

  • Основные булевы утверждения
  • Сравнительные утверждения
  • Активы для коллекций

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

Sr.No Метод и описание
1

assertEqual (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 равны. Если значения не совпадают, тест не пройден.

2

assertNotEqual (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 не равны. Если значения сравниваются равными, тест не пройден.

3

assertTrue (expr, msg = None)

Проверьте, что expr верно. Если false, тест не пройден

4

assertFalse (expr, msg = None)

Проверьте, что expr ложно. Если это правда, тест не пройден

5

assertIs (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 оценивают один и тот же объект.

6

assertIsNot (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 не оценивают один и тот же объект.

7

assertIsNone (expr, msg = None)

Проверьте, что expr — None. Если нет, тест не пройден

8

assertIsNotNone (expr, msg = None)

Проверьте, что expr не None. Если нет, тест не пройден

9

assertIn (arg1, arg2, msg = нет)

Проверьте, что arg1 находится в arg2 .

10

assertNotIn (arg1, arg2, msg = None)

Проверьте, что arg1 отсутствует в arg2 .

11

assertIsInstance (obj, cls, msg = None)

Проверьте, что obj является экземпляром cls

12

assertNotIsInstance (obj, cls, msg = None)

Проверьте, что obj не является экземпляром cls

assertEqual (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 равны. Если значения не совпадают, тест не пройден.

assertNotEqual (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 не равны. Если значения сравниваются равными, тест не пройден.

assertTrue (expr, msg = None)

Проверьте, что expr верно. Если false, тест не пройден

assertFalse (expr, msg = None)

Проверьте, что expr ложно. Если это правда, тест не пройден

assertIs (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 оценивают один и тот же объект.

assertIsNot (arg1, arg2, msg = None)

Проверьте, что arg1 и arg2 не оценивают один и тот же объект.

assertIsNone (expr, msg = None)

Проверьте, что expr — None. Если нет, тест не пройден

assertIsNotNone (expr, msg = None)

Проверьте, что expr не None. Если нет, тест не пройден

assertIn (arg1, arg2, msg = нет)

Проверьте, что arg1 находится в arg2 .

assertNotIn (arg1, arg2, msg = None)

Проверьте, что arg1 отсутствует в arg2 .

assertIsInstance (obj, cls, msg = None)

Проверьте, что obj является экземпляром cls

assertNotIsInstance (obj, cls, msg = None)

Проверьте, что obj не является экземпляром cls

Некоторые из приведенных выше функций утверждения реализованы в следующем коде:

import unittest

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertEqual(4 + 5,9)
   def test2(self):
      self.assertNotEqual(5 * 2,10)
   def test3(self):
      self.assertTrue(4 + 5 == 9,"The result is False")
   def test4(self):
      self.assertTrue(4 + 5 == 10,"assertion fails")
   def test5(self):
      self.assertIn(3,[1,2,3])
   def test6(self):
      self.assertNotIn(3, range(5))

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

Когда приведенный выше сценарий запущен, test2, test4 и test6 покажут сбой, а другие запустятся успешно.

FAIL: test2 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 9, in test2
      self.assertNotEqual(5*2,10)
AssertionError: 10 == 10

FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 13, in test4
      self.assertTrue(4+5==10,"assertion fails")
AssertionError: assertion fails

FAIL: test6 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python27\SimpleTest.py", line 17, in test6
      self.assertNotIn(3, range(5))
AssertionError: 3 unexpectedly found in [0, 1, 2, 3, 4]

----------------------------------------------------------------------            
Ran 6 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 3)

Вторым набором функций утверждения являются сравнительные утверждения

  • assertAlmostEqual (первый, второй, мест = 7, сообщения = нет, дельта = нет)

    Проверьте, что первое и второе приблизительно (или не приблизительно) равны, вычисляя разницу, округляя до заданного числа десятичных знаков (по умолчанию 7),

  • assertNotAlmostEqual (первое, второе, места, сообщения, дельта)

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

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

    Предоставление и дельты, и мест вызывает ошибку TypeError.

  • assertGreater (первый, второй, сообщения = нет)

    Проверьте, что first больше второго, в зависимости от имени метода. Если нет, тест не пройден.

  • assertGreaterEqual (первый, второй, сообщение = нет)

    Проверьте, что first больше или равно second, в зависимости от имени метода. Если нет, тест не пройден

  • assertLess (первое, второе, сообщение = нет)

    Проверьте, что первое меньше второго, в зависимости от имени метода. Если нет, тест не пройден

  • assertLessEqual (first, second, msg = None)

    Проверьте, что first меньше или равно second в зависимости от имени метода. Если нет, тест не пройден.

  • assertRegexpMatches (text, regexp, msg = None)

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

  • assertNotRegexpMatches (текст, регулярное выражение, сообщение = нет)

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

assertAlmostEqual (первый, второй, мест = 7, сообщения = нет, дельта = нет)

Проверьте, что первое и второе приблизительно (или не приблизительно) равны, вычисляя разницу, округляя до заданного числа десятичных знаков (по умолчанию 7),

assertNotAlmostEqual (первое, второе, места, сообщения, дельта)

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

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

Предоставление и дельты, и мест вызывает ошибку TypeError.

assertGreater (первый, второй, сообщения = нет)

Проверьте, что first больше второго, в зависимости от имени метода. Если нет, тест не пройден.

assertGreaterEqual (первый, второй, сообщение = нет)

Проверьте, что first больше или равно second, в зависимости от имени метода. Если нет, тест не пройден

assertLess (первое, второе, сообщение = нет)

Проверьте, что первое меньше второго, в зависимости от имени метода. Если нет, тест не пройден

assertLessEqual (first, second, msg = None)

Проверьте, что first меньше или равно second в зависимости от имени метода. Если нет, тест не пройден.

assertRegexpMatches (text, regexp, msg = None)

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

assertNotRegexpMatches (текст, регулярное выражение, сообщение = нет)

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

Функции утверждения реализованы в следующем примере:

import unittest
import math
import re

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertAlmostEqual(22.0/7,3.14)
   def test2(self):
      self.assertNotAlmostEqual(10.0/3,3)
   def test3(self):
      self.assertGreater(math.pi,3)
   def test4(self):
      self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")

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

Приведенный выше скрипт сообщает о test1 и test4 как о сбое. В тесте 1 деление 22/7 находится не в 7 десятичных разрядах от 3,14. Точно так же, поскольку второй аргумент совпадает с текстом в первом аргументе, test4 приводит к AssertionError.

=====================================================FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 7, in test1
      self.assertAlmostEqual(22.0/7,3.14)
AssertionError: 3.142857142857143 != 3.14 within 7 places
================================================================
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 13, in test4
      self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
AssertionError: Regexp matched: 'Point' matches 'Point' in 'Tutorials Point (I)
Private Limited'
----------------------------------------------------------------------

Ran 4 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 2)

Отстаивать для коллекций

Этот набор функций assert предназначен для использования с типами данных коллекции в Python, такими как List, Tuple, Dictionary и Set.

Sr.No Метод и описание
1

assertListEqual (list1, list2, msg = None)

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

2

assertTupleEqual (tuple1, tuple2, msg = None)

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

3

assertSetEqual (set1, set2, msg = None)

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

4

assertDictEqual (ожидаемый, фактический, msg = Нет)

Проверьте, что два словаря равны. Если нет, то создается сообщение об ошибке, которое показывает различия в словарях.

assertListEqual (list1, list2, msg = None)

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

assertTupleEqual (tuple1, tuple2, msg = None)

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

assertSetEqual (set1, set2, msg = None)

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

assertDictEqual (ожидаемый, фактический, msg = Нет)

Проверьте, что два словаря равны. Если нет, то создается сообщение об ошибке, которое показывает различия в словарях.

Следующий пример реализует вышеуказанные методы —

import unittest

class SimpleTest(unittest.TestCase):
   def test1(self):
      self.assertListEqual([2,3,4], [1,2,3,4,5])
   def test2(self):
      self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
   def test3(self):
      self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})

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

В приведенном выше примере test1 и test3 показывают AssertionError. Сообщение об ошибке отображает различия в объектах List и Dictionary.

FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 5, in test1
      self.assertListEqual([2,3,4], [1,2,3,4,5])
AssertionError: Lists differ: [2, 3, 4] != [1, 2, 3, 4, 5]

First differing element 0:
2
1

Second list contains 2 additional elements.
First extra element 3:
4

- [2, 3, 4]
+ [1, 2, 3, 4, 5]
? +++       +++

FAIL: test3 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "asserttest.py", line 9, in test3
      self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
AssertionError: {1: 11, 2: 22} != {1: 11, 2: 22, 3: 33}
- {1: 11, 2: 22}
+ {1: 11, 2: 22, 3: 33}
?              +++++++
                                                                                  
----------------------------------------------------------------------            
Ran 3 tests in 0.001s                                                             
                                                                                  
FAILED (failures = 2)

UnitTest Framework — тестовое обнаружение

Класс TestLoader имеет функцию Discover (). Среда тестирования Python использует это для простого обнаружения тестов. Чтобы быть совместимыми, модули и пакеты, содержащие тесты, должны импортироваться из каталога верхнего уровня.

Ниже приведено основное использование командной строки для обнаружения тестов:

Python –m unittest discover

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

Sr.No Варианты и описание
1

-v, —verbose

Подробный вывод

2

-s, —start-каталог

каталог Каталог для запуска обнаружения (. по умолчанию)

3

-p, —pattern

pattern Шаблон для соответствия тестовым файлам (test * .py по умолчанию)

4

-t, —top-level-directory

каталог Каталог верхнего уровня проекта (по умолчанию — начальный каталог)

-v, —verbose

Подробный вывод

-s, —start-каталог

каталог Каталог для запуска обнаружения (. по умолчанию)

-p, —pattern

pattern Шаблон для соответствия тестовым файлам (test * .py по умолчанию)

-t, —top-level-directory

каталог Каталог верхнего уровня проекта (по умолчанию — начальный каталог)

Например, чтобы обнаружить тесты в модулях, имена которых начинаются с «assert» в каталоге «tests», используется следующая командная строка:

C:\python27>python –m unittest –v –s "c:\test" –p "assert*.py"

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

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

UnitTest Framework — пропустить тест

Поддержка пропуска тестов была добавлена ​​начиная с Python 2.7. Можно пропустить отдельный метод тестирования или класс TestCase, как условно, так и безоговорочно. Эта структура позволяет пометить определенный тест как «ожидаемый сбой». Этот тест «провалится», но не будет засчитан как провальный в TestResult.

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

import unittest

   def add(x,y):
      return x+y

class SimpleTest(unittest.TestCase):
   @unittest.skip("demonstrating skipping")
   def testadd1(self):
      self.assertEquals(add(4,5),9)

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

Поскольку skip () является методом класса, к нему добавляется префикс @ token. Метод принимает один аргумент: сообщение журнала, описывающее причину пропуска.

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

C:\Python27>python skiptest.py
s
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK (skipped = 1)

Символ ‘s’ указывает, что тест был пропущен.

Альтернативный синтаксис для пропуска теста использует метод экземпляра skipTest () внутри функции теста.

def testadd2(self):
   self.skipTest("another method for skipping")
   self.assertTrue(add(4 + 5) == 10)

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

Sr.No Метод и описание
1

unittest.skip (причина)

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

2

unittest.skipIf (условие, причина)

Пропустите оформленный тест, если условие выполняется.

3

unittest.skipUnless (условие, причина)

Пропустите оформленный тест, если условие не выполняется.

4

unittest.expectedFailure ()

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

unittest.skip (причина)

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

unittest.skipIf (условие, причина)

Пропустите оформленный тест, если условие выполняется.

unittest.skipUnless (условие, причина)

Пропустите оформленный тест, если условие не выполняется.

unittest.expectedFailure ()

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

В следующем примере демонстрируется использование условного пропуска и ожидаемого сбоя.

import unittest

class suiteTest(unittest.TestCase):
   a = 50
   b = 40
   
   def testadd(self):
      """Add"""
      result = self.a+self.b
      self.assertEqual(result,100)

   @unittest.skipIf(a>b, "Skip over this routine")
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)
   
   @unittest.skipUnless(b == 0, "Skip over this routine")
   def testdiv(self):
      """div"""
      result = self.a/self.b
      self.assertTrue(result == 1)

   @unittest.expectedFailure
   def testmul(self):
      """mul"""
      result = self.a*self.b
      self.assertEqual(result == 0)

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

В приведенном выше примере testsub () и testdiv () будут пропущены. В первом случае a> b истинно, а во втором случае b == 0 не верно. С другой стороны, testmul () был отмечен как ожидаемый сбой.

При запуске вышеуказанного сценария два пропущенных теста показывают «s», а ожидаемый сбой — «x».

C:\Python27>python skiptest.py
Fsxs
================================================================
FAIL: testadd (__main__.suiteTest)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
   File "skiptest.py", line 9, in testadd
      self.assertEqual(result,100)
AssertionError: 90 != 100

----------------------------------------------------------------------
Ran 4 tests in 0.000s

FAILED (failures = 1, skipped = 2, expected failures = 1)

UnitTest Framework — тест исключений

Платформа тестирования Python предоставляет следующие методы утверждения для проверки возникновения исключений.

assertRaises (исключение, вызываемый, * args, ** kwds)

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

В приведенном ниже примере определена тестовая функция для проверки, вызвано ли ZeroDivisionError.

import unittest

def div(a,b):
   return a/b
class raiseTest(unittest.TestCase):
   def testraise(self):
      self.assertRaises(ZeroDivisionError, div, 1,0)

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

Функция testraise () использует функцию assertRaises (), чтобы увидеть, происходит ли деление на ноль при вызове функции div (). Приведенный выше код вызовет исключение. Но изменяет аргументы функции div () следующим образом:

self.assertRaises(ZeroDivisionError, div, 1,1)

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

F
================================================================
FAIL: testraise (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 7, in testraise
      self.assertRaises(ZeroDivisionError, div, 1,1)
AssertionError: ZeroDivisionError not raised

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures = 1)

assertRaisesRegexp (исключение, регулярное выражение, вызываемое, * args, ** kwds)

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

В следующем примере показано, как используется assertRaisesRegexp () —

import unittest
import re

class raiseTest(unittest.TestCase):
   def testraiseRegex(self):
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
      
if __name__ == '__main__':
   unittest.main()

Здесь testraseRegex () test не является первым аргументом. «Точка» находится во второй строке аргумента.

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:/Python27/raiseTest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
AssertionError: TypeError not raised
----------------------------------------------------------------------

Тем не менее, изменение, как показано ниже —

self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")

Исключение TypeError будет выдано. Следовательно, будет показан следующий результат —

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
AssertionError: "invalid" does not match 
   "first argument must be string or compiled pattern"
----------------------------------------------------------------------

UnitTest Framework — Тест времени

Junit, инфраструктура модульного тестирования Java (Pyunit — это реализация JUnit), имеет удобную опцию тайм-аута. Если тест занимает больше указанного времени, он будет помечен как неудачный.

Среда тестирования Python не содержит поддержки времени ожидания. Тем не менее, модуль третьей части под названием timeout-decorator может сделать эту работу.

Загрузите и установите модуль с —

https://pypi.python.org/packages/source/t/timeout-decorator/timeout-decorator-0.3.2.tar.gz

  • Импортировать timeout_decorator в код
  • Поставьте таймаут декоратор перед тестом
  • @ Timeout_decorator.timeout (10)

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

import time
import timeout_decorator

class timeoutTest(unittest.TestCase):

   @timeout_decorator.timeout(5)
   def testtimeout(self):
      print "Start"
   for i in range(1,10):
      time.sleep(1)
      print "%d seconds have passed" % i
      
if __name__ == '__main__':
   unittest.main()

UnitTest Framework — Unittest2

unittest2 — это бэкпорт дополнительных функций, добавленных в среду тестирования Python в Python 2.7 и более поздних версиях. Он протестирован для работы на Python 2.6, 2.7 и 3. *. Последняя версия может быть загружена с https://pypi.python.org/pypi/unittest2

Чтобы использовать unittest2 вместо unittest, просто замените импорт unittest на импорт unittest2.

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

Ниже приведены новые функции unittest2 —

  • addCleanups для лучшего управления ресурсами

  • Содержит много новых методов assert

  • assertRaises как менеджер контекста, с доступом к исключению впоследствии

  • Имеет приборы уровня модуля, такие как setUpModule и tearDownModule

  • Включает протокол load_tests для загрузки тестов из модулей или пакетов

  • Методы startTestRun и stopTestRun для TestResult

addCleanups для лучшего управления ресурсами

Содержит много новых методов assert

assertRaises как менеджер контекста, с доступом к исключению впоследствии

Имеет приборы уровня модуля, такие как setUpModule и tearDownModule

Включает протокол load_tests для загрузки тестов из модулей или пакетов

Методы startTestRun и stopTestRun для TestResult

В Python 2.7 вы вызываете функции командной строки unittest (включая тестовое обнаружение) с помощью python -m unittest <args> .

Вместо этого unittest2 поставляется со скриптом unit2.

unit2 discover
unit2 -v test_module

UnitTest Framework — Обработка сигналов

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

Если вызывается обработчик unittest, но обработчик signal.SIGINT не установлен, он вызывает обработчик по умолчанию. Обычно это будет ожидаемое поведение кода, который заменяет установленный обработчик и делегирует его. Для отдельных тестов, которым требуется отключенная обработка controltest c-unit, можно использовать декоратор removeHandler ().

Следующие служебные функции включают функцию обработки control-c в рамках тестирования —

unittest.installHandler ()

Установите обработчик control-c. Когда получен сигнал .SIGINT, для всех зарегистрированных результатов вызывается TestResult.stop ().

unittest.registerResult (результат)

Зарегистрируйте объект TestResult для обработки control-c. При регистрации результата сохраняется слабая ссылка на него, поэтому он не предотвращает сбор мусора.

unittest.removeResult (результат)

Удалить зарегистрированный результат. После удаления результата TestResult.stop () больше не будет вызываться для этого объекта результата в ответ на control-c.

unittest.removeHandler (function = None)

При вызове без аргументов эта функция удаляет обработчик control-c, если он был установлен. Эта функция также может использоваться в качестве декоратора теста для временного удаления обработчика во время выполнения теста.

GUI Test Runner

Модуль unittest устанавливается для интерактивного обнаружения и запуска тестов. Эта утилита, скрипт Python inittestgui.py, использует модуль Tkinter, который является портом Python для набора графических инструментов TK. Это дает простой в использовании графический интерфейс для обнаружения и запуска тестов.

Python unittestgui.py

Бегущий тест

Нажмите кнопку «Обнаружить тесты». Появится небольшое диалоговое окно, в котором вы можете выбрать каталог и модули, из которых будет выполняться тест.

Откройте тест

Наконец, нажмите кнопку запуска. Тесты будут обнаружены по выбранному пути и именам модулей, а на панели результатов отобразятся результаты.

Панель результатов

Чтобы увидеть подробности отдельного теста, выберите и нажмите на тест в окне результатов —

Индивидуальные тестовые данные

Если вы не нашли эту утилиту в установке Python, вы можете получить ее на странице проекта http://pyunit.sourceforge.net/ .

Похоже, что утилита на основе wxpython toolkit также доступна там.

UnitTest Framework — Doctest

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

Doctest может быть очень полезен в следующих сценариях —

  • Чтобы проверить актуальность строк документации модуля, убедитесь, что все интерактивные примеры по-прежнему работают так, как описано в документации.

  • Выполнить регрессионное тестирование, проверив, что интерактивные примеры из тестового файла или тестового объекта работают должным образом.

  • Чтобы написать учебную документацию для пакета, подробно иллюстрированного примерами ввода-вывода

Чтобы проверить актуальность строк документации модуля, убедитесь, что все интерактивные примеры по-прежнему работают так, как описано в документации.

Выполнить регрессионное тестирование, проверив, что интерактивные примеры из тестового файла или тестового объекта работают должным образом.

Чтобы написать учебную документацию для пакета, подробно иллюстрированного примерами ввода-вывода

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

Обычная практика — помещать пример использования различных частей кода Python в строку документации. Модуль doctest позволяет проверить, соответствуют ли эти строки документации прерывистым изменениям в коде.

В следующем коде факториальная функция определяется с использованием примера использования. Чтобы проверить правильность использования примера, вызовите функцию testmod () в модуле doctest.

"""
This is the "example" module.

The example module supplies one function, factorial(). For example,

>>> factorial(5)
120
"""

def factorial(x):
   """Return the factorial of n, an exact integer >= 0.
   >>> factorial(-1)
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
   """
   
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testmod()

Введите и сохраните приведенный выше скрипт как FactDocTest.py и попробуйте выполнить этот скрипт из командной строки.

Python FactDocTest.py

Выходные данные не будут показаны, если пример не удался. Теперь измените командную строку на следующее —

Python FactDocTest.py –v

Консоль теперь покажет следующий вывод —

C:\Python27>python FactDocTest.py -v
Trying:
   factorial(5)
Expecting:
   120
ok
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
2 items passed all tests:
   1 tests in __main__
   1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.

Если, с другой стороны, код функции factorial () не дает ожидаемого результата в строке документации, будет отображаться результат ошибки. Например, измените f = 2 вместо f = 1 в приведенном выше сценарии и снова запустите doctest. Результат будет следующим:

Trying:
   factorial(5)
Expecting:
   120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
   120
Got:
   240
Trying:
   factorial(-1)
Expecting:
   Traceback (most recent call last):
      ...
   ValueError: x must be >= 0
ok
1 items passed all tests:
   1 tests in __main__.factorial
**********************************************************************
1 items had failures:
   1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.

Doctest: проверка примеров в текстовом файле

Еще одно простое приложение doctest — тестирование интерактивных примеров в текстовом файле. Это можно сделать с помощью функции testfile ().

Следующий текст хранится в текстовом файле с именем «example.txt».

Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
   >>> from example import factorial
Now use it:
   >>> factorial(5)
   120

Содержимое файла обрабатывается как строка документации. Чтобы проверить примеры в текстовом файле, используйте функцию testfile () модуля doctest.

def factorial(x):
   if not x >= 0:
      raise ValueError("x must be >= 0")
   f = 1
   for i in range(1,x+1):
      f = f*i
   return f
   
if __name__ == "__main__":
   import doctest
   doctest.testfile("example.txt")
  • Как и в случае с testmod (), testfile () ничего не отобразит, если не удастся выполнить пример. Если пример терпит неудачу, то неудачный пример (ы) и причина (и) сбоя (ей) выводятся на консоль, используя тот же формат, что и testmod ().

  • В большинстве случаев копирование и вставка сеанса интерактивной консоли работает нормально, но doctest не пытается выполнить точную эмуляцию какой-либо конкретной оболочки Python.

  • Любой ожидаемый вывод должен следовать сразу за последней строкой «>>>» или «…», содержащей код, а ожидаемый вывод (если таковой имеется) продолжается до следующей строки «>>>» или пробела.

  • Ожидаемый вывод не может содержать строку, в которой есть все пробелы, поскольку такая строка используется для обозначения конца ожидаемого вывода. Если ожидаемый результат содержит пустую строку, поместите <BLANKLINE> в ваш пример документа каждый раз, когда ожидается пустая строка.

Как и в случае с testmod (), testfile () ничего не отобразит, если не удастся выполнить пример. Если пример терпит неудачу, то неудачный пример (ы) и причина (и) сбоя (ей) выводятся на консоль, используя тот же формат, что и testmod ().

В большинстве случаев копирование и вставка сеанса интерактивной консоли работает нормально, но doctest не пытается выполнить точную эмуляцию какой-либо конкретной оболочки Python.

Любой ожидаемый вывод должен следовать сразу за последней строкой «>>>» или «…», содержащей код, а ожидаемый вывод (если таковой имеется) продолжается до следующей строки «>>>» или пробела.

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

UnitTest Framework — API Doctest

API doctest вращается вокруг следующих двух контейнерных классов, используемых для хранения интерактивных примеров из строк документации:

  • Пример — один оператор Python в сочетании с ожидаемым результатом.

  • DocTest — коллекция примеров, обычно извлекаемая из одной строки документации или текстового файла.

Пример — один оператор Python в сочетании с ожидаемым результатом.

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

Следующие дополнительные классы обработки определены для поиска, анализа, запуска и проверки примеров doctest —

  • DocTestFinder — Находит все строки документации в данном модуле и использует DocTestParser для создания DocTest из каждой строки документации, содержащей интерактивные примеры.

  • DocTestParser — Создает объект doctest из строки (такой как строка документа объекта).

  • DocTestRunner — выполняет примеры в тестовом документе и использует OutputChecker для проверки их вывода.

  • OutputChecker — сравнивает фактический вывод из примера doctest с ожидаемым выводом и решает, соответствуют ли они.

DocTestFinder — Находит все строки документации в данном модуле и использует DocTestParser для создания DocTest из каждой строки документации, содержащей интерактивные примеры.

DocTestParser — Создает объект doctest из строки (такой как строка документа объекта).

DocTestRunner — выполняет примеры в тестовом документе и использует OutputChecker для проверки их вывода.

OutputChecker — сравнивает фактический вывод из примера doctest с ожидаемым выводом и решает, соответствуют ли они.

Класс DocTestFinder

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

Этот класс определяет метод find (). Он возвращает список DocTests, которые определены строкой документации объекта или любой из строк документации содержащихся в нем объектов.

Класс DocTestParser

Это класс обработки, используемый для извлечения интерактивных примеров из строки и использования их для создания объекта DocTest. Этот класс определяет следующие методы —

  • get_doctest () — извлекает все примеры doctest из заданной строки и собирает их в объект DocTest .

  • get_examples (string [, name]) — извлекает все примеры doctest из заданной строки и возвращает их в виде списка объектов Example . Номера строк начинаются с 0. Необязательный аргумент name является именем, идентифицирующим эту строку, и используется только для сообщений об ошибках.

  • parse (string [, name]) — Разделите данную строку на примеры и промежуточный текст и верните их в виде списка чередующихся примеров и строк. Номера строк для примеров начинаются с 0. Необязательный аргумент name является именем, идентифицирующим эту строку, и используется только для сообщений об ошибках.

get_doctest () — извлекает все примеры doctest из заданной строки и собирает их в объект DocTest .

get_examples (string [, name]) — извлекает все примеры doctest из заданной строки и возвращает их в виде списка объектов Example . Номера строк начинаются с 0. Необязательный аргумент name является именем, идентифицирующим эту строку, и используется только для сообщений об ошибках.

parse (string [, name]) — Разделите данную строку на примеры и промежуточный текст и верните их в виде списка чередующихся примеров и строк. Номера строк для примеров начинаются с 0. Необязательный аргумент name является именем, идентифицирующим эту строку, и используется только для сообщений об ошибках.

DocTestRunner Class

Это класс обработки, используемый для выполнения и проверки интерактивных примеров в DocTest. В нем определены следующие методы —

report_start ()

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

report_success ()

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

report_failure ()

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

report_unexpected_exception ()

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

бег (тест)

Запустите тестируемые примеры (объект DocTest) и отобразите результаты, используя функцию записи.

Подводя итог ([многословный])

Распечатайте сводку всех тестовых случаев, которые были выполнены этим DocTestRunner, и верните именованный кортеж TestResults (не удалось, попытка). Необязательный подробный аргумент контролирует, насколько детализирована сводка. Если многословие не указано, то используется многословие DocTestRunner.

Класс OutputChecker

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

Следующие методы определены в этом классе —

check_output ()

Верните True, если фактический результат из примера ( полученный ) совпадает с ожидаемым результатом ( хотите ). Эти строки всегда считаются совпадающими, если они идентичны; но в зависимости от того, какие флажки использует тестовый исполнитель, также возможны несколько типов неточного совпадения. Смотрите раздел Флаги параметров и Директивы для получения дополнительной информации о флагах параметров.

output_difference ()

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

Интеграция DocTest с Unittest

Модуль doctest предоставляет две функции, которые можно использовать для создания тестовых комплектов unittest из модулей и текстовых файлов, содержащих doctests. Для интеграции с обнаружением тестов unittest включите функцию load_tests () в ваш тестовый модуль —

import unittest
import doctest
import doctestexample

def load_tests(loader, tests, ignore):
   tests.addTests(doctest.DocTestSuite(doctestexample))
   return tests

Будет сформирован комбинированный TestSuite тестов из unittest и doctest, и теперь он может быть выполнен методом main () модуля unittest или методом run ().

Ниже приведены две основные функции для создания экземпляров unittest.TestSuite из текстовых файлов и модулей с doctests —

doctest.DocFileSuite ()

Он используется для преобразования тестов doctest из одного или нескольких текстовых файлов в unittest.TestSuite . Возвращенный unittest.TestSuite должен быть запущен платформой unittest и запускает интерактивные примеры в каждом файле. Если какой-либо из примеров в файле дает сбой, то синтезированный модульный тест завершается неудачей, и возникает исключение errorException, показывающее имя файла, содержащего тест, и (иногда приблизительный) номер строки.

doctest.DocTestSuite ()

Он используется для преобразования тестов doctest для модуля в unittest.TestSuite .

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

Под прикрытием DocTestSuite () создает unittest.TestSuite из экземпляров doctest.DocTestCase, а DocTestCase является подклассом unittest.TestCase.

Аналогичным образом DocFileSuite () создает unittest.TestSuite из экземпляров doctest.DocFileCase, а DocFileCase является подклассом DocTestCase.

Таким образом, оба способа создания unittest.TestSuite запускают экземпляры DocTestCase. Когда вы сами запускаете функции doctest, вы можете напрямую управлять используемыми параметрами doctest, передавая флаги параметров функциям doctest.

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

UnitTest Framework — модуль Py.test

В 2004 году Хольгер Крекел переименовал свой пакет std , имя которого часто путали с именем Стандартной библиотеки, поставляемой с Python, на имя (только немного менее запутанное) имя «py». Хотя пакет содержит несколько подпакетов, теперь он почти полностью известен своей структурой py.test.

Платформа py.test установила новый стандарт для тестирования Python и стала очень популярной среди многих разработчиков сегодня. Изящные и Pythonic идиомы, которые он ввел для написания тестов, позволили писать наборы тестов в гораздо более компактном стиле.

py.test — неоригинальная альтернатива стандартному модулю unittest Python. Несмотря на то, что это полнофункциональный и расширяемый инструмент тестирования, он имеет простой синтаксис. Создать набор тестов так же просто, как написать модуль с парой функций.

py.test работает во всех операционных системах POSIX и WINDOWS (XP / 7/8) с Python версий 2.6 и выше.

Монтаж

Используйте следующий код для загрузки модуля pytest в текущем дистрибутиве Python, а также утилиты py.test.exe. Тесты могут быть запущены с использованием обоих.

pip install pytest

использование

Вы можете просто использовать оператор assert для подтверждения ожиданий теста. Интроспекция astest в pytest будет разумно сообщать о промежуточных значениях выражения assert, освобождая вас от необходимости изучать многие имена унаследованных методов JUnit .

# content of test_sample.py
def func(x):
   return x + 1
   
def test_answer():
   assert func(3) == 5

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

C:\Python27>scripts\py.test -v test_sample.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyth
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 1 items
test_sample.py::test_answer FAILED
================================== FAILURES =====================
_________________________________ test_answer _________________________________
   def test_answer():
>  assert func(3) == 5
E     assert 4 == 5
E     + where 4 = func(3)
test_sample.py:7: AssertionError
========================== 1 failed in 0.05 seconds ====================

Тест также можно запустить из командной строки, включив модуль pytest с помощью ключа -m.

python -m pytest test_sample.py

Группировка нескольких тестов в классе

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

class TestClass:
   def test_one(self):
      x = "this"
      assert 'h' in x
   def test_two(self):
      x = "hello"
      assert hasattr(x, 'check')

Следующий результат теста будет отображаться —

C:\Python27>scripts\py.test -v test_class.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyt
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 2 items
test_class.py::TestClass::test_one PASSED
test_class.py::TestClass::test_two FAILED
================================== FAILURES =====================
_____________________________ TestClass.test_two ______________________________
self = <test_class.TestClass instance at 0x01309DA0>

   def test_two(self):
      x = "hello"
>  assert hasattr(x, 'check')
E     assert hasattr('hello', 'check')

test_class.py:7: AssertionError
===================== 1 failed, 1 passed in 0.06 seconds ======================

Тестирование носа — Framework

Нос проект был выпущен в 2005 году, через год после того, как py.test получил свой современный облик. Он был написан Джейсоном Пеллереном для поддержки тех же тестовых идиом, которые были впервые разработаны py.test, но в пакете, который проще в установке и обслуживании.

Носовой модуль можно установить с помощью утилиты pip

pip install nose

Это установит переносной модуль в текущем дистрибутиве Python, а также переносимый нос, что означает, что тест можно запустить с помощью этой утилиты, а также с ключом -m.

C:\python>nosetests –v test_sample.py
Or
C:\python>python –m nose test_sample.py

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

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

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

Основное использование

Давайте посмотрим на nosetest.py, похожий на скрипт, который использовался ранее —

# content of nosetest.py
def func(x):
   return x + 1
   
def test_answer():
   assert func(3) == 5

Для запуска вышеуказанного теста используйте следующий синтаксис командной строки —

C:\python>nosetests –v nosetest.py

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

nosetest.test_answer ... FAIL
================================================================
FAIL: nosetest.test_answer
----------------------------------------------------------------------
Traceback (most recent call last):
   File "C:\Python34\lib\site-packages\nose\case.py", line 198, in runTest
      self.test(*self.arg)
   File "C:\Python34\nosetest.py", line 6, in test_answer
      assert func(3) == 5
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)

Нос можно интегрировать с DocTest с помощью параметра with-doctest в командной строке athe bove.

\nosetests --with-doctest -v nosetest.py

Вы можете использовать нос в тестовом скрипте —

import nose
nose.main()

Если вы не хотите, чтобы тестовый скрипт завершал работу с 0 в случае успеха и 1 в случае сбоя (например, unittest.main), используйте вместо этого nose.run () —

import nose
result = nose.run()

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

нос поддерживает приспособления (методы установки и разрыва) на уровне пакета, модуля, класса и теста. Как и в случае с py.test или unittest, установка всегда выполняется перед любым тестом (или набором тестов для тестовых пакетов и модулей); Разборка запускается, если установка успешно завершена, независимо от состояния тестового прогона.

Тестирование носа — Инструменты

Модуль nose.tools предоставляет ряд вспомогательных средств тестирования, которые могут оказаться полезными, включая декораторы для ограничения времени выполнения теста и тестирования на исключения, и все те же методы assertX, что и в unittest.TestCase.

  • nose.tools.ok_ (expr, msg = None) — Сокращение для утверждения.

  • nose.tools.eq_ (a, b, msg = None) — Сокращение для «assert a == b,«% r! =% r »% (a, b)

  • nose.tools.make_decorator (func) — Оборачивает тестовый декоратор для правильной репликации метаданных оформленной функции, включая дополнительные элементы носа (а именно, установку и разбор).

  • nose.tools.raises (* исключения) — тест должен вызвать одно из ожидаемых исключений для прохождения.

  • nose.tools.timed (limit) — Тест должен завершиться в течение указанного времени, чтобы пройти

  • nose.tools.istest (func) — Декоратор, чтобы пометить функцию или метод как тест

  • nose.tools.nottest (func) — Декоратор, чтобы пометить функцию или метод как не тест

nose.tools.ok_ (expr, msg = None) — Сокращение для утверждения.

nose.tools.eq_ (a, b, msg = None) — Сокращение для «assert a == b,«% r! =% r »% (a, b)

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

nose.tools.raises (* исключения) — тест должен вызвать одно из ожидаемых исключений для прохождения.

nose.tools.timed (limit) — Тест должен завершиться в течение указанного времени, чтобы пройти

nose.tools.istest (func) — Декоратор, чтобы пометить функцию или метод как тест

nose.tools.nottest (func) — Декоратор, чтобы пометить функцию или метод как не тест

Параметризованное тестирование

Среда тестирования Python, unittest, не имеет простого способа запуска параметризованных тестовых случаев. Другими словами, вы не можете легко передать аргументы в unittest.TestCase извне.

Однако порты модуля pytest тестируют параметризацию несколькими хорошо интегрированными способами —

  • pytest.fixture () позволяет вам определять параметризацию на уровне функций фикстуры .

  • @ pytest.mark.parametrize позволяет определять параметризацию на уровне функции или класса. Он предоставляет несколько наборов аргументов / фиксаторов для конкретной тестовой функции или класса.

  • pytest_generate_tests позволяет реализовать вашу собственную схему динамической параметризации или расширения.

pytest.fixture () позволяет вам определять параметризацию на уровне функций фикстуры .

@ pytest.mark.parametrize позволяет определять параметризацию на уровне функции или класса. Он предоставляет несколько наборов аргументов / фиксаторов для конкретной тестовой функции или класса.

pytest_generate_tests позволяет реализовать вашу собственную схему динамической параметризации или расширения.

Сторонний модуль «параметризованный нос» позволяет проводить параметризованное тестирование с помощью любой среды тестирования Python. Его можно скачать по этой ссылке — https://github.com/wolever/nose-parameterized