SlideShare a Scribd company logo
Test Doubles
Rubén Bernárdez
 www.rubenbp.com
   @rubenbpv
    #aos2011
¿Por qué usamos dobles?
El colaborador:
class Communicator():

    def send_email(self, address, total_savings):
        suponemos_que_esto_envia_un_email = True



El SUT (System Under Test):
class SavingsService():

    def __init__(self, communicator):
        self.communicator = communicator

    def analyze_month(self, month_savings):
        calculation = month_savings[0] + month_savings[1]
        self.communicator.send_email('savings@iexpertos.com', calculation)
Pruébalo cobarde! … pecador!...
class Communicator():

    def send_email(self, address, total_savings):
        suponemos_que_esto_envia_un_email = True

class SavingsService():

    def __init__(self, communicator):
        self.communicator = communicator

    def analyze_month(self, month_savings):
        calculation = month_savings[0] + month_savings[1]
        self.communicator.send_email('savings@iexpertos.com', calculation)

class LoFlipoEnEl_AOS(unittest.TestCase):
    def test_report_correcto_es_enviado_a_la_central(self):
        communicator = spy(Communicator())
        month_savings = [1234,1276435]
        service = SavingsService(communicator)

        service.analyze_month(month_savings)
        assert_that(communicator.send_email).was_called()
¿Mock o Spy?
class LoFlipoEnEl_AOS(unittest.TestCase):
    def test_al_menos_es_enviado_a_la_central(self):
        communicator = spy(Communicator())
        month_savings = [1234,1276435]
        service = SavingsService(communicator)

       service.analyze_month(month_savings)

       assert_that(communicator.send_email).was_called()

   def test_se_envia_a_la_central_y_nada_mais(self):
       communicator = mock(Communicator())
       expect_call(communicator.send_email)
       month_savings = [1234,1276435]
       service = SavingsService(communicator)

       service.analyze_month(month_savings)

       communicator.assert_that_is_satisfied()
¿Qué test se romperá?
class Communicator():

    def send_email(self, address, total_savings):
        suponemos_que_esto_envia_un_email = True

    def post_savings(self, total_savings):
        suponemos_que_esto_llama_a_un_webservice = True

class SavingsService():

    def __init__(self, communicator):
        self.communicator = communicator

    def analyze_month(self, month_savings):
        calculation = month_savings[0] + month_savings[1]
        self.communicator.send_email('savings@iexpertos.com', calculation)
        self.communicator.post_savings(calculation)
Un diseño distinto...                 ¿Ahora qué hacemos?

class Communicator():

    def send_email(self, address, total_savings):
        suponemos_que_esto_envia_un_email = True

class AccountRepository():
    def month_savings(self):
        suponemos_que_esto_devuelve_de_bd_los_ahorros = True

class SavingsService():

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

    def analyze_month(self):
        month_savings = self.repository.month_savings()
        calculation = month_savings[0] + month_savings[1]
        self.communicator.send_email('savings@iexpertos.com', calculation)
Mejor Stub que Spy esta vez! fistro!
class SavingsService():

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

    def analyze_month(self):
        month_savings = self.repository.month_savings()
        calculation = month_savings[0] + month_savings[1]
        self.communicator.send_email('savings@iexpertos.com', calculation)


class LoFlipoEnEl_AOS(unittest.TestCase):
    def test_si_hay_report_envialo_a_la_central(self):
        communicator = spy(Communicator())
        repository = stub(AccountRepository())
        when(repository.month_savings).then_return([1234,1276435])
        service = SavingsService(communicator, repository)

        service.analyze_month(month_savings)

        assert_that(communicator.send_email).was_called()
Tests frágiles VS legibilidad
    Classic VS Mockist
Test doubles frameworks
   ¿Qué más comportamientos se pueden
    programar en los dobles de test? Con qué
    frameworks?
                pyDoubles
                Mockito
                Jmock
                Moq
                Rhino.Mocks
                PHPUnit
                GoogleMock
pyDoubles.org
        Made with TDD and open source!




   when(obj.method).with_args(1).then_return(1000)
   when(obj.method).then_raise(ApplicationException())
   when(obj.method).then_return(1000)
   expect_call(obj.method).with_args(1)
   expect_call(obj.method).with_args(1, ANY_ARG)
   assert_that(obj.method).was_called().with_args(1)
   when(obj.method).with_args(
              str_containing(”abc”)).then_return(1)


                                  Powered by...
iExpertos.com
   Formación para equipos de desarrollo:
       Iniciación a TDD y TDD Avanzado
       eXtreme Programming a fondo (XP)
       Coaching

   Desarrollamos contigo:
       Dos iExpertos en tu empresa desde el arranque
        del proyecto.
       Formación y desarrollo, todo en uno.

More Related Content

Similar to Test Doubles - stubs, spies & mocks

Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patterns
Tomasz Kowal
 
Python Magic Methods: a practical example
Python Magic Methods: a practical examplePython Magic Methods: a practical example
Python Magic Methods: a practical example
Nacho Gentile
 
Introduction to coding using Python
Introduction to coding using PythonIntroduction to coding using Python
Introduction to coding using Python
Dan D'Urso
 
Micropatterns
MicropatternsMicropatterns
Micropatterns
cameronp
 
Odoo from 7.0 to 8.0 API
Odoo from 7.0 to 8.0 APIOdoo from 7.0 to 8.0 API
Odoo from 7.0 to 8.0 API
Mustufa Rangwala
 
Odoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new apiOdoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new api
Odoo
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in Python
Subhash Bhushan
 
Kaggle KDD Cup Report
Kaggle KDD Cup ReportKaggle KDD Cup Report
Kaggle KDD Cup Report
Chamila Wijayarathna
 
Lecture 8.pdf
Lecture 8.pdfLecture 8.pdf
Lecture 8.pdf
HiHi398889
 
Empower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo MixinsEmpower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo Mixins
Odoo
 
Monads in python
Monads in pythonMonads in python
Monads in python
eldariof
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
Kerry Buckley
 
Python classes objects
Python classes objectsPython classes objects
Testing in Django
Testing in DjangoTesting in Django
Testing in Django
Kevin Harvey
 
PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2
Graham Dumpleton
 
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Codemotion
 
Tip Top Typing - A Look at Python Typing
Tip Top Typing - A Look at Python TypingTip Top Typing - A Look at Python Typing
Tip Top Typing - A Look at Python Typing
Patrick Viafore
 
Class 26: Objectifying Objects
Class 26: Objectifying ObjectsClass 26: Objectifying Objects
Class 26: Objectifying Objects
David Evans
 
Python advance
Python advancePython advance
Python advance
Deepak Chandella
 
Python programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphismPython programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphism
Emertxe Information Technologies Pvt Ltd
 

Similar to Test Doubles - stubs, spies & mocks (20)

Very basic functional design patterns
Very basic functional design patternsVery basic functional design patterns
Very basic functional design patterns
 
Python Magic Methods: a practical example
Python Magic Methods: a practical examplePython Magic Methods: a practical example
Python Magic Methods: a practical example
 
Introduction to coding using Python
Introduction to coding using PythonIntroduction to coding using Python
Introduction to coding using Python
 
Micropatterns
MicropatternsMicropatterns
Micropatterns
 
Odoo from 7.0 to 8.0 API
Odoo from 7.0 to 8.0 APIOdoo from 7.0 to 8.0 API
Odoo from 7.0 to 8.0 API
 
Odoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new apiOdoo - From v7 to v8: the new api
Odoo - From v7 to v8: the new api
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in Python
 
Kaggle KDD Cup Report
Kaggle KDD Cup ReportKaggle KDD Cup Report
Kaggle KDD Cup Report
 
Lecture 8.pdf
Lecture 8.pdfLecture 8.pdf
Lecture 8.pdf
 
Empower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo MixinsEmpower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo Mixins
 
Monads in python
Monads in pythonMonads in python
Monads in python
 
Tdd for BT E2E test community
Tdd for BT E2E test communityTdd for BT E2E test community
Tdd for BT E2E test community
 
Python classes objects
Python classes objectsPython classes objects
Python classes objects
 
Testing in Django
Testing in DjangoTesting in Django
Testing in Django
 
PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2PyCon US 2012 - State of WSGI 2
PyCon US 2012 - State of WSGI 2
 
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
Joe Bew - Apprendi un nuovo linguaggio sfruttando il TDD e il Clean Code - Co...
 
Tip Top Typing - A Look at Python Typing
Tip Top Typing - A Look at Python TypingTip Top Typing - A Look at Python Typing
Tip Top Typing - A Look at Python Typing
 
Class 26: Objectifying Objects
Class 26: Objectifying ObjectsClass 26: Objectifying Objects
Class 26: Objectifying Objects
 
Python advance
Python advancePython advance
Python advance
 
Python programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphismPython programming : Inheritance and polymorphism
Python programming : Inheritance and polymorphism
 

Recently uploaded

20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
Adtran
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
Zilliz
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
Neo4j
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
kumardaparthi1024
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
IndexBug
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
Matthew Sinclair
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 

Recently uploaded (20)

20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
Pushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 daysPushing the limits of ePRTC: 100ns holdover for 100 days
Pushing the limits of ePRTC: 100ns holdover for 100 days
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Full-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalizationFull-RAG: A modern architecture for hyper-personalization
Full-RAG: A modern architecture for hyper-personalization
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
GenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizationsGenAI Pilot Implementation in the organizations
GenAI Pilot Implementation in the organizations
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
 
20240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 202420240609 QFM020 Irresponsible AI Reading List May 2024
20240609 QFM020 Irresponsible AI Reading List May 2024
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 

Test Doubles - stubs, spies & mocks

  • 1. Test Doubles Rubén Bernárdez www.rubenbp.com @rubenbpv #aos2011
  • 2. ¿Por qué usamos dobles? El colaborador: class Communicator(): def send_email(self, address, total_savings): suponemos_que_esto_envia_un_email = True El SUT (System Under Test): class SavingsService(): def __init__(self, communicator): self.communicator = communicator def analyze_month(self, month_savings): calculation = month_savings[0] + month_savings[1] self.communicator.send_email('savings@iexpertos.com', calculation)
  • 3. Pruébalo cobarde! … pecador!... class Communicator(): def send_email(self, address, total_savings): suponemos_que_esto_envia_un_email = True class SavingsService(): def __init__(self, communicator): self.communicator = communicator def analyze_month(self, month_savings): calculation = month_savings[0] + month_savings[1] self.communicator.send_email('savings@iexpertos.com', calculation) class LoFlipoEnEl_AOS(unittest.TestCase): def test_report_correcto_es_enviado_a_la_central(self): communicator = spy(Communicator()) month_savings = [1234,1276435] service = SavingsService(communicator) service.analyze_month(month_savings) assert_that(communicator.send_email).was_called()
  • 4. ¿Mock o Spy? class LoFlipoEnEl_AOS(unittest.TestCase): def test_al_menos_es_enviado_a_la_central(self): communicator = spy(Communicator()) month_savings = [1234,1276435] service = SavingsService(communicator) service.analyze_month(month_savings) assert_that(communicator.send_email).was_called() def test_se_envia_a_la_central_y_nada_mais(self): communicator = mock(Communicator()) expect_call(communicator.send_email) month_savings = [1234,1276435] service = SavingsService(communicator) service.analyze_month(month_savings) communicator.assert_that_is_satisfied()
  • 5. ¿Qué test se romperá? class Communicator(): def send_email(self, address, total_savings): suponemos_que_esto_envia_un_email = True def post_savings(self, total_savings): suponemos_que_esto_llama_a_un_webservice = True class SavingsService(): def __init__(self, communicator): self.communicator = communicator def analyze_month(self, month_savings): calculation = month_savings[0] + month_savings[1] self.communicator.send_email('savings@iexpertos.com', calculation) self.communicator.post_savings(calculation)
  • 6. Un diseño distinto... ¿Ahora qué hacemos? class Communicator(): def send_email(self, address, total_savings): suponemos_que_esto_envia_un_email = True class AccountRepository(): def month_savings(self): suponemos_que_esto_devuelve_de_bd_los_ahorros = True class SavingsService(): def __init__(self, communicator, repository): self.communicator = communicator self.repository = repository def analyze_month(self): month_savings = self.repository.month_savings() calculation = month_savings[0] + month_savings[1] self.communicator.send_email('savings@iexpertos.com', calculation)
  • 7. Mejor Stub que Spy esta vez! fistro! class SavingsService(): def __init__(self, communicator, repository): self.communicator = communicator self.repository = repository def analyze_month(self): month_savings = self.repository.month_savings() calculation = month_savings[0] + month_savings[1] self.communicator.send_email('savings@iexpertos.com', calculation) class LoFlipoEnEl_AOS(unittest.TestCase): def test_si_hay_report_envialo_a_la_central(self): communicator = spy(Communicator()) repository = stub(AccountRepository()) when(repository.month_savings).then_return([1234,1276435]) service = SavingsService(communicator, repository) service.analyze_month(month_savings) assert_that(communicator.send_email).was_called()
  • 8. Tests frágiles VS legibilidad Classic VS Mockist
  • 9. Test doubles frameworks  ¿Qué más comportamientos se pueden programar en los dobles de test? Con qué frameworks?  pyDoubles  Mockito  Jmock  Moq  Rhino.Mocks  PHPUnit  GoogleMock
  • 10. pyDoubles.org Made with TDD and open source!  when(obj.method).with_args(1).then_return(1000)  when(obj.method).then_raise(ApplicationException())  when(obj.method).then_return(1000)  expect_call(obj.method).with_args(1)  expect_call(obj.method).with_args(1, ANY_ARG)  assert_that(obj.method).was_called().with_args(1)  when(obj.method).with_args( str_containing(”abc”)).then_return(1) Powered by...
  • 11. iExpertos.com  Formación para equipos de desarrollo:  Iniciación a TDD y TDD Avanzado  eXtreme Programming a fondo (XP)  Coaching  Desarrollamos contigo:  Dos iExpertos en tu empresa desde el arranque del proyecto.  Formación y desarrollo, todo en uno.