Видео смотреть бесплатно

Смотреть аниме видео

Официальный сайт interaktiveboard 24/7/365

Смотреть видео бесплатно

12.12.10 12:14 RANUX

Python — Урок 1.1 TDD для начинающих на Python

Представляю вашему вниманию первую часть первого урока посвящённую разработке через тестирование. Надеюсь будет полезно:) Старался написать максимально простым языком:) Комментарии приветствуются.

Добро пожаловать на серию уроков по Test Driven Development. Для тех кто ещё не знает что такое TDD: Разрабо́тка че́рез тести́рование (англ. test-driven development) — техника программирования, при которой модульные тесты для программы или её фрагмента пишутся до самой программы и, по существу, управляют её разработкой. Основная идея - реализовать правильно работающий функционал, обеспечить возможность повторного использования и простого изменения структуры исходного кода, при этом не изменяя его поведения (рефакторинг)

Давайте в начале рассмотрим из каких
шагов состоит TDD:
  1. Красный. Подготавливаем файл с тестом,
    создаём не работающий тест
  2. Зелёный. Заставляем тест сработать
  3. Рефакторинг Удаляем дублирование
Помимо этих основных шагов я применяю в начале нулевой шаг - «исследование и хакинг» в случае, когда я с трудом представляю, как мне пройти последующие 3-и шага. Давайте пройдёмся по этим шагам на примере реализации простой задачи, например вычисления факториала.

Исследование и хакинг. Что нам известно о
факториале?


Давайте разберём пример:
n! = 1 * 2 * 3 * … * n
0! = 1 1! = 1 2! = 2 3! = 6 4! = 24 и так далее

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

  • Функции

  • Условные операторы

  • Аргументы функции

  • Рекурсия

Запускаем консоль и заходим в python.

>>> 2 * 3
6
  • Умножение

  • Функции

  • Условные операторы

  • Аргументы функции

  • Рекурсия

С умножением всё ясно. Теперь попробуем написать какую-нибудь простую функцию:

1
2
3
4
5
6

>>> def f():
...   print "hello"
...
>>> f()
hello


Отлично, наша функция отработала. Не забываем про отступы в функциях, те перед print "hello" у меня стоят два пробела.
Посмотрим как функция будет возвращать наше значение:


1
2
3
4
5
>>> def f():
...   return "hello"
...
>>> f()
'hello'


С этим разобрались.
  • Умножение

  • Функции

  • Условные операторы

  • Аргументы функции

  • Рекурсия

Теперь посмотрим как работают условные операторы и аргументы функции:

1
2
3
4
5
6
7
8
9
10
>>> def f(flag):
...   if flag:
...     return True
...   else:
...     return False
...
>>> f(1)
True
>>> f(0)
False


Если наш флаг присутствует, то возвращаем True, в противном случае False.
  • Умножение

  • Функции

  • Условные операторы

  • Аргументы функции

  • Рекурсия

Что же такое рекурсия. Рекурсия — это функция вызывающая сама себя. Давайте разберёмся:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> def f(n):
...   if n == 0:
...     return 0
...   else:
...     print "n: %s" % n
...     return f(n-1)
...
>>> f(5)
n: 5
n: 4
n: 3
n: 2
n: 1
0


В месте return f(n-1) функция будет вызывать сама себя, но n при этом будет уменьшаться на единицу. Конструкция print "n: %s" % n
вставляет n в строку и форматирует его как строковое значение.
  • Умножение

  • Функции

  • Условные операторы

  • Аргументы функции

  • Рекурсия

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

Снова составим список того, что нам надо
сделать:
  • Эксперимент с doctest

  • Вычисление факториала

Созадём файл factor.py содержащий:

1
2
3
4
5
6
#!/usr/bin/python
# -*- coding: UTF-8 -*-

if __name__ == '__main__':
  pass
 


Попробуйте его запустить из консоли: python
factor.py
Отлично, пока что у нас нечего не выводиться, но файл выполнился.

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

Смотрим пример:
1
2
3
4
5
6
7
8
9
10
11
12
def f(a, b):
  '''
  Функция складывает два числа
  >>> f(1,2)
  3
  '
''
  pass

if __name__ == '__main__':
  import doctest
  doctest.testmod()
  pass


Оператор pass означает, что делать нечего не надо. Попробуем запустить: python factor.py

В результате видим:
**********************************************************************
File "factor.py", line 11, in __main__.f
Failed example:
f(1,2)
Expected:
3
Got nothing
**********************************************************************
1 items had failures:
1 of 1 in __main__.f
***Test Failed*** 1 failures.

Отлично, мы проделали первый шаг TDD - «Красный». Приступим к зелёному .

1
2
3
4
5
6
7
8
def f(a, b):
  '''
  Функция складывает два числа
  >>> f(1,2)
  3
  '
''
  return 1 + 2
 


Запускаем и видим, что наша функция прошла тест, второй шаг «Зелёный» вроде пройден, но что если мы попробуем вызвать
f(2, 3). Изменим функцию и посмотрим результат:

1
2
3
4
5
6
7
8
9
def f(a, b):
  '''
  Функция складывает два числа
  >>> f(1,2)
  3
  >>> f(2,3)
  5
  '
''
  return 1 + 2


Запускаем python factor.py
**********************************************************************
File "factor.py", line 13, in __main__.f
Failed example:
f(2,3)
Expected:
5
Got:
3
**********************************************************************
1 items had failures:
1 of 2 in __main__.f
***Test Failed*** 1 failures

Что и следовало ожидать, мы хотим 2 + 3 = 5, но получили 3. Теперь у нас достаточно тестов чтобы реализовать нашу функцию. Приступим:

1
2
3
4
5
6
7
8
9
def f(a, b):
  '''
  Функция складывает два числа
  >>> f(1,2)
  3
  >>> f(2,3)
  5
  '
''
  return a + b



Запускаем python factor.py и видим, что тесты прошли. Отлично. Мы написали первую функию в рамках TDD и разобрались с doctest-ом.

На этом я заканчиваю первую часть первого урока. Во второй части разберёмся как реализовать функцию вычисления
факториала.
  • Эксперимент с doctest

  • Вычисление факториала

Домашнее задание


Напишите функцию разницы. Тест для функции:
1
2
3
4
5
6
7
8
9
10
11
def minus(a, b):
  '''
  Функция разницы
  >>> f(4,2)
  2
  >>> f(2,4)
  -2
  >>> f(10,3)
  7
  '
''
  pass

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



wiz 12.12.10 12:26 # +3
имхо лучше не встраивать всю эту дребедень в __main__, а пользоваться правильными аргументами: python -m doctest factor.py

потмоу что тесты приходят и уходят, а код остаётся.
RANUX 12.12.10 12:49 # +1
В следующем уроке учтём :)
wiz 12.12.10 12:29 # +2
вместо pass и подобных загушек рекомендую использовать честные raise NotImplementedError

также, многие редакторы подсвечивают строки типа TODO и FIXME
wiz 12.12.10 12:30 # +0
Жду продолжения, своими идеями поделюсь когда будут затрагиваться более продвинутые аспекты.
ZogG 12.12.10 17:17 # +2
спасибо, плюсанул, но...
если пост ссылка, то зачем копировать всё?
и если уж скопировал, то кат всеравно раньше ставь.
RANUX 12.12.10 17:19 # +0
Всё. Разобрался. Спасибо)) Я просто не сразу понял, что за кат))
knyazeff 12.12.10 17:26 # +0
Есть мнение, что пока еще не разобрался :-)
knyazeff 12.12.10 17:27 # +0
Умолкаю...
RANUX 12.12.10 17:34 # +0
Учимся потихоньку)
ZogG 12.12.10 17:30 # +0
вот так отлично, я бы даже перед самим катом добавил бы:
«продолжение внутри» или «кто заинтересовался, продолжение под катом»
RANUX 12.12.10 17:33 # +0
Вроде и так можно нажать на "Подробнее" )
RANUX 12.12.10 17:34 # +0
Точнее "Полностью"))
Elvis 12.12.10 18:13 # +4
Похоже что все вышеописанное - это часть стандартной документации unittest.
Дело в том, что полным новичкам не нужно TDD, а более продвинутые уже все это и так знают.

Я бы посоветовал вам написать:
- про mock библиотеки
- про nosetest, как запускать его с django
- про инструменты BDD
- про интеграцию code coverage с nosetest
- рассказать о том, какин нужно писать тесты, а какие не нужно (антипаттерны).

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

exelens 12.12.10 18:28 # +1
Я бы посоветовал вам написать:

про что мог сам бы написать?
Elvis 12.12.10 19:27 # +3
В ближайшие три недели - ни про что, на днях уезжаю в жаркие страны...
А так, могу написать про питон, джангу, много чего, если в теме будет заинтересовано сообщество.
Sylar 12.12.10 20:34 # +0
Пиши конечно.
ЗЫ: Удачного отдыха :)
RANUX 12.12.10 19:20 # +0
В прошлом посте http://welinux.ru/post/4684/ я попытался привести пример более сложного способа тестирования. Но была просьба начать с вещей по проще. В TDD главное понять основу. Всю методику я не расскажу для этого есть соответствующие книги того же Кента Бэка, но вот своим опытом я пытаюсь поделиться:))
wiz 12.12.10 23:24 # +2
Новичкам надо сразу давать программирование, как инженерную дисциплину, а то в последнее время народ начал такой говнокод, что индусы плачут, его читая.

К слову, мы у себя в конторе прям сразу же с первого же занятия ввели TDD. И знаете, нормально восприняли, благо что в питоне с этим всё нормально - и доктесты, и юнит и всё что хочешь. И при этом не надо ничего перекомпиливать.

Так.. О чём это я? А!.. Ну, собственно, я тоже хотел всё это посоветовать, но видимо, у RANUX уже есть какая-то программа в плане, так что ждём новых постов и там уже обсудим.

А вообще конечно было бы неплохо сварганить "новый курс молодого бойца", осветив в нём всё, что не преподают в институтах, и с чем начинающий програмер сталкивается на предприятиях.
kstep 13.12.10 03:02 # +0
Да, TDD и прочими юнит-тестами такая беда: если их с самого начала не начать юзать, то потом чем больше кода, тем сложнее его ввести =(
wiz 13.12.10 12:01 # +0
тем сложнее его ввести

в моск
RANUX 13.12.10 07:28 # +0
Я тоже всегда хотел работать в конторе где TDD и Python, но пока-что приходиться рыться в системах с быдлокодом:( В общем, удовольствия от быдлокодерских систем не испытываю, скорее одно сплошное раздражение, а покрывать тестами и рефакторить в одиночку желания нет.
Так.. О чём это я? А!.. Ну, собственно, я тоже хотел всё это посоветовать, но видимо, у RANUX уже есть какая-то программа в плане, так что ждём новых постов и там уже обсудим.

Идей полно, вот только времени не всегда хватает, но в любом случае продолжение будет:)
Minoru 14.12.10 05:25 # +0
А вообще конечно было бы неплохо сварганить "новый курс молодого бойца", осветив в нём всё, что не преподают в институтах, и с чем начинающий програмер сталкивается на предприятиях.
Я бы такой пост с удовольствием почитал, даже если бы это был просто список ссылок на актуальные подходы, алгоритмы, книги и прочее.
knyazeff 12.12.10 21:03 # +1
Мужики! Я прошу прощения за оффтопик, а может кто-нибудь написать про программирование под андроид, полагаю, это по теме ресурса.
Вот только не про то, как поставить эклипс и прикрутить к нему андроид SDK и плагины, а реально работающую программу разобрать.
Вот это было бы нереально круто!
kmarks 13.12.10 10:34 # +0
Возьми сам и напиши. Не думаю что очень сложно.
kmarks 13.12.10 13:51 # +1
Спасибо за статью! Всё выполнил.
Задание по факториалу сделал, но почему-то не удалось выполнить полную проверку на натуральность числа. Подробности на pastie.org

В следующей части, пожалуйста, не забудьте снова напомнить про все шаги TTD (а то вылетит из головы как что и зачем) и научить пользоваться аргументами, переданными из командной строки:
fact.py -n 5 //так вроде по POSIX правильно
Sylar 14.12.10 01:25 # +1
Ты, наверное, хотел
if n >= 0 and n % 1 == 0


По аргументам -- доки по argparse, getopt.
Вот тут еще человек скрипт выкладывал с опциями.
kmarks 14.12.10 12:48 # +0
Точно, n % 1 == 0
А я что-то тупанул, хотя смысл операции остатка от деления понял как надо.
Спасибо.

Посты Комментарии
Последние посты
    Посты Комментарии
    Последние комментарии
      Посты Комментарии
      Изменения
        Посты Комментарии Изменения Черновики Избранное
        Черновики (все)
          Посты Комментарии Изменения Черновики Избранное
          Избранное (всё)
            Посты Комментарии Изменения Черновики Избранное
            Лучшие блоги (все 165)
            Топ пользователей Топ блогов
            Топ пользователей Топ блогов
            Элита (все 3376 из 238 городов)
            Топ пользователей Топ блогов
            welinux.ru

            Смотреть онлайн бесплатно

            Онлайн видео бесплатно


            Смотреть русское с разговорами видео

            Online video HD

            Видео скачать на телефон

            Русские фильмы бесплатно

            Full HD video online

            Смотреть видео онлайн

            Смотреть HD видео бесплатно

            School смотреть онлайн