BDD: Behaviour driven development

Preview:

DESCRIPTION

Aborda conceitos básicos do BDD.Palestra apresentada na quarta edição do Liberdade Interativa, no dia 08 de dezembro de 2010, em Vitória no Espírito Santo.

Citation preview

Francisco Souza

http://www.games-workshop.com/MEDIA_CustomProductCatalog/m1241904_99060105229_StormtrooperSergpowerswordmain_445x319.jpg

francisco@franciscosouza.net franciscosouza.com.br

BDD: Behaviour-driven development

Uma introdução ao desenvolvimento guiado por comportamento

what the f**rancisco?!?!

● Giran Soluções e Ensino● Associação Python Brasil● Apaixonado por Python● Viciado em coding dojo● PMP

what the f**rancisco?!?!

● Giran Soluções e Ensino● Associação Python Brasil● Apaixonado por Python● Viciado em coding dojo● PMP

Professional Mario Player

Como desenvolvemos software?

http://www.flickr.com/photos/bibendum84/4721132699/

http://www.flickr.com/photos/3336/142845984/

Especificação

http://www.flickr.com/photos/drbethsnow/2194409454/

http://www.flickr.com/photos/drbethsnow/2194409454/

http://www.flickr.com/photos/enebish/2498232255/

Design

http://www.flickr.com/photos/drbethsnow/2194409454/

Especificação

http://www.flickr.com/photos/peterhellberg/4625578444/

http://www.flickr.com/photos/chernobylbob/4976837748/

Mas é tudo papel! o__O'

Design

http://1.bp.blogspot.com/_xuZyFxSS-UI/TLhIng0YnsI/AAAAAAAAH6g/dqcytiNO8Pc/s1600/image001111.jpg

http://test.ical.ly/wp-content/uploads/2010/03/tdd_cycle.jpg

TDDTest-driven development

http://test.ical.ly/wp-content/uploads/2010/03/tdd_cycle.jpg

TDDTest-driven development

http://3.bp.blogspot.com/_00az4KUgbFE/TGCEQ9pZmZI/AAAAAAAAAO8/cGXlQplTSbM/s1600/minesweeper_game_fail_windows_epic.jpg

Especificação

EspecificaçãoExecutável

class TestEnquetes(mocker.MockerTestCase):

def test_quantidade_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

class TestEnquetes(mocker.MockerTestCase):

def test_quantidade_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

http://www.flickr.com/photos/samnewman/201939659/

class TestEnquetes(mocker.MockerTestCase):

def test_quantidade_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

http://1.bp.blogspot.com/_36x37e5S95A/TE-v6kK1CAI/AAAAAAAABEI/eq-YbU9XbTg/s1600/jack_t_ripper.jpg

Vamos por partes...

class TestEnquetes(mocker.MockerTestCase):

def test_quantidade_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Usuário logado...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Usuário logado...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Enquete cadastrada...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Enquete cadastrada...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Opção cadastrada...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() self.e_que_existe_uma_opcao_cadastrada()

votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Opção cadastrada...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() self.e_que_existe_uma_opcao_cadastrada()

votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

Usuário vota na opção...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() self.e_que_existe_uma_opcao_cadastrada()

self.quando_ele_vota_na_opcao()

assert enquete.opcoes[2].votos == votos_desejados

Usuário vota na opção...

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() self.e_que_existe_uma_opcao_cadastrada()

self.quando_ele_vota_na_opcao()

assert enquete.opcoes[2].votos == votos_desejados

Deve ter um voto a mais

class TestEnquetes(mocker.MockerTestCase):

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado()

self.e_que_existe_uma_enquete_cadastrada() self.e_que_existe_uma_opcao_cadastrada()

self.quando_ele_vota_na_opcao()

self.entao_a_opcao_deve_ter_um_voto_a_mais()

Deve ter um voto a mais

class TestEnquetes(mocker.MockerTestCase):

def test_quantidade_votos(self): login_mock = self.mocker.mock(Login) login_mock.checa_logado(mocker.ARGS) self.mocker.result(True) self.mocker.replay() enquete = Enquete.objects.get_by_pk(1) votos_desejados = enquete.opcoes[2].votos + 1 votador = Votador() votador.vota(enquete, 2) assert enquete.opcoes[2].votos == votos_desejados

class TestEnquetes(mocker.MockerTestCase):

# outros métodos

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado() self.e_que_existe_uma_enquete_cadastrada()

self.e_que_existe_uma_opcao_cadastrada() self.quando_ele_vota_na_opcao()

self.entao_a_opcao_deve_ter_um_voto_a_mais()

Entrada

Processamento

Saída

Dado

Então

Quando

class TestEnquetes(mocker.MockerTestCase):

# outros métodos

def test_deve_incrementar_quantidade_de_votos(self): self.dado_que_existe_um_usuario_logado() self.e_que_existe_uma_enquete_cadastrada()

self.e_que_existe_uma_opcao_cadastrada() self.quando_ele_vota_na_opcao()

self.entao_a_opcao_deve_ter_um_voto_a_mais()

Dado que existe um usuário logado

E que existe uma enquete cadastrada

E que existe uma opção cadastrada

Quando o usuário vota nesta opção

Então a opção deve ter um voto a mais

http://www.flickr.com/photos/striatic/2145725302/

http://queroabracaromundo.files.wordpress.com/2009/12/o-contador-de-historias.jpg

Um pouco de história...

http://www.flickr.com/photos/scoop/1403808340/

http://www.flickr.com/photos/drics/3989109318/

Conceituando

História/Funcionalidade

http://www.stellman-greene.com/blog/wp-content/uploads/2009/05/search-and-replace-user-story-card.png

História/Funcionalidade

http://www.stellman-greene.com/blog/wp-content/uploads/2009/05/search-and-replace-user-story-card.png

Especificação?

http://www.flickr.com/photos/dhammza/132440085/

Cenários

Dado Given

Quando When

Então Then

Dado que existe um usuário logado

E que existe uma enquete cadastrada

E que existe uma opção cadastrada

Quando o usuário vota nesta opção

Então a opção deve ter um voto a mais

http://eggsonbread.com/wp-content/uploads/2009/07/bdd.png

Outside-in development

E no dia a dia?

Quero esse cadastro de

enquetes aí! :D

Tá sussa! :D

http://www.flickr.com/photos/bre/552152780/

JBehavecuke4duke

CucumberRSpec

RBehave

LettuceFreshenspecloud should-dsl

http://www.flickr.com/photos/ateliervanessamaurer/3177029046/

Gherkin Syntax

Feature: Manipulate strings In order to have some fun As a programming beginner I want to manipulate strings

Scenario: Uppercased strings Given I have the string "lettuce leaves" When I put it in upper case Then I see the string is "LETTUCE LEAVES"

http://lettuce.it

http://www.flickr.com/photos/pfv/2889794588/

Unbelievable!

Inacreditável!

Unglaublich!

http://eggsonbread.com/wp-content/uploads/2009/07/bdd.png

Outside-in development

http://slidesha.re/9Us7HL

ATDD

http://www.flickr.com/photos/quinnanya/4221482856/

Obrigado!

@franciscosouza

francisco@franciscosouza.net

franciscosouza.com

franciscosouza.com.brDúvida

s? :)