Защита мобильных устройств

Модуль unittest: тестируем свои программы

Очень просто сделать свой декоратор


Представьте, что вы написали какую-либо программу, а теперь хотите проверить, правильно ли она работает. Что вы для этого сделаете? Скорее всего, вы запустите её несколько раз с различными входными данными, и убедитесь в правильности выдаваемого ответа.
А теперь вы что-то поменяли и снова хотите проверить корректность программы. Запускать ещё несколько раз? А если потом снова что-то поменяется?

Нельзя ли как-то автоматизировать это дело?
Оказывается, можно. В Python встроен модуль unittest, который поддерживает автоматизацию тестов, использование общего кода для настройки и завершения тестов, объединение тестов в группы, а также позволяет отделять тесты от фреймворка для вывода информации.
Для автоматизации тестов, unittest поддерживает некоторые важные концепции:


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

  • Тестовый случай (test case) - минимальный блок тестирования. Тестирование на проникновение Он проверяет ответы для разных наборов данных. Модуль unittest предоставляет базовый класс TestCase, который можно использовать для создания новых тестовых случаев.

  • Набор тестов (test suite) - несколько тестовых случаев, наборов тестов или и того и другого. Он используется для объединения тестов, которые должны быть выполнены вместе.

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


  • Модуль unittest предоставляет богатый набор инструментов для написания и запуска тестов. Однако достаточно лишь некоторых из них, чтобы удовлетворить потребности большинства пользователей.
    Вот короткий скрипт для тестирования трех методов строк:
    Тестовый случай создаётся путём наследования от unittest.TestCase. 3 отдельных теста определяются с помощью методов, имя которых начинается на test. Это соглашение говорит исполнителю тестов о том, какие методы являются тестами.
    Суть каждого теста - вызов assertEqual() для проверки ожидаемого результата; assertTrue() или assertFalse() для проверки условия; assertRaises() для проверки, что метод порождает исключение. Эти методы используются вместо обычного assert для того, чтобы исполнитель тестов смог взять все результаты и оформить отчёт.
    Методы setUp() и tearDown() (которые в данном простом случае не нужны) позволяют определять инструкции, выполняемые перед и после каждого теста, соответственно.
    Последние 2 строки показывают простой способ запуска тестов. unittest.main() предоставляет интерфейс командной строки для тестирования программы. pentest тестирование на проникновение Будучи запущенным из командной строки, этот скрипт выводит отчёт, подобный этому:
    unittest может быть использован из командной строки для запуска модулей с тестами, классов или даже отдельных методов:
    Можно также указывать путь к файлу:
    С помощью флага -v можно получить более детальный отчёт:
    Для нашего примера подробный отчёт будет таким:
    -b ( --buffer ) - вывод программы при провале теста будет показан, а не скрыт, как обычно.
    -c ( --catch ) - Ctrl+C во время выполнения теста ожидает завершения текущего теста и затем сообщает результаты на данный момент. Второе нажатие Ctrl+C вызывает обычное исключение KeyboardInterrupt.
    -f ( --failfast ) - выход после первого же неудачного теста.
    --locals (начиная с Python 3.5) - показывать локальные переменные для провалившихся тестов.
    unittest поддерживает простое обнаружение тестов. Для совместимости с обнаружением тестов, все файлы тестов должны быть модулями или пакетами, импортируемыми из директории верхнего уровня проекта (см. подробнее о правилах наименования модулей ).
    Обнаружение тестов реализовано в TestLoader.discover(), но может быть использовано из командной строки:
    -s ( --start-directory ) directory_name - директория начала обнаружения тестов (текущая по умолчанию).
    -p ( --pattern ) pattern - шаблон названия файлов с тестами (по умолчанию test*.py).
    -t ( --top-level-directory ) directory_name - директория верхнего уровня проекта (по умолчанию равна start-directory ).
    Базовые блоки тестирования это тестовые случаи - простые случаи, которые должны быть проверены на корректность.
    Тестовый случай создаётся путём наследования от unittest.TestCase.
    Тестирующий код должен быть самостоятельным, то есть никак не зависеть от других тестов.
    Простейший подкласс TestCase может просто реализовывать тестовый метод (метод, начинающийся с test). Вымышленный пример:
    Заметьте, что для того, чтобы проверить что-то, мы используем один из assert\*() методов.
    Тестов может быть много, и часть кода настройки может повторяться. К счастью, мы можем определить код настройки путём реализации метода setUp(), который будет запускаться перед каждым тестом:
    Мы также можем определить метод tearDown(), который будет запускаться после каждого теста:
    Можно разместить все тесты в том же файле, что и сама программа (таком как widgets.py), но размещение тестов в отдельном файле (таком как test_widget.py) имеет много преимуществ:

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

    • Тестовый код может быть легко отделён от программы.

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

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

    • Протестированный код может быть легче переработан.

    • Тесты для модулей на C должны быть в отдельных модулях, так почему же не быть последовательным?

    • Если стратегия тестирования изменяется, нет необходимости изменения кода программы.


    • unittest поддерживает пропуск отдельных тестов, а также классов тестов. Вдобавок, поддерживается пометка теста как не работает, но так и надо.
      Пропуск теста осуществляется использованием декоратора skip() или одного из его условных вариантов.
      Классы также могут быть пропущены:
      Ожидаемые ошибки используют декоратор expectedFailure():
      Очень просто сделать свой декоратор. Например, следующий декоратор пропускает тест, если переданный объект не имеет указанного атрибута:
      Декораторы, пропускающие тесты или говорящие об ожидаемых ошибках:
      @unittest.skip(reason) - пропустить тест. reason описывает причину пропуска.
      @unittest.skipIf(condition, reason) - пропустить тест, если condition истинно.
      @unittest.skipUnless(condition, reason) - пропустить тест, если condition ложно.
      @unittest.expectedFailure - пометить тест как ожидаемая ошибка.
      Для пропущенных тестов не запускаются setUp() и tearDown(). Для пропущенных классов не запускаются setUpClass() и tearDownClass(). Для пропущенных модулей не запускаются setUpModule() и tearDownModule().
      Когда некоторые тесты имеют лишь незначительные отличия, например некоторые параметры, unittest позволяет различать их внутри одного тестового метода, используя менеджер контекста subTest().
      Например, следующий тест:
      даст следующий отчёт:
      Без использования подтестов, выполнение будет остановлено после первой ошибки, и ошибку будет сложнее диагностировать, потому что значение i не будет показано:
      Модуль unittest предоставляет множество функций для самых различных проверок:
      assertIsNotNone(x) — x is not None
      assertIsInstance(a, b) — isinstance(a, b)
      assertNotIsInstance(a, b) — not isinstance(a, b)
      assertRaises(exc, fun, *args, **kwds) — fun(*args, **kwds) порождает исключение exc
      assertRaisesRegex(exc, r, fun, *args, **kwds) — fun(*args, **kwds) порождает исключение exc и сообщение соответствует регулярному выражению r
      assertWarns(warn, fun, *args, **kwds) — fun(*args, **kwds) порождает предупреждение
      assertWarnsRegex(warn, r, fun, *args, **kwds) — fun(*args, **kwds) порождает предупреждение и сообщение соответствует регулярному выражению r
      assertNotAlmostEqual(a, b) — round(a-b, 7) != 0
      assertCountEqual(a, b) — a и b содержат те же элементы в одинаковых количествах, но порядок не важен
      Обсуждение вопросов, не связанных со статьёй (в т.ч. комментарии типа Помогите!), ведётся на форуме pythonworld.club, а не в комментариях.
      Для вставки кода на Python в комментарий заключайте его в теги precode class=python3Ваш код/code/pre

      Похожие статьи Pentest

      • Новости информационной безопасности

        Пентест может оказаться на уровне state-of-art, или, наоборот, разочаровывающим. Многое зависит от ваших ожиданий, которые сформированы предыдущим...

      • Взлом спосощью metasploit framework

        Metasploit Framework программа и субпроект разработанный Metasploit LLC. Изначально она была роздана в 2003 году на Perl, но позже была кардинально...

      • Комплексное тестирование

        Правила формирования структуры 1. Структура программного изделия и правила оформления описания каждого модуля должны быть унифицированы. 2. Каждый модуль...

      • Что нужно знать о тестировании на проникновение

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