BDD IN Python 

Behaviour-Driven Development и все-все-все.

XP

Extreme Programming

  • Повышение качества ПО
  • Частые релизы
  • Требования меняются
  • Циклы разработки

TDD

Test-Driven Development

  • Возник из XP
  • Короткий цикл разработки:
    • Написание тестов
    • Написание кода
    • Рефакторинг кода
  • Быстрая локализаци я ошибок
  • Меньше размер - проще понять

TDD

Возникающие вопросы

  • С чего начать?
  • Что тестировать?
  • Каков объем тестов?
  • Как называть тесты?
  • Из-за чего произошла ошибка? 

TDD

Не все так просто.

BDD

Behavior-Driven Development

"BDD is a second-generation, outside-in, 
pull-based, multiple-stakeholder, 
multiple-scale, high automation, 
agile methodology".

Dan North   

BDD

История
  • 2004 - начата работа над JBehave
  • 2006 - выходит статья "Introducing  BDD"
  • 2007 - создается RBehave, RSpec.
  • 2009 - выходит первая версия Cucumber.

BDD

Цикл разработки

  1. Анализ User Story
  2. Расстановка приоритетов
  3. Обсуждение и рефакторинг
  4. Написание кода
  5. Рефакторинг кода
  6. ?????????
  7. PROFIT!!!

BDD

Суровая реальность

  • BDD != замена TDD
  • Сценарии не заменяют тестов
  • Сценарии должны легко читаться
  • Придется общаться с людьми :-(

BDD

Ubiquitous Language
http://martinfowler.com/bliki/UbiquitousLanguage.html

  • Язык описания, общий для всех
  • Четкое определение сущностей
  • Отсутствие "размытых" описаний

BDD

Gherkin


BDD

Gherkin

  • Язык описания
    поведения системы
  • "Функции" (Feature)
  • "Сценарии" (Scenario)
  • "Шаги" (Given, When, Then)

BDD

Пример сценария на Gherkin

Функция: срабатывание флага уведомления

    Сценарий: трейдер уведомляется о превышении
        Дано акции и порог равен 15.0
        Когда стоимость акций равна 6
        То уведомление в состоянии "ВЫКЛ"
        Когда стоимость акций равна 16
        То уведомление в состоянии "ВКЛ"

BDD

Lettuce
http://lettuce.it/

  • Сравнительно точный порт Cucumber
  • Произвольная структура тестов
  • Общее состояние для всех функций
  • Нестабильная работа

BDD

Freshen
https://github.com/rlisagor/freshen

  • Различные контексты выполнения
  • Интеграция с nose
  • Интеграция с nose
  • Нет контекстных обработчиков
    для разных уровней исполнения

BDD

Cucumber
http://cukes.info

  • Хорошо встраивается в
    существующий процесс
    с RSpec и Cucumber
  • Написано на Ruby
    (Ruby? In my Python?!)

BDD

behave
http://pythonhosted.org/behave/

  • Гибкая настройка
  • Никакой магии с импортами
  • Удобная документация
  • Поддержка тегов (tags)

BDD

PyVows
http://heynemann.github.io/pyvows/

  • Асинхронное выполнение тестов
  • Сценарий описывается в коде
  • Трудночитаемый синтаксис

HOME READING

 

ВОПРОСЫ?


Борисов Кирилл
БАРС Груп
Архитектор ПО

twitter: @lensvol
skype: kirbars
borisov@bars-open.ru



BEHAVE

Запускаем "behave  --lang  ru"...
  Функция: срабатывание флага уведомления # notify.feature:1

  Сценарий: трейдер уведомляется о превышении  # notify.feature:3
    Дано акции и порог равен 15.0 
    Когда стоимость акций равна 6              
    То уведомление в состоянии "ВЫКЛ"          
    Когда стоимость акций равна 16             
    То уведомление в состоянии "ВКЛ"
    
Failing scenarios:
  notify.feature:3  трейдер уведомляется о превышении

0 features passed, 1 failed, 0 skipped
0 scenarios passed, 1 failed, 0 skipped
0 steps passed, 0 failed, 0 skipped, 5 undefined
Took 0m0.000s
    

BEHAVE

Обработчики шагов (steps/steps.py)
#coding: utf-8
from behave import *

@given(u'акции и порог равен 15.0')
def step_impl(context):
    assert False
    
@when(u'стоимость акций равна 6')
def step_impl(context):
    assert False

@then(u'уведомление в состоянии "ВЫКЛ"')
def step_impl(context):
    assert False

    
... tl;dr

BEHAVE

Реализация шагов
#coding: utf-8

from behave import *

@given(u'акции и порог равен {threshold}')
def step_impl(context, threshold):
    context.threshold = float(threshold)
    context.notify = False

@when(u'стоимость акций равна {price}')
def step_impl(context, price):
    if float(price) > context.threshold:
        context.notify = True
    else:
        context.notify = False

@then(u'уведомление в состоянии "{status}"')
def step_impl(context, status):
    assert status in [u"ВКЛ", u"ВЫКЛ"]
    assert context.notify == (status == u"ВКЛ")
    

BEHAVE

Повторный прогон...
  Функция: срабатывание флага уведомления # notify.feature:1

  Сценарий: трейдер уведомляется о превышении  # notify.feature:3
    Дано акции и порог равен 15.0
    Когда стоимость акций равна 6              
    То уведомление в состоянии "ВЫКЛ"          
    Когда стоимость акций равна 16             
    То уведомление в состоянии "ВКЛ"

1 feature passed, 0 failed, 0 skipped
1 scenario passed, 0 failed, 0 skipped
5 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m0.000s
PROFIT!!!
Made with Slides.com