Статьи

Начало тестовой разработки в Python

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

Я представлю основные понятия TDD.

Весь процесс очень прост в освоении, и это не займет много времени, прежде чем вы задумаетесь, как вы смогли сделать что-то раньше! От TDD можно добиться огромных преимуществ, а именно: улучшить качество вашего кода, а также внести ясность и сосредоточиться на том, чего вы пытаетесь достичь, и на том, как вы этого добьетесь. TDD также беспрепятственно работает с гибкой разработкой и может лучше всего использоваться при парном программировании, как вы увидите позже.

В этом уроке я познакомлю вас с основными понятиями TDD и приведу примеры на Python, используя пакет модульного тестирования для носовых тестов. Я дополнительно предложу несколько альтернативных пакетов, которые также доступны в Python.


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

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

Вы можете видеть, что TDD — это большой цикл, в котором ваш код проходит столько итераций тестов, написания и разработки, сколько необходимо, до тех пор, пока функция не будет завершена. Реализация этих тестов до того, как вы напишите код, выявляет естественную тенденцию сначала думать о вашей проблеме. Пока вы начинаете создавать свой тест, вы должны думать о том, как вы разрабатываете свой код. Что вернет этот метод? Что если мы получим исключение здесь? И так далее.

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

Процесс можно определить так:

  • Написать неудачный юнит-тест
  • Сделайте прохождение модульного теста
  • Refactor

Повторите этот процесс для каждой функции, если это необходимо.


TDD идеально соответствует идеалам и принципам процесса Agile Development, с огромным стремлением предоставлять постепенные обновления продукта с истинным качеством, а не с количеством. Уверенность в ваших отдельных единицах кода, которую обеспечивает модульное тестирование, означает, что вы выполняете это требование для обеспечения качества, одновременно устраняя проблемы в вашей производственной среде.

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

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

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

TDD также является неотъемлемой частью процесса разработки, основанной на поведении, который, опять же, заключается в написании тестов заранее, но в форме приемочных тестов. Это гарантирует, что функция «ведет себя» так, как вы ожидаете от конца до конца. Дополнительную информацию можно найти в следующей статье Tuts +, которая будет посвящена BDD в Python.


Основные методы, которые мы используем в модульном тестировании для Python:

  • assert : base assert, позволяющий вам писать свои собственные утверждения
  • assertEqual(a, b) : проверьте, что a и b равны
  • assertNotEqual(a, b) : проверьте, что a и b не равны
  • assertIn(a, b) : проверьте, что a находится в элементе b
  • assertNotIn(a, b) : проверьте, что a нет в элементе b
  • assertFalse(a) : проверьте, что значение a является Ложным
  • assertTrue(a) : проверьте, что значение a — True
  • assertIsInstance(a, TYPE) : проверьте, что a имеет тип «TYPE»
  • assertRaises(ERROR, a, args) : проверьте, что когда a вызывается с аргументами, он вызывает ERROR

Нам, безусловно, доступно больше методов, которые вы можете просмотреть — см. Документы по модульному тестированию Python — но, по моему опыту, перечисленные выше являются одними из наиболее часто используемых. Мы будем использовать их в наших примерах ниже.

Перед тем, как приступить к упражнениям, приведенным ниже, вам необходимо установить nosetest тестирования nosetest . Установка бегунка для nosetest проста, следуя стандартной схеме установки «pip». Также обычно хорошей идеей является работа над вашими проектами с помощью virtualenv, который хранит все пакеты, которые вы используете для различных проектов, отдельно. Если вы не знакомы с pip или virtualenv, вы можете найти документацию по ним здесь: VirtualEnv , PIP .

Установка pip так же проста, как и запуск этой строки:

1
«pip install nose»

После установки вы можете выполнить один тестовый файл.

1
$ nosetests example_unit_test.py

Или выполнить набор тестов в папке.

1
$ nosetests /path/to/tests

Единственный стандарт, которому вы должны следовать, — это начинать каждый метод теста с «test_», чтобы бегун-тестер мог найти ваши тесты!

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

  • -v : дает более подробный вывод, включая имена выполняемых тестов.
  • -s или -nocapture : позволяет выводить операторы печати, которые обычно -nocapture и скрываются при выполнении тестов. Полезно для отладки.
  • --nologcapture : позволяет выводить информацию регистрации.
  • --rednose : необязательный плагин, который можно скачать здесь , но предоставляет цветной вывод для тестов.
  • --tags=TAGS : позволяет поместить @TAG над определенным тестом, чтобы выполнять только его, а не весь набор тестов.

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

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

В пустом проекте создайте два пакета python — app и test . Чтобы сделать их пакетами Python (и, следовательно, позже поддерживать импорт файлов в тестах), создайте пустой файл с именем __init__.py в каждом каталоге. Это стандартная структура Python для проектов, и она должна быть сделана для того, чтобы элемент можно было импортировать через структуру каталогов. Для лучшего понимания этой структуры вы можете обратиться к документации по пакетам Python . Создайте файл с именем test_calculator.py в каталоге test со следующим содержимым.

1
2
3
4
5
6
7
8
import unittest
 
class TddInPythonExample(unittest.TestCase):
 
    def test_calculator_add_method_returns_correct_result(self):
        calc = Calculator()
        result = calc.add(2,2)
        self.assertEqual(4, result)

Написание теста довольно просто.

  • Сначала мы импортируем стандартный модуль unittest из стандартной библиотеки Python.
  • Далее нам нужен класс для хранения различных тестовых случаев.
  • Наконец, для самого теста требуется метод, с единственным требованием, чтобы в начале он назывался «test_», чтобы его мог выбрать и выполнить бегун- nosetest , о котором мы вскоре расскажем.

Имея структуру, мы можем написать тестовый код. Мы инициализируем наш калькулятор, чтобы мы могли выполнять методы на нем. После этого мы можем затем вызвать метод add который мы хотим протестировать, и сохранить его значение в переменной result . Как только это будет завершено, мы сможем использовать метод unitsert assertEqual чтобы убедиться, что метод add нашего калькулятора работает так, как ожидалось.

Теперь вы будете использовать бегун для проверки nosetest для выполнения теста. При желании вы можете выполнить тест, используя стандартный unittest runner, добавив следующий блок кода в конец файла теста.

1
2
if __name__ == ‘__main__’:
   unittest.main()

Это позволит вам запустить тест, используя стандартный способ выполнения файлов Python, $ python test_calculator.py . Тем не менее, в этом уроке вы собираетесь использовать nosetests , у которого есть некоторые приятные функции, такие как возможность выполнения тестов носа для каталога и запуск всех тестов, среди других полезных функций.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$ nosetests test_calculator.py
E
======================================================================
ERROR: test_calculator_add_method_returns_correct_result (test.test_calculator.TddInPythonExample)
———————————————————————-
Traceback (most recent call last):
  File «/Users/user/PycharmProjects/tdd_in_python/test/test_calculator.py», line 6, in test_calculator_add_method_returns_correct_result
    calc = Calculator()
NameError: global name ‘Calculator’ is not defined
 
———————————————————————-
Ran 1 test in 0.001s
 
FAILED (errors=1)

Исходя из результатов теста носа, мы видим, что проблема связана с тем, что мы не импортируем Calculator . Это потому, что мы еще не создали его! Итак, давайте определимся с Calculator в файле с именем calculator.py в каталоге app и импортируем его:

1
2
3
4
class Calculator(object):
 
       def add(self, x, y):
           pass
01
02
03
04
05
06
07
08
09
10
11
12
13
import unittest
from app.calculator import Calculator
 
class TddInPythonExample(unittest.TestCase):
 
    def test_calculator_add_method_returns_correct_result(self):
        calc = Calculator()
        result = calc.add(2,2)
        self.assertEqual(4, result)
 
 
if __name__ == ‘__main__’:
    unittest.main()

Теперь, когда мы определили Calculator , давайте посмотрим, что нам сейчас показывает тест на нос:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$ nosetests test_calculator.py
F
======================================================================
FAIL: test_calculator_add_method_returns_correct_result (test.test_calculator.TddInPythonExample)
———————————————————————-
Traceback (most recent call last):
  File «/Users/user/PycharmProjects/tdd_in_python/test/test_calculator.py», line 9, in test_calculator_add_method_returns_correct_result
    self.assertEqual(4, result)
AssertionError: 4 != None
 
———————————————————————-
Ran 1 test in 0.001s
 
FAILED (failures=1)

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

1
2
3
4
class Calculator(object):
 
       def add(self, x, y):
           return x+y
1
2
3
4
5
6
$ nosetests test_calculator.py
.
———————————————————————-
Ran 1 test in 0.000s
 
OK

Успех! Мы определили наш метод add и он работает как ожидалось. Тем не менее, есть еще работа над этим методом, чтобы убедиться, что мы проверили его должным образом.

Мы попали в ловушку простого тестирования интересующего нас случая на данный момент.

Что произойдет, если кто-то добавит что-то кроме цифр? Python фактически позволяет добавлять строки и другие типы, но в нашем случае для нашего калькулятора имеет смысл разрешать только добавление чисел. Давайте добавим еще один неудачный тест для этого случая, используя метод assertRaises чтобы проверить, возникает ли здесь исключение:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
import unittest
from app.calculator import Calculator
 
 
class TddInPythonExample(unittest.TestCase):
 
    def setUp(self):
        self.calc = Calculator()
 
    def test_calculator_add_method_returns_correct_result(self):
        result = self.calc.add(2, 2)
        self.assertEqual(4, result)
 
    def test_calculator_returns_error_message_if_both_args_not_numbers(self):
        self.assertRaises(ValueError, self.calc.add, ‘two’, ‘three’)
 
 
if __name__ == ‘__main__’:
    unittest.main()

Вы можете видеть сверху, что мы добавили тест и теперь проверяем, не возникла ли ValueError , если мы передадим строки. Мы могли бы также добавить больше проверок для других типов, но пока мы будем делать все просто. Вы также можете заметить, что мы использовали метод setup() . Это позволяет нам размещать вещи перед каждым тестом. Итак, поскольку нам нужно, чтобы наш объект Calculator был доступен в обоих тестовых случаях, имеет смысл инициализировать это в методе setUp . Давайте посмотрим, что нам сейчас показывает тест на нос:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$ nosetests test_calculator.py
.F
======================================================================
FAIL: test_calculator_returns_error_message_if_both_args_not_numbers (test.test_calculator.TddInPythonExample)
———————————————————————-
Traceback (most recent call last):
  File «/Users/user/PycharmProjects/tdd_in_python/test/test_calculator.py», line 15, in test_calculator_returns_error_message_if_both_args_not_numbers
    self.assertRaises(ValueError, self.calc.add, ‘two’, ‘three’)
AssertionError: ValueError not raised
 
———————————————————————-
Ran 2 tests in 0.001s
 
FAILED (failures=1)

Очевидно, что nosetests указывает нам, что мы не поднимаем ValueError когда ожидаем. Теперь, когда у нас есть новый провальный тест, мы можем написать решение, чтобы оно прошло успешно.

1
2
3
4
5
6
7
8
class Calculator(object):
   def add(self, x, y):
       number_types = (int, long, float, complex)
 
       if isinstance(x, number_types) and isinstance(y, number_types):
           return x + y
       else:
           raise ValueError

Из приведенного выше кода видно, что мы добавили небольшое дополнение для проверки типов значений и их соответствия тем, что мы хотим. Один из подходов к этой проблеме может означать, что вы следуете за типизацией утки и просто пытаетесь использовать ее как число, а также «пробуете / исключаете» ошибки, которые будут возникать в других случаях. Вышеприведенный пример является крайним случаем и означает, что мы должны проверить, прежде чем двигаться вперед. Как упоминалось ранее, строки могут быть объединены с символом плюса, поэтому мы хотим разрешить только числа. Использование метода isinstance позволяет нам гарантировать, что предоставленные значения могут быть только числами.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import unittest
from app.calculator import Calculator
 
 
class TddInPythonExample(unittest.TestCase):
    def setUp(self):
        self.calc = Calculator()
 
    def test_calculator_add_method_returns_correct_result(self):
        result = self.calc.add(2, 2)
        self.assertEqual(4, result)
 
    def test_calculator_returns_error_message_if_both_args_not_numbers(self):
        self.assertRaises(ValueError, self.calc.add, ‘two’, ‘three’)
 
    def test_calculator_returns_error_message_if_x_arg_not_number(self):
        self.assertRaises(ValueError, self.calc.add, ‘two’, 3)
 
    def test_calculator_returns_error_message_if_y_arg_not_number(self):
        self.assertRaises(ValueError, self.calc.add, 2, ‘three’)
 
 
if __name__ == ‘__main__’:
    unittest.main()

Запустив все эти тесты сейчас, мы можем подтвердить, что метод соответствует нашим требованиям!

1
2
3
4
5
6
$ nosetests test_calculator.py
….
———————————————————————-
Ran 4 tests in 0.001s
 
OK

Это nosetest , подобный тесту nosetest , который использует те же соглашения, что означает, что вы можете выполнить свои тесты в любом из двух. Приятной особенностью pytest является то, что он захватывает ваш вывод из теста внизу в отдельной области, что означает, что вы можете быстро увидеть все, что напечатано в командной строке (см. Ниже). Я обнаружил, что pytest полезен при выполнении отдельных тестов, в отличие от набора тестов.

Чтобы установить pytest Runner, следуйте той же процедуре установки pip, которую вы выполнили, чтобы установить nosetest . Просто запустите $ pip install pytest и он получит последнюю версию и установится на ваш компьютер. Затем вы можете запустить бегунка в соответствии с вашим набором тестов, $ py.test test/ каталог ваших тестовых файлов, $ py.test test/ , или вы можете $ py.test test/ путь к тестовому файлу, который вы хотите выполнить: $ py.test test/calculator_tests.py

1
2
3
4
5
6
7
8
$ py.test test/test_calculator.py
================================================================= test session starts =================================================================
platform darwin — Python 2.7.6 — py-1.4.26 — pytest-2.6.4
collected 4 items
 
test/test_calculator.py ….
 
============================================================== 4 passed in 0.02 seconds ===============================================================

Пример pytest при печати из ваших тестов или кода показан ниже. Это может быть полезно для быстрой отладки ваших тестов и просмотра некоторых данных, которыми он манипулирует. ПРИМЕЧАНИЕ. Вывод из вашего кода будет показан только при ошибках или сбоях в ваших тестах, в противном случае pytest любой вывод.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ py.test test/test_calculator.py
================================================================= test session starts =================================================================
platform darwin — Python 2.7.6 — py-1.4.26 — pytest-2.6.4
collected 4 items
 
test/test_calculator.py F…
 
====================================================================== FAILURES =======================================================================
________________________________________ TddInPythonExample.test_calculator_add_method_returns_correct_result _________________________________________
 
self = <test.test_calculator.TddInPythonExample testMethod=test_calculator_add_method_returns_correct_result>
 
    def test_calculator_add_method_returns_correct_result(self):
        result = self.calc.add(3, 2)
> self.assertEqual(4, result)
E AssertionError: 4 != 5
 
test/test_calculator.py:11: AssertionError
—————————————————————- Captured stdout call ——————————————————————
X value is: 3
Y value is: 2
Result is 5
========================================================= 1 failed, 3 passed in 0.03 seconds ==========================================================

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

1
2
if __name__ == ‘__main__’:
   unittest.main()

Выполните тест, используя python calculator_tests.py . Вот результат, который вы можете ожидать:

1
2
3
4
5
6
$ python test/test_calculator.py
….
———————————————————————-
Ran 4 tests in 0.004s
 
OK

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

Будут случаи, когда, когда ваши тесты не пройдут, не сразу понятно, почему это происходит

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

Если вы намеренно измените наш код калькулятора так, чтобы он не работал, вы можете получить представление о том, как отладка вашего кода будет работать. Измените код в методе add app/calculator.py чтобы фактически вычесть два значения.

1
2
3
4
5
6
7
8
class Calculator(object):
   def add(self, x, y):
       number_types = (int, long, float, complex)
 
       if isinstance(x, number_types) and isinstance(y, number_types):
           return x — y
       else:
           raise ValueError

Когда вы сейчас запускаете тесты, тест, который проверяет, что ваш метод add корректно возвращает четыре, при добавлении два плюс два дает сбой, так как теперь он возвращает 0. Чтобы проверить, как он приходит к такому выводу, вы можете добавить несколько операторов print, чтобы проверить, что он правильно получает два значения и затем проверяет вывод. Это приведет вас к выводу, что логика сложения двух чисел неверна. Добавьте следующие операторы печати в код в app/calculator.py .

01
02
03
04
05
06
07
08
09
10
11
12
class Calculator(object):
   def add(self, x, y):
       number_types = (int, long, float, complex)
 
       if isinstance(x, number_types) and isinstance(y, number_types):
           print ‘X is: {}’.format(x)
           print ‘Y is: {}’.format(y)
           result = x — y
           print ‘Result is: {}’.format(result)
           return result
       else:
           raise ValueError

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
$ nosetests test/test_calculator.py
F…
======================================================================
FAIL: test_calculator_add_method_returns_correct_result (test.test_calculator.TddInPythonExample)
———————————————————————-
Traceback (most recent call last):
  File «/Users/user/PycharmProjects/tdd_in_python/test/test_calculator.py», line 11, in test_calculator_add_method_returns_correct_result
    self.assertEqual(4, result)
AssertionError: 4 != 0
——————— >> begin captured stdout << ———————
X is: 2
Y is: 2
Result is: 0
 
——————— >> end captured stdout << ———————-
 
———————————————————————-
Ran 4 tests in 0.002s
 
FAILED (failures=1)

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

Одним из наиболее часто используемых инструментов является pdb (или Python Debugger). Инструмент включен в стандартную библиотеку и просто требует добавления одной строки, где вы хотели бы остановить выполнение программы и войти в pdb , обычно называемый «точкой останова». Используя наш ошибочный код в методе add, попробуйте добавить следующую строку, прежде чем вычтены два значения.

1
2
3
4
5
6
7
8
9
class Calculator(object):
   def add(self, x, y):
       number_types = (int, long, float, complex)
 
       if isinstance(x, number_types) and isinstance(y, number_types):
           import pdb;
           return x — y
       else:
           raise ValueError

Если для выполнения теста используется nosetest с nosetest обязательно nosetest его, используя флаг -s который указывает на то, что nosetest на nosetest не должен захватывать стандартный вывод, иначе ваш тест просто зависнет и не выдаст приглашение pdb . Использование стандартного unittest и pytest не требует такого шага.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
$ nosetests -s
> /Users/user/PycharmProjects/tdd_in_python/app/calculator.py(7)add()
-> return x — y
(Pdb) list
  2 def add(self, x, y):
  3 number_types = (int, long, float, complex)
  4
  5 if isinstance(x, number_types) and isinstance(y, number_types):
  6 import pdb;
  7 -> return x — y
  8 else:
  9 raise ValueError
[EOF]
(Pdb)

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

1
2
3
4
(Pdb) x
2
(Pdb) y
2

Вы можете продолжать «играть» с кодом, поскольку вам нужно выяснить, что не так. Вы можете в любой момент набрать help чтобы получить список команд, но основной набор, который вам, вероятно, понадобится:

  • n : шаг вперед к следующей строке исполнения.
  • list : показать пять строк по обе стороны от того места, где вы сейчас выполняете, чтобы увидеть код, связанный с текущей точкой выполнения.
  • args : список переменных, участвующих в текущей точке выполнения.
  • continue : выполнить код до конца.
  • jump <line number> : запускать код до указанного номера строки.
  • exit / exit : остановка pdb .

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

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

Сделайте TDD частью вашего ежедневного рабочего процесса сегодня.

Если эта статья разожгла ваш аппетит к миру тестирования в Python, почему бы не проверить книгу « Тестирование Python », написанную автором статей и выпущенную недавно на Amazon и других хороших ритейлерах. Посетите эту страницу, чтобы приобрести свою копию книги сегодня и поддержать одного из своих участников Tuts +.

Изучите Python с нашим полным руководством по питону, независимо от того, начинаете ли вы или начинающий программист, ищущий новые навыки.