В каком модуле присутствуют функции для тестирования программы pdb distutils profile unittest

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

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

В Python поставляется модуль unittest, который облегчает написание тестов:

  • Обнаружение и автоматическое исполнение тестов
  • Настройка теста и его завершение
  • Группирование тестов
  • Статистика тестирования

Чтобы создать тестовый случай, нужно создать класс, отнаследованный от unittest.TestCase . А внутри этого класса можно добавить несколько методов, начинающихся со слова test. Каждый из этих методов должен тестировать какой-то из аспектов кода. Для примера мы тестируем свойства строк Python: сложение строк (test_sum) и преобразование к нижнему регистру (test_lower):

Unit Testing in Python using unittest framework — Basic Introduction and How to Write Tests


import unittest class StringTestCase(unittest.TestCase): def test_sum(self): self.assertEqual(«» + «», «») self.assertEqual(«foo» + «bar», «foobar») def test_lower(self): self.assertEqual(«FOO».lower(), «foo») self.assertTrue(«foo».islower()) self.assertFalse(«Bar».islower())

Самые распространенные проверки:

self.assertEqual – непосредственно проверяет, чтобы первый аргумент равнялся второму. Если это будет не так, то тест будет провален, и появится сообщение о том, что и где пошло не так.

self.assertTrue – ожидает, что аргумент будет эквивалентен правде (True), а self.assertFalse – проверяет на ложь (False).

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

if name == ‘__main__’: unittest.main()

А можно из консоли:

python -m unittest my_test.py

Модуль unittest сам найдет все тестовые случаи и выполнит в них все тестовые функции.

Скрин результата запуска тестов

Фикстуры

Тестовые фикстуры (test fixtures) – особые условия, которые создаются для выполнения тестов. Сюда могут входить такие вещи:

  • Подготовка тестовых данных
  • Создание подключений к БД, сервисам и т.п.
  • Создание заглушек (mock) для имитации компонентов программы
  • Другие действия по поддержке рабочего окружения для проведения теста

Пример: у вас программа, которая вычисляет вычисляет число π до n-знака, и вам нужно протестировать, как будет выведен на экран миллионнный знак. Вы же не будете в тесте ждать вычисления всех предыдущих 999,999 знаков часами, а просто загрузите какие-то данные в память, чтобы создать условия, как будто мы уже на миллионом знаке.

Python Tutorial: Unit Testing Your Code with the unittest Module

В unittest фикстуры можно создавать на уровне модуля с тестами, отдельного класса (от unittest.TestCase ) и каждого метода в классе теста.

Метод setUp() вызывается перед каждым вызовом метода test* в классе тестового случая.

Классовый метод setUpClass() вызывается один раз перед запуском тестов в классе тестового случая.

Функция setUpModule() вызывается перед выполнением тестовых случаев в этом модуле.

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

tearDown() – после каждого метода-теста в классе.
tearDownClass() – после всех тестов в классе.
tearDownModule() – после всех классов в модуле.

В примере изучим порядок вызовов этих функций:

Даст такую схему вызовов:

set up module — set up class — — set up method — — tear down method — — set up method — — tear down method — tear down class tear down module

Даже если в одной из этих или тестовых функций произошло исключение, то прочие методы tearDown*() будут все равно запущены, чтобы освобождение ресурсов произошло корректно.

Пропуск тестов

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

Пример пропуска класса:

Вы можете написать свой декоратор. Например, данный декоратор пропускает тест, если объект obj не имеет атрибут attr :

В конце выполнения будут счетчики пропусков и ожидаемых провалов тестов:

OK (skipped=5, expected failures=1)

Проверки

В первой части мы обсудили методы проверки assertEqual , assertTrue и assertFalse , так как они самые распространенные на практике. Вообще достаточно одного assertTrue . Действительно, одно и тоже:

assertNotIn(item, list) assertTrue(item not in list)

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

self.assertEqual(2 + 2, 5, «я не учил математику»)

Однако, стоит упомянуть метод self.assertRaises(SomeException) , который проверяет, возбуждает ли код нужное исключение. Обычно он применяется как контекст-менеджер (с with ).

Пример: деление на 0 должно бросать исключение ZeroDivisionError :

import unittest def my_div(a, b): return a // b class MyDivTestCase(unittest.TestCase): def test_1(self): self.assertEqual(my_div(10, 2), 5) # при делении на 0 ждем исключение: with self.assertRaises(ZeroDivisionError): my_div(7, 0) # или так: исключение, ф-ция, аргументы self.assertRaises(ZeroDivisionError, my_div, 5, 0) unittest.main()

Читайте также:
Как настроить программу Tor

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

with self.assertRaises(SomeException) as cm: do_something() self.assertEqual(cm.exception.error_code, 3)

Картинка с таблицей проверок и что они проверяют

PyTest

Ранее мы обсуждали тестирование средствами встроенного модуля unittest. Естественно, есть и сторонние библиотеки для тестирования. Например, библиотека PyTest предоставляет более лаконичный и удобный инструментарий для написания тестов. Однако, ее нужно установить:

pip install pytest

  • Краткий и красивый код
  • Только один стандартный assert
  • Подробный отчет
  • Разнообразие фикстур на всех уровнях
  • Плагин и интеграции с другими системами

Сравните этот код с кодом из предыдущих постов про unittest:

import pytest def setup_module(module): #init_something() pass def teardown_module(module): #teardown_something() pass def test_upper(): assert ‘foo’.upper() == ‘FOO’ def test_isupper(): assert ‘FOO’.isupper() def test_failed_upper(): assert ‘foo’.upper() == ‘FOo’

Для тестов можно применять и классы (как в unittest), так и отдельные функции.

Запускать тесты тоже просто. В окружении, где установлен pytest, появится команда py.test. Из терминала пишем:

py.test my_test_cases.py

py.test обнаружит и выполнит тесты из этого файла.

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

Источник: tirinox.ru

Русские Блоги

[Запись Python] 19. Отладчик pdb, unit test unittest и тестовый документ doctest

Описание: различные методы отладки представляют assert, logging, debugger pdb; метод написания модульного теста unittest, как запустить модульный тест; написание документа test doctest

* Напишите впереди: чтобы лучше изучить Python, блоггер записывает свое учебное путешествие. Это исследование основано наУчебник по Python Ляо Сюэфэна, Если есть какие-либо нарушения, сообщите об удалении. Добро пожаловать на изучение Python с блоггерами ヽ ( ̄ ▽  ̄) ノ *

оглавление

Отладка и тестирование
отладка
• print
• assert
• logging
• PDB отладчика
• pdb.set_trace( )
• IDE
unit test unittest
• Написание модульного теста
• Метод модульного тестирования
• Запускать модульные тесты.
• setUp () и tearDown ()
doctest

Отладка и тестирование

отладка

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

• print

Самый простой и грубый метод — это печать, если вы распечатываете переменные, которые могут быть неправильными.

def fn(s): n = s print(‘>>> n = %d’ % n) return 10 / n def main(): fn(0) main()
>>> n = 0 Traceback (most recent call last): . ZeroDivisionError: division by zero

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

• Утверждать

Его можно использовать везде, где используется печать вышеassertВместо.

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

def fn(s): n = s assert n != 0, ‘>>> n = 0’ return 10 / n def main(): fn(0) main()
Traceback (most recent call last): . AssertionError: >>> n = 0

assert означает объявить и утверждать, что n не должно быть равно 0, но если результат n равен 0, утверждение не выполняется, выдает ошибку AssertionError и выводит следующую строку ‘>>> n = 0’.

По сравнению с print, assert можно отключить с помощью параметра -O, и все операторы assert после закрытия эквивалентны pass. Например, сохраните приведенный выше код как файл err.py и запустите его в интерпретаторе python:

python -O err.py
Traceback (most recent call last): . ZeroDivisionError: division by zero

Видно, что assert закрыт, а интерпретатор печатает ZeroDivisionError вместо AssertionError.

• logging

Ведение журнала также может выводить ошибки.

import logging s = 0 n = s logging.info(‘n = %d’ % n) print(10 / n)

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

Добавить после регистрации импорта:

logging.basicConfig(level=logging.INFO)

Запускаем снова в это время:

INFO:root:n = 0 Traceback (most recent call last): . ZeroDivisionError: division by zero

Отображаемое сообщение об ошибке — это сообщение после logging.info.

loggingПреимущество заключается в том, что он позволяет вам указать уровень информации журнала. Всего существует пять уровней, от маленького до большого:debug,info,warning,error,critical. Уровень по умолчанию — предупреждение. Будет напечатана только информация, превышающая или равная уровню предупреждения. Конечно, вы можете изменить уровень, поэтому в начале информация не печатается.

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

• Отладчик pdb

pdb, отладчик Python, Отладчик Python. Отладчик позволяет программе запускаться шаг за шагом и проверять состояние выполнения.

Сначала напишите простой файл py:

# err.py s = ‘0’ n = int(s) print(10 / n)

Запустите err.py с параметром -m pdb в режиме командной строки:

python -m pdb err.py

После запуска pdb он автоматически найдет следующий исполняемый код «s = ‘0’», а затем будет ждать ввода после (pdb).

Введите команду с буквой l, чтобы просмотреть все коды ошибки err.py:

(Pdb) l 1 # err.py 2 -> s = ‘0’ 3 n = int(s) 4 print(10 / n)

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

Введите букву n для перехода по коду:

(Pdb) n > c:usersadministratorerr.py(3)() -> n = int(s) (Pdb) n > c:usersadministratorerr.py(4)() -> print(10 / n)

Введите букву p и имя переменной, чтобы просмотреть переменную:

(Pdb) p s ‘0’ (Pdb) p n 0

Введите букву q, чтобы завершить отладку:

(Pdb) q

• pdb.set_trace( )

set_trace — установить точку останова. Добавить утверждения, где могут быть ошибкиpdb.set_trace()Вы можете установить точку останова

# err.py import pdb s = ‘0’ n = int(s) pdb.set_trace () # Он автоматически приостанавливается при запуске здесь print(10 / n)

Когда код запускается в pdb.set_trace (), он приостанавливается и автоматически входит в среду отладки pdb. Описанные выше команды могут быть выполнены для отладки. Введите c, чтобы продолжить работу.

Этот метод немного более эффективен, чем пошаговая отладка pdb.

• IDE

Integrated Development Environment, Интегрированная среда разработки или IDE. Приложения, используемые в среде разработки программ.

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

В настоящее время существуют лучшие IDE для Python:
pycharm
Eclipse + PyDev
Visual Studio + PTVS

Модульный тест

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

Например, если мы хотим протестировать функцию abs, дайте следующий тестовый пример:

Введите положительное число, 1, 100, 0,1, и ожидайте вывода 1, 10, 0,1;
Введите отрицательное число, -1, -100, -0,1, и ожидайте вывода 1, 10, 0,1;
Введите 0, ожидайте вывода 0;
Введите нечисловой тип, ‘a’, [], <>, ожидайте вывода TypeError

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

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

Приведем пример с официального сайта Liao Xuefeng, чтобы познакомить с написанием модульных тестов на Python.

• Написание модульных тестов

Если мы хотим написать класс Dict, цель такая же, как и у встроенного dict, но к нему можно получить доступ через атрибуты, например:

>>> d = Dict(a=1, b=2) >>> d[‘a’] 1 >>> d.a 1

Так что напишите mydict:

class Dict(dict): def __init__(self, **kw): super () .__ init __ (** kw) # Атрибуты экземпляра класса Dict наследуют dict def __getattr __ (self, key): # При доступе к атрибуту ключа экземпляра, но без атрибута ключа, вызовите этот метод try: return self [key] # Пытаться вернуть значение, соответствующее ключевому ключу except KeyError: raise AttributeError(r»‘Dict’ object has no attribute ‘%s'» % key) # Если возврат завершился неудачно, это означает, что Dict не имеет этого атрибута def __setattr __ (self, key, value): # Установить метод присваивания setattr self[key] = value

Затем начните писать модуль модульного тестирования mydict_test.py.

Во-первых, нам нужно представить собственный Pythonмодуль unittestИ напишите модуль DIct, а затем определите тестовый класс, этот класс наследует unittest.TestCase

import unittest from mydict import Dict class TestDice(unittest.TestCase): pass

• Метод модульного тестирования

Далее следует написать методы тестирования. Для каждого типа теста необходимо написать метод test_xxx (). Методы, начинающиеся с test, являются методами тестирования.

Методы, не начинающиеся с test, не считаются методами тестирования и не будут выполняться.

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

assertEqual( )Передайте два параметра, один — это объект, который нужно выполнить, а другой — результат, который, как ожидается, будет возвращен после выполнения объекта.

self.assertEqual (abs (-1), 1) # Утверждаем, что результат, возвращаемый функцией, равен 1

assertTrue( ), Ожидайте, что значение, возвращенное в скобках, будет истинным.

self.assertTrue(abs(-1) == 1)

assertRaises( ):, ожидайте, что оператор после двоеточия выдаст ошибку внутри скобок.

with self.assertRaises(TypeError): abs(‘a’)

Основные стандартные модули Python

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

В качестве иллюстрации можно предположить, что создается модуль для вычисления простых чисел по алгоритму » решето Эратосфена «. Модуль будет находиться в файле Sieve.py и состоять из одной функции primes(N) , которая в результате своей работы дает все простые (не имеющие натуральных делителей кроме себя и единицы) числа от 2 до N :

import sets import math «»»Модуль для вычисления простых чисел от 2 до N «»» def primes(N): «»»Возвращает все простые от 2 до N»»» sieve = sets.Set(range(2, N)) for i in range(2, int(math.sqrt(N)+1)): if i in sieve: sieve -= sets.Set(range(2*i, N, i)) return sieve

Модуль pdb

Модуль pdb предоставляет функции отладчика с интерфейсом — командной строкой. Сессия отладки вышеприведенного модуля могла бы быть такой:

>>> import pdb >>> pdb.runcall(Sieve.primes, 100) > /home/rnd/workup/intuit-python/examples/Sieve.py(15)primes() -> sieve = sets.Set(range(2, N)) (Pdb) l 10 import sets 11 import math 12 «»»Модуль для вычисления простых чисел от 2 до N «»» 13 def primes(N): 14 «»»Возвращает все простые от 2 до N»»» 15 -> sieve = sets.Set(range(2, N)) 16 for i in range(2, int(math.sqrt(N)+1)): 17 if i in sieve: 18 sieve -= sets.Set(range(2*i, N, i)) 19 return sieve 20 (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(16)primes() -> for i in range(2, int(math.sqrt(N)+1)): (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(17)primes() -> if i in sieve: (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(18)primes() -> sieve -= sets.Set(range(2*i, N, i)) (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(16)primes() -> for i in range(2, int(math.sqrt(N)+1)): (Pdb) p sieve Set([2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]) (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(17)primes() -> if i in sieve: (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(18)primes() -> sieve -= sets.Set(range(2*i, N, i)) (Pdb) n > /home/rnd/workup/intuit-python/examples/Sieve.py(16)primes() -> for i in range(2, int(math.sqrt(N)+1)): (Pdb) p sieve Set([2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97])

Читайте также:
Это программы перехватывающие вирусоопасные ситуации
Модуль profile

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

Продолжая пример с решетом Эратосфена , стоит посмотреть, как тратится процессорное время при вызове функции primes() :

>>> profile.run(«Sieve.primes(100000)») 709 function calls in 1.320 CPU seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.010 0.010 1.320 1.320 :1(?) 1 0.140 0.140 1.310 1.310 Sieve.py:13(primes) 1 0.000 0.000 1.320 1.320 profile:0(Sieve.primes(100000)) 0 0.000 0.000 profile:0(profiler) 65 0.000 0.000 0.000 0.000 sets.py:119(__iter__) 314 0.000 0.000 0.000 0.000 sets.py:292(__contains__) 65 0.000 0.000 0.000 0.000 sets.py:339(_binary_sanity_check) 66 0.630 0.010 0.630 0.010 sets.py:356(_update) 66 0.000 0.000 0.630 0.010 sets.py:425(__init__) 65 0.010 0.000 0.540 0.008 sets.py:489(__isub__) 65 0.530 0.008 0.530 0.008 sets.py:495(difference_update)

Здесь ncalls — количество вызовов функции или метода, tottime — полное время выполнения кода функции (без времени нахождения в вызываемых функциях), percall — тоже, в пересчете на один вызов, cumtime — аккумулированное время нахождения в функции, вместе со всеми вызываемыми функциями. В последнем столбце приведено имя файла, номер строки с функцией или методом и его имя.

«Странные» имена, например, __iter__ , __contains__ и __isub__ — имена методов, реализующих итерацию по элементам, проверку принадлежности элемента ( in ) и операцию -= . Метод __init__ — конструктор объекта (в данном случае — множества).

Модуль unittest

При разработке программного обеспечения рекомендуется применять так называемые регрессионные испытания. Для каждого модуля составляется набор тестов, по возможности таким образом, чтобы проверялись не только типичные вычисления, но и «крайние», вырожденные случаи, чтобы испытания затронули каждую ветку алгоритма хотя бы один раз. Тест для данного модуля (написанный сразу после того, как определен интерфейс модуля) находится в файле test_Sieve.py :

# file: test_Sieve.py import Sieve, sets import unittest class TestSieve(unittest.TestCase): def setUp(self): pass def testone(self): primes = Sieve.primes(1) self.assertEqual(primes, sets.Set()) def test100(self): primes = Sieve.primes(100) self.assert_(primes == sets.Set([2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97])) if __name__ == ‘__main__’: unittest.main()

Тестовый модуль состоит из определения класса, унаследованного от класса unittest.TestCase , в котором описывается подготовка к испытаниям (метод setUp ) и сами испытания — методы, начинающиеся на test . В данном случае таких испытаний всего два: в первом испытывается случай N=1 , а во втором — N=100 .

Запуск тестов производится выполнением функции unittest.main() . Вот как выглядят успешные испытания:

$ python test_Sieve.py .. ———————————————————————- Run 2 tests in 0.002s OK

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

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

Модуль pydoc

Успех проекта зависит не только от обеспечения эффективного и качественного кода, но и от качества документации. Утилита pydoc аналогична команде man в Unix:

$ pydoc Sieve Help on module Sieve: NAME Sieve — Модуль для вычисления простых чисел от 2 до N FILE Sieve.py FUNCTIONS primes(N) Возвращает все простые от 2 до N

Эта страница помощи появилась благодаря тому, что были написаны строки документации — как ко всему модулю, так и к функции primes(N) .

Стоит попробовать запустить pydoc следующей командой:

pydoc -p 8088

И направить браузер на URL http://127.0.0.1:8088/ — можно получить документацию по модулям Python в виде красивого web-сайта.

Узнать другие возможности pydoc можно, подав команду pydoc pydoc .

Пакет docutils

Этот пакет и набор утилит пока что не входит в стандартную поставку Python, однако о нем нужно знать тем, кто хочет быстро готовить документацию (руководства пользователя и т.п.) для своих модулей. Этот пакет использует специальный язык разметки (ReStructuredText), из которого потом легко получается документация в виде HTML, LaTeX и в других форматах. Текст в формате RST легко читать и в исходном виде. С этим инструментом можно познакомиться на http://docutils.sourceforge.net

Пакет distutils
Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru