SlideShare ist ein Scribd-Unternehmen logo
1 von 36
Downloaden Sie, um offline zu lesen
TDD
или как я стараюсь писать код

Владимир Филонов
labbler.com
Теория TDD
“Разработка через тестирование (англ. test-driven
  development, TDD) — техника разработки
  программного обеспечения, которая основывается
  на повторении очень коротких циклов разработки:
  сначала пишется тест, покрывающий желаемое
  изменение, затем пишется код, который позволит
  пройти тест, и под конец проводится рефакторинг
  нового кода к соответствующим стандартам.” ©
  Wikipedia.org
Тесты



Рефакто-
                   Код
  ринг
Зачем все это?
Говорят, что TDD помогает
•  Улучшить качество кода
•  Уменьшить количество ошибок и багов
•  Ускорить разработку
В чем сила, брат?
В чем разница?


           Тесты                    Код


Рефакто-                                  Рефакто-
  ринг             Код      Тесты           ринг
IMHO
Вектор мышления
Сначала код:
•  Разработчик концентрируется на отдельных частях
   кода больше чем на общем дизайне
•  К моменту написания тестов разработчик уже
   устает
•  Тесты пишутся уже с учетом особенностей
   реализации, в том числе и костылей, если таковые
   присутствуют
class OneFieldForm(forms.Form):
   value = forms.IntegerField()

class SimpleView(View):
   def get(self, *args, **kwargs):
     form = OneFieldForm()
        return render_template(form)
   def post(self, *args, **kwargs):
     form = OneFieldForm(self.request.POST)
     if form.is_valid():
        #Какой-то сложный, утомительный код, который
        #использует значение из формы
        return render_to_response(“success.html")
     else:
         return render_template(form)
   def render_template(self, form):
     context = { "form": form,}
     return render_to_response("template.html", context)
class SimpleViewTestCase(TestCase):

    def test_simple_view(self):
      response = self.client.get(”/”)
      self.assertEqual(response.tempates[0].name, “template.html ")

      response2 = self.client.post(”/”)
      self.assertEqual(response2.tempates[0].name, “template.html")

      response3 = self.client.post(”/”, {“count”: 1})
      self.assertEqual(response3.tempates[0].name, “success.html")

.
Ситуации

class OneFieldForm(forms.Form):
   value = forms.CharField()




if “value” in self.request.POST and 
                             self.request.POST[“value”]:
TDD
•  При написании тестов, мы не отвлекаемся на
   детали реализации
•  Более чёткое и целостное представление о
   дизайне кода
•  Выше скорость написания кода
•  Хорошего кода ;)
•  Меньше рефакторинга
Смена исполнителя
•  Проще понять, что уже сделано, а что еще нет –
   достаточно запустить тесты
•  Тесты как документация – проще разобраться в уже
   написанном коде
•  Более отчуждаемый код
Человечные интерфейсы
•  Сразу смотрим на задачу с позиции пользователя
   интерфейсов
•  Не делаем допущений, основанных на знании
   деталей реализации
•  Ниже порог вхождения, меньше подводных камней
•  Более отчуждаемый код
Мотивация
Обычное течение разработки
•  Начало. Уровень мотивации высокий, все рвутся в
   бой
•  Понеслась
  –  Имплементация
  –  Передача в QA
  –  Баги
  –  Дебагинг
  –  Мотивация = - 1* Баги
TDD
•  Тесты пишутся на первой волне энтузиазма
•  Для написания кода после тестов появляются
   дополнительные стимулы:
  –  Четко поставленная цель: пройти все тесты
  –  Каждый пройденный тест – достижение
  –  Это поддерживает положительный настрой
•  Стимулы для написания тестов после кода




  –  Требуется очень хорошая самоорганизация
  –  Формальных требований может быть недостаточно для
     написания хороших тестов
Acceptance TDD
•  Пишем приёмочные тесты и ставим задачи
   команде
•  Приёмочные тесты – тесты верхнего уровня
   абстракции
•  Сами пишем тесты на невалидные входные данные
•  Кто, кроме нас? :)

•  Сам я ещё не пробовал, но очень хочу
Как писать тесты до
       кода?
•  От абстракций верхнего уровня - к абстракциям нижних
   –  Глобальные вещи (views) -> API, DAO -> утилитарные методы
•  Проще показать на примере
Сделаем виртуальную библиотеку.
Книга - название, автор, ISBN
Читатель
Чтобы получить билет, надо зарегистрироваться. Для простоты, в
качестве номера будем использовать django.contrib.auth.models.User.id
Читатели могут брать/сдавать книги, но не более 2х одновременно.
Если книгу кто-то взял, то другому ее не получить.
Брать книги можно по:
•  1. Название+Автор
•  2. ISBN
#Книги: title, author, year, isbn
#
#Капитал, Кащей Б.С., 942 г., 1234-5678-9
#100 диетических блюд из репы, Прекрасная В., 1142 г.,
#                                         4321-8765-9
#Ковка подков, Гефест, 2675 г. до н.э. 9876-5432-1
#Бустâн, Абу Мухаммад Муслих ад-Дин ибн Абд Аллах Саади
#                          Ширази, 1257 г., 6789-2345-1

class LibraryViewsTestCase(TestCase):

    def setUp(self):
        self.ivan = User.objects.get(username="ivan")
        self.maria = User.objects.get(username="maria")
        self.books = INITIAL_BOOKS_LIST

    def test_library_urls(self):
        self.assertEqual(reverse("library:take"), "/take/")
        self.assertEqual(reverse("library:return"), "/return/")
def test_get_book_view__unauth(self):
    """
    Книжки можно раздавать только авторизованным пользователям
    """

   response = self.client.post("/take/", {"isbn": "1234-5678-9"})
   self.assertEqual(response.status_code, 301)

   self.client.login(username="ivan", password="durak")
   response = self.client.post("/take/", {"isbn": "1234-5678-9"})
   self.assertEqual(response.status_code, 200)
def test_get_book_view__isbn(self):
       """
       Наберем книжек по ISBN
       """
       self.client.login(username="ivan", password="pozhaluista")

       #Возьмем книгу
       response = self.client.post("/take/", {"isbn": "1234-5678-9"})
       self.assertEqual(response.status_code, 200)
       self.assertIn("book", response.context)
       self.assertEqual(response.context["book"]["title"], u"Капитал")
       self.assertEqual(response.templates[0].name, "take_success.html")
       self.assertEqual(get_user_books_count(self.ivan), 1)
       self.assertIn(self.books[0], get_user_books(self.ivan))

       #Еще одну
       self.client.post("/take/", {"isbn": "9876-5432-1"})
       self.assertEqual(get_user_books_count(self.ivan), 2)
       self.assertIn(self.books[0], get_user_books(self.ivan))
       self.assertIn(self.books[2], get_user_books(self.ivan))
#Поробуем третью
failed_response = self.client.post("/take/", {"isbn": "6789-2345-1"})
self.assertIn("book", response.context)
self.assertEqual(response.context["book"]["title"], u"Бустâн")
self.assertEqual(response.templates[0].name, "take_failed.html")
self.assertIn("error", response.context)
self.assertEqual(response.context["error"], u"Хватит уже")

self.assertEqual(get_user_books_count(self.ivan), 2)
self.assertIn(self.books[0], get_user_books(self.ivan))
self.assertIn(self.books[2], get_user_books(self.ivan))
def test_get_book_view__title_and_author(self):
    """
    Берем книги по заголовку и автору
    """

def test_get_book_view__taken(self):
    """
    Попробуем взять книгу, которую уже унес кто-то
    """

def test_get_book_view__again(self):
    """
    Попробуем взять одну и ту же книгу дважды
    """

def test_get_book_view__unknown(self):
     """
     Попробуем взять книгу, которой нет в библиотеке
     """
#...
#Возврат книги, возврат не взятой книги,
#возврат книги не из библиотеки
Полученные тесты можно
 использовать для ATDD
class LibriatyDaoTestCase(TestCase):
    """
    Следующий уровень - функции, которые нам понадобятся,
    чтобы решить ситуации, описанные выше
    """
    def test_get_book_by_isbn(self):
        """
        Получаем их базы книгу по isbn
        """

   def test_get_book_by_title_and_author(self):
       """
       Получаем из базы книгу по isbn
       """

   def test_user_has_book(self):
       """
       Есть ли эта книга у читателя
       """
def test_get_user_books(self):
    """
    Все книги которые есть у читателя
    """

def test_get_user_books_count(self):
    """
    Сколько книг у читателя
    """

def test_book_is_owned(self):
    """
    Взяли ли кто-то эту книгу
    """
Та-дааа!
Эпилог
•  Более продуманный дизайн кода к моменту начала
   реализации
•  Как следствие - более чистый код
•  Возможно, более быстрая реализация
•  Лучшее покрытие тестами (как по качеству, так и по
   количеству)
•  Дополнительный источник мотивации в процессе
•  Более отчуждаемый код
•  Меньше багов, а значит и меньше итераций «QA-
   багфиксинг»
Спасибо!
          И…
Немного саморекламы =)
https://labbler.com
mailto: vladimir@labbler.com
Спасибо!

Weitere ähnliche Inhalte

Was ist angesagt?

Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptTimur Shemsedinov
 
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...Badoo Development
 
NoSql. Фокус на тестирование
NoSql. Фокус на тестированиеNoSql. Фокус на тестирование
NoSql. Фокус на тестированиеUladzimir Kryvenka
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Alex Ott
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.Igor Shkulipa
 
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Andrey Rebrov
 
Особенности тестирования NoSql приложений
Особенности тестирования NoSql приложенийОсобенности тестирования NoSql приложений
Особенности тестирования NoSql приложенийUladzimir Kryvenka
 
Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)
Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)
Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)Ontico
 
Изоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесьИзоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесьCodeFest
 
MongoDB. Фокус на тестирование
MongoDB. Фокус на тестированиеMongoDB. Фокус на тестирование
MongoDB. Фокус на тестированиеUladzimir Kryvenka
 
Быстро о быстром
Быстро о быстромБыстро о быстром
Быстро о быстромRoman Dvornov
 
Basis.js – «под капотом»
Basis.js – «под капотом»Basis.js – «под капотом»
Basis.js – «под капотом»Roman Dvornov
 
DOM-шаблонизаторы – не только "быстро"
DOM-шаблонизаторы – не только "быстро"DOM-шаблонизаторы – не только "быстро"
DOM-шаблонизаторы – не только "быстро"Roman Dvornov
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb SpockBohdan Danyliuk
 
Инструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важныИнструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важныRoman Dvornov
 
Automation Functional Testing in Agile Projects
Automation Functional Testing in Agile ProjectsAutomation Functional Testing in Agile Projects
Automation Functional Testing in Agile ProjectsAndrey Rebrov
 
SPA инструменты
SPA инструментыSPA инструменты
SPA инструментыRoman Dvornov
 
JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.Igor Shkulipa
 
Производительность и надежность Docsvision 5
Производительность и надежность Docsvision 5Производительность и надежность Docsvision 5
Производительность и надежность Docsvision 5Docsvision
 

Was ist angesagt? (20)

Class queries
Class queriesClass queries
Class queries
 
Метапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScriptМетапрограммирование с примерами на JavaScript
Метапрограммирование с примерами на JavaScript
 
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
Доклад Сергея Аверина на DevConf 2013. "Распространенные ошибки применения ба...
 
NoSql. Фокус на тестирование
NoSql. Фокус на тестированиеNoSql. Фокус на тестирование
NoSql. Фокус на тестирование
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)
 
JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.JavaScript Базовый. Занятие 07.
JavaScript Базовый. Занятие 07.
 
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
Автоматизируйте это немедленно или коллекция инструментов автотестирования с ...
 
Особенности тестирования NoSql приложений
Особенности тестирования NoSql приложенийОсобенности тестирования NoSql приложений
Особенности тестирования NoSql приложений
 
Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)
Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)
Функциональное тестирование высоконагруженных проектов / Илья Пастушков (2ГИС)
 
Изоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесьИзоморфный JavaScript — будущее уже здесь
Изоморфный JavaScript — будущее уже здесь
 
MongoDB. Фокус на тестирование
MongoDB. Фокус на тестированиеMongoDB. Фокус на тестирование
MongoDB. Фокус на тестирование
 
Быстро о быстром
Быстро о быстромБыстро о быстром
Быстро о быстром
 
Basis.js – «под капотом»
Basis.js – «под капотом»Basis.js – «под капотом»
Basis.js – «под капотом»
 
DOM-шаблонизаторы – не только "быстро"
DOM-шаблонизаторы – не только "быстро"DOM-шаблонизаторы – не только "быстро"
DOM-шаблонизаторы – не только "быстро"
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock
 
Инструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важныИнструменты разные нужны, инструменты разные важны
Инструменты разные нужны, инструменты разные важны
 
Automation Functional Testing in Agile Projects
Automation Functional Testing in Agile ProjectsAutomation Functional Testing in Agile Projects
Automation Functional Testing in Agile Projects
 
SPA инструменты
SPA инструментыSPA инструменты
SPA инструменты
 
JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.JavaScript Базовый. Занятие 11.
JavaScript Базовый. Занятие 11.
 
Производительность и надежность Docsvision 5
Производительность и надежность Docsvision 5Производительность и надежность Docsvision 5
Производительность и надежность Docsvision 5
 

Ähnlich wie TDD или как я стараюсь писать код

TDD или как я стараюсь писать код
TDD или как я стараюсь писать кодTDD или как я стараюсь писать код
TDD или как я стараюсь писать кодVladimir Filonov
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Python Meetup
 
Повышение качества тестов и автоматическая валидация REST API документации
Повышение качества тестов и автоматическая валидация REST API документацииПовышение качества тестов и автоматическая валидация REST API документации
Повышение качества тестов и автоматическая валидация REST API документацииCEE-SEC(R)
 
«DevOps — это о передаче смысла» — Александр Титов, Express 42
«DevOps — это о передаче смысла» — Александр Титов, Express 42«DevOps — это о передаче смысла» — Александр Титов, Express 42
«DevOps — это о передаче смысла» — Александр Титов, Express 42DevDay
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.Roman Brovko
 
Михаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionМихаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionAlbina Tiupa
 
М. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionМ. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionAlbina Tiupa
 
HSE{Consult}: DevOps – новая методология разработки
HSE{Consult}: DevOps – новая методология разработкиHSE{Consult}: DevOps – новая методология разработки
HSE{Consult}: DevOps – новая методология разработкиBusiness incubator HSE
 
DevOps или исскуство ухода за Интернет-проектом
DevOps или исскуство ухода за Интернет-проектомDevOps или исскуство ухода за Интернет-проектом
DevOps или исскуство ухода за Интернет-проектомAlexander Titov
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полнойОмские ИТ-субботники
 
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNgДело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNgIT61
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Ontico
 
TestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщикаTestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщикаdavertmik
 
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...Ontico
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорьdrupalconf
 

Ähnlich wie TDD или как я стараюсь писать код (20)

TDD или как я стараюсь писать код
TDD или как я стараюсь писать кодTDD или как я стараюсь писать код
TDD или как я стараюсь писать код
 
Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"Максим Щепелин. "Unittesting. Как?"
Максим Щепелин. "Unittesting. Как?"
 
BDD
BDDBDD
BDD
 
Повышение качества тестов и автоматическая валидация REST API документации
Повышение качества тестов и автоматическая валидация REST API документацииПовышение качества тестов и автоматическая валидация REST API документации
Повышение качества тестов и автоматическая валидация REST API документации
 
«DevOps — это о передаче смысла» — Александр Титов, Express 42
«DevOps — это о передаче смысла» — Александр Титов, Express 42«DevOps — это о передаче смысла» — Александр Титов, Express 42
«DevOps — это о передаче смысла» — Александр Титов, Express 42
 
Лекция 11. Тестирование.
Лекция 11. Тестирование.Лекция 11. Тестирование.
Лекция 11. Тестирование.
 
Михаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionМихаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с Codeception
 
М. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionМ. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с Codeception
 
HSE{Consult}: DevOps – новая методология разработки
HSE{Consult}: DevOps – новая методология разработкиHSE{Consult}: DevOps – новая методология разработки
HSE{Consult}: DevOps – новая методология разработки
 
DevOps или исскуство ухода за Интернет-проектом
DevOps или исскуство ухода за Интернет-проектомDevOps или исскуство ухода за Интернет-проектом
DevOps или исскуство ухода за Интернет-проектом
 
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
2014-10-04 02 Владислав Безверхий. Mocha - покрой frontend по полной
 
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNgДело тестера боится: как в опытных руках могут заиграть Java и TestNg
Дело тестера боится: как в опытных руках могут заиграть Java и TestNg
 
UI+unit testing in iOS
UI+unit testing in iOSUI+unit testing in iOS
UI+unit testing in iOS
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)Язык программирования Scala / Владимир Успенский (TCS Bank)
Язык программирования Scala / Владимир Успенский (TCS Bank)
 
TestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщикаTestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщика
 
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
TDD: когда нужно и, самое главное, когда не нужно / Павел Калашников (SimbirS...
 
PowerShell
PowerShellPowerShell
PowerShell
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
 
Codeception Introduction
Codeception IntroductionCodeception Introduction
Codeception Introduction
 
Tdd php
Tdd phpTdd php
Tdd php
 

Mehr von MoscowDjango

Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Пример fuzzy testing для поиска URL в тексте
Пример fuzzy testing для поиска URL в текстеПример fuzzy testing для поиска URL в тексте
Пример fuzzy testing для поиска URL в текстеMoscowDjango
 
Cyclone + Eventsource (realtime push-сообщения)
Cyclone + Eventsource (realtime push-сообщения)Cyclone + Eventsource (realtime push-сообщения)
Cyclone + Eventsource (realtime push-сообщения)MoscowDjango
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в DjangoMoscowDjango
 
Django на Android
Django на AndroidDjango на Android
Django на AndroidMoscowDjango
 
Работа со статикой в Django
Работа со статикой в DjangoРабота со статикой в Django
Работа со статикой в DjangoMoscowDjango
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoMoscowDjango
 
Class Based Generic Views в Django
Class Based Generic Views в DjangoClass Based Generic Views в Django
Class Based Generic Views в DjangoMoscowDjango
 
Простой и удобный деплоймент проекта
Простой и удобный деплоймент проектаПростой и удобный деплоймент проекта
Простой и удобный деплоймент проектаMoscowDjango
 
Django South. Миграция баз данных.
Django South. Миграция баз данных.  Django South. Миграция баз данных.
Django South. Миграция баз данных. MoscowDjango
 
Журнальная вёрстка в Django
Журнальная вёрстка в DjangoЖурнальная вёрстка в Django
Журнальная вёрстка в DjangoMoscowDjango
 

Mehr von MoscowDjango (11)

Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Пример fuzzy testing для поиска URL в тексте
Пример fuzzy testing для поиска URL в текстеПример fuzzy testing для поиска URL в тексте
Пример fuzzy testing для поиска URL в тексте
 
Cyclone + Eventsource (realtime push-сообщения)
Cyclone + Eventsource (realtime push-сообщения)Cyclone + Eventsource (realtime push-сообщения)
Cyclone + Eventsource (realtime push-сообщения)
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 
Django на Android
Django на AndroidDjango на Android
Django на Android
 
Работа со статикой в Django
Работа со статикой в DjangoРабота со статикой в Django
Работа со статикой в Django
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на Django
 
Class Based Generic Views в Django
Class Based Generic Views в DjangoClass Based Generic Views в Django
Class Based Generic Views в Django
 
Простой и удобный деплоймент проекта
Простой и удобный деплоймент проектаПростой и удобный деплоймент проекта
Простой и удобный деплоймент проекта
 
Django South. Миграция баз данных.
Django South. Миграция баз данных.  Django South. Миграция баз данных.
Django South. Миграция баз данных.
 
Журнальная вёрстка в Django
Журнальная вёрстка в DjangoЖурнальная вёрстка в Django
Журнальная вёрстка в Django
 

TDD или как я стараюсь писать код

  • 1. TDD или как я стараюсь писать код Владимир Филонов labbler.com
  • 2. Теория TDD “Разработка через тестирование (англ. test-driven development, TDD) — техника разработки программного обеспечения, которая основывается на повторении очень коротких циклов разработки: сначала пишется тест, покрывающий желаемое изменение, затем пишется код, который позволит пройти тест, и под конец проводится рефакторинг нового кода к соответствующим стандартам.” © Wikipedia.org
  • 3. Тесты Рефакто- Код ринг
  • 4. Зачем все это? Говорят, что TDD помогает •  Улучшить качество кода •  Уменьшить количество ошибок и багов •  Ускорить разработку
  • 6. В чем разница? Тесты Код Рефакто- Рефакто- ринг Код Тесты ринг
  • 8. Вектор мышления Сначала код: •  Разработчик концентрируется на отдельных частях кода больше чем на общем дизайне •  К моменту написания тестов разработчик уже устает •  Тесты пишутся уже с учетом особенностей реализации, в том числе и костылей, если таковые присутствуют
  • 9. class OneFieldForm(forms.Form): value = forms.IntegerField() class SimpleView(View): def get(self, *args, **kwargs): form = OneFieldForm() return render_template(form) def post(self, *args, **kwargs): form = OneFieldForm(self.request.POST) if form.is_valid(): #Какой-то сложный, утомительный код, который #использует значение из формы return render_to_response(“success.html") else: return render_template(form) def render_template(self, form): context = { "form": form,} return render_to_response("template.html", context)
  • 10. class SimpleViewTestCase(TestCase): def test_simple_view(self): response = self.client.get(”/”) self.assertEqual(response.tempates[0].name, “template.html ") response2 = self.client.post(”/”) self.assertEqual(response2.tempates[0].name, “template.html") response3 = self.client.post(”/”, {“count”: 1}) self.assertEqual(response3.tempates[0].name, “success.html") .
  • 11. Ситуации class OneFieldForm(forms.Form): value = forms.CharField() if “value” in self.request.POST and self.request.POST[“value”]:
  • 12. TDD •  При написании тестов, мы не отвлекаемся на детали реализации •  Более чёткое и целостное представление о дизайне кода •  Выше скорость написания кода •  Хорошего кода ;) •  Меньше рефакторинга
  • 13. Смена исполнителя •  Проще понять, что уже сделано, а что еще нет – достаточно запустить тесты •  Тесты как документация – проще разобраться в уже написанном коде •  Более отчуждаемый код
  • 14. Человечные интерфейсы •  Сразу смотрим на задачу с позиции пользователя интерфейсов •  Не делаем допущений, основанных на знании деталей реализации •  Ниже порог вхождения, меньше подводных камней •  Более отчуждаемый код
  • 16. Обычное течение разработки •  Начало. Уровень мотивации высокий, все рвутся в бой •  Понеслась –  Имплементация –  Передача в QA –  Баги –  Дебагинг –  Мотивация = - 1* Баги
  • 17. TDD •  Тесты пишутся на первой волне энтузиазма •  Для написания кода после тестов появляются дополнительные стимулы: –  Четко поставленная цель: пройти все тесты –  Каждый пройденный тест – достижение –  Это поддерживает положительный настрой
  • 18. •  Стимулы для написания тестов после кода –  Требуется очень хорошая самоорганизация –  Формальных требований может быть недостаточно для написания хороших тестов
  • 20. •  Пишем приёмочные тесты и ставим задачи команде •  Приёмочные тесты – тесты верхнего уровня абстракции •  Сами пишем тесты на невалидные входные данные •  Кто, кроме нас? :) •  Сам я ещё не пробовал, но очень хочу
  • 22. •  От абстракций верхнего уровня - к абстракциям нижних –  Глобальные вещи (views) -> API, DAO -> утилитарные методы •  Проще показать на примере Сделаем виртуальную библиотеку. Книга - название, автор, ISBN Читатель Чтобы получить билет, надо зарегистрироваться. Для простоты, в качестве номера будем использовать django.contrib.auth.models.User.id Читатели могут брать/сдавать книги, но не более 2х одновременно. Если книгу кто-то взял, то другому ее не получить. Брать книги можно по: •  1. Название+Автор •  2. ISBN
  • 23. #Книги: title, author, year, isbn # #Капитал, Кащей Б.С., 942 г., 1234-5678-9 #100 диетических блюд из репы, Прекрасная В., 1142 г., # 4321-8765-9 #Ковка подков, Гефест, 2675 г. до н.э. 9876-5432-1 #Бустâн, Абу Мухаммад Муслих ад-Дин ибн Абд Аллах Саади # Ширази, 1257 г., 6789-2345-1 class LibraryViewsTestCase(TestCase): def setUp(self): self.ivan = User.objects.get(username="ivan") self.maria = User.objects.get(username="maria") self.books = INITIAL_BOOKS_LIST def test_library_urls(self): self.assertEqual(reverse("library:take"), "/take/") self.assertEqual(reverse("library:return"), "/return/")
  • 24. def test_get_book_view__unauth(self): """ Книжки можно раздавать только авторизованным пользователям """ response = self.client.post("/take/", {"isbn": "1234-5678-9"}) self.assertEqual(response.status_code, 301) self.client.login(username="ivan", password="durak") response = self.client.post("/take/", {"isbn": "1234-5678-9"}) self.assertEqual(response.status_code, 200)
  • 25. def test_get_book_view__isbn(self): """ Наберем книжек по ISBN """ self.client.login(username="ivan", password="pozhaluista") #Возьмем книгу response = self.client.post("/take/", {"isbn": "1234-5678-9"}) self.assertEqual(response.status_code, 200) self.assertIn("book", response.context) self.assertEqual(response.context["book"]["title"], u"Капитал") self.assertEqual(response.templates[0].name, "take_success.html") self.assertEqual(get_user_books_count(self.ivan), 1) self.assertIn(self.books[0], get_user_books(self.ivan)) #Еще одну self.client.post("/take/", {"isbn": "9876-5432-1"}) self.assertEqual(get_user_books_count(self.ivan), 2) self.assertIn(self.books[0], get_user_books(self.ivan)) self.assertIn(self.books[2], get_user_books(self.ivan))
  • 26. #Поробуем третью failed_response = self.client.post("/take/", {"isbn": "6789-2345-1"}) self.assertIn("book", response.context) self.assertEqual(response.context["book"]["title"], u"Бустâн") self.assertEqual(response.templates[0].name, "take_failed.html") self.assertIn("error", response.context) self.assertEqual(response.context["error"], u"Хватит уже") self.assertEqual(get_user_books_count(self.ivan), 2) self.assertIn(self.books[0], get_user_books(self.ivan)) self.assertIn(self.books[2], get_user_books(self.ivan))
  • 27. def test_get_book_view__title_and_author(self): """ Берем книги по заголовку и автору """ def test_get_book_view__taken(self): """ Попробуем взять книгу, которую уже унес кто-то """ def test_get_book_view__again(self): """ Попробуем взять одну и ту же книгу дважды """ def test_get_book_view__unknown(self): """ Попробуем взять книгу, которой нет в библиотеке """ #... #Возврат книги, возврат не взятой книги, #возврат книги не из библиотеки
  • 28. Полученные тесты можно использовать для ATDD
  • 29. class LibriatyDaoTestCase(TestCase): """ Следующий уровень - функции, которые нам понадобятся, чтобы решить ситуации, описанные выше """ def test_get_book_by_isbn(self): """ Получаем их базы книгу по isbn """ def test_get_book_by_title_and_author(self): """ Получаем из базы книгу по isbn """ def test_user_has_book(self): """ Есть ли эта книга у читателя """
  • 30. def test_get_user_books(self): """ Все книги которые есть у читателя """ def test_get_user_books_count(self): """ Сколько книг у читателя """ def test_book_is_owned(self): """ Взяли ли кто-то эту книгу """
  • 33. •  Более продуманный дизайн кода к моменту начала реализации •  Как следствие - более чистый код •  Возможно, более быстрая реализация •  Лучшее покрытие тестами (как по качеству, так и по количеству) •  Дополнительный источник мотивации в процессе •  Более отчуждаемый код •  Меньше багов, а значит и меньше итераций «QA- багфиксинг»
  • 34. Спасибо! И… Немного саморекламы =)