Tdd Com Mock e Orientação a Objetos (PyNE 2015)

Post on 23-Jul-2015

90 views 2 download

Transcript of Tdd Com Mock e Orientação a Objetos (PyNE 2015)

PyNE 2015TDD com Mock e Orientação a Objetos

Bernardo FontesNatal/RN

16 de Maio de 2015

Só para dizer um oi!twitter.com/bbfontesgithub.com/berinhard

garimpo.fmpessoas.cc

bernardoxhc@gmail.com

github.com/berinhard/talks

Obrigado, Turicas!

Obrigado, Turicas!

RoteiroBásicos de Orientação aObjetosTest-driven Development(TDD)TDD Com MocksDúvidas

Básicos de Orientação aObjetos

Não é fazer getter e setter

Orientação aObjetos?

Estratégia de DesignDefinição de EstadoEncapsulamentoColaboração com troca deMensagens

S.O.L.I.D.

Exemplo Pythonfrom datetime import date

class Ticket(object):

def __init__(self, buyer, price, schedule_date): self.buyer = buyer self.price = price self.schedule_date = schedule_date

def has_expired(self): return date.today() > self.schedule_date

#############################

ticket = Ticket("Bernardo", 10, date(2015, 10, 10))if not ticket.has_expired(): #processa ticket válido

Referências

Test-driven Development (TDD)

Primeiro o testeclass Ticket(TestCase):

def test_3_returns_fizz(self): self.assertEqual("fizz", fizz(3))

Primeira implementaçãodef foo(number): return "fizz"

class Ticket(TestCase):

def test_3_returns_fizz(self): self.assertEqual("fizz", fizz(3))

Coding Dojo!!!

Processo de Design

Design EmergenteRefatoraçãoRemoção de AcoplamentosDuplicidade

Exploração e Descobertacansativo...

Sem Evidência do Designclass TestTicketManager(TestCase):

def test_expire_ticket(self): ticket = Ticket.objects.create(id=30) self.assertFalse(ticket.expired)

manager = TicketManager() manager.expire_ticket(ticket_id=30)

ticket = Ticket.objects.get(id=30) self.assertTrue(ticket.expired)

Difícil de começar a testar noalto nível

Infra vs Domínio

Referências

Curso TDD - J. B. Rainsberger

TDD com Mock

MockSimulam funcionamento de objetosRespeitam API dos objetosViabilizam maneira de fazer asserções

Foco do Domíno nasMensagens

Menos Estado e mais Colaboração

Implementação de Testes Top-Down

Need-Driven DevelopmentCódigo criado só se necessário

TODO ListRecuperar IngressoExpirá-loNotificar Usuário

Entry Pointclass TestTicketManager(TestCase):

def test_expire_ticket(self): manager = TicketManager() manager.expire_ticket(ticket_id=30)

Recuperar Ingressofrom mock import Mock

class TestTicketManager(TestCase):

def test_expire_ticket(self): tickets_repository = Mock(TicketsRepository) tickets_repository.get_by_id.return_value = Ticket()

manager = TicketManager(tickets_repository) manager.expire_ticket(ticket_id=30)

tickets_repository.get_by_id.assert_called_once_with(30)

class TicketManager(object):

def __init__(self, tickets_repository): self.repository = tickets_repository

def expire_ticket(self, ticket_id): self.repository.get_by_id(ticket_id)

class Ticket(object): pass

class TicketsRepository(object):

def get_by_id(self, id): "Must return a Ticket object" pass

Expirar Ingressofrom mock import Mock

class TestTicketManager(TestCase):

def test_expire_ticket(self): ticket = Mock(Ticket) tickets_repository = Mock(TicketsRepository) tickets_repository.get_by_id.return_value = ticket

manager = TicketManager(tickets_repository) manager.expire_ticket(ticket_id=30)

tickets_repository.get_by_id.assert_called_once_with(30) ticket.expire.assert_called_once_with()

class TicketManager(object):

def __init__(self, tickets_repository): self.repository = tickets_repository

def expire_ticket(self, ticket_id): ticket = self.repository.get_by_id(ticket_id) ticket.expire()

class Ticket(object):

def expire(self): pass

class TicketsRepository(object):

def get_by_id(self, id): "Must return a Ticket object"

Notificar Usuáriofrom mock import Mock

class TestTicketManager(TestCase):

def test_expire_ticket(self): ticket = Mock(Ticket) tickets_repository = Mock(TicketsRepository) tickets_repository.get_by_id.return_value = ticket notificator = Mock(TicketNotificator)

manager = TicketManager(tickets_repository, notificator) manager.expire_ticket(ticket_id=30)

tickets_repository.get_by_id.assert_called_once_with(30) ticket.expire.assert_called_once_with() notificator.notify_expired.assert_called_once_with(ticket)

class TicketManager(object):

def __init__(self, tickets_repository, notificator): self.repository = tickets_repository self.notificator = notificator

def expire_ticket(self, ticket_id): ticket = self.repository.get_by_id(ticket_id) ticket.expire() self.notificator.notify_expired(ticket)

class Ticket(object):

def expire(self): pass

class TicketsRepository(object):

Respeito ao contrato é tudoComportamentos de EntradaComportamentos de Saída

Novos testes para garantircontrato e funcionamentounitário dos componentes

Referências

Mock Roles, not Objects

Dúvidas?

Obrigado!Bernardo Fontes

twitter.com/bbfontesgithub.com/berinhard

garimpo.fmpessoas.cc

bernardoxhc@gmail.com