DeSymfonyDay 2014 - To mock or not to mock - Spanish

Post on 13-Dec-2014

210 views 0 download

description

 

Transcript of DeSymfonyDay 2014 - To mock or not to mock - Spanish

¿Quiénes somos?

Eloi Poch Jordi Llonch

Agenda• ¿Qué hacemos en Akamon?

• To test or not to test?

• ¿Cómo hacemos test?

• Librerías de mock.

• Conclusiones y consejos.

• Osiris:

• Nueva plataforma de servicios de Akamon.

• Principios:

• Simplicidad sobre facilidad.

¿Qué hacemos?

Calidad

Funcionalidad Velocidad

Domain

Con

tract

Infrastructure

Domain (Business Logic)

Con

tract

Infrastructure

Domain (Business Logic)

Applications

Background

Website

APIsAPIsAPIs

Arquitecturaby Akamon

APIs

DBs

Con

tract

External Services

Infrastructure

Domain (Business Logic)

Calidad

• Pull Request • Pair Programming • Test

by Akamon

To test or not to test?

Todo e

l mund

o

hace t

ests

To test or not to test

Los buenos test ahorran DINERO en cualquier aplicación

To test or not to test

Testear es controvertido

• David Heinemeier (creador de Ruby on Rails y Fundador y CTO de Basecamp)

• TDD is dead. Long live testing & RailsConf 2014 Keynote - Writing Software by DHH

• Hangouts entre Kent Beck, DHH y M. Fowler

El caso DHH

¿Cómo hacemos test?

Akamon

Way

Un feedback rápido…

…para el código que estamos escribiendo…

…de una funcionalidad.

¿Qué queremos de los tests?

Testean de manera rápida una funcionalidad.

¿Qué hacen nuestros tests?

Infrastructure

External Services

Test Double

Test DoubleAPIs

DBs

Con

tract

Domain (Business Logic)

Test doubles• Implementación alternativa de un colaborador

(clase o servicio)

• Objetivo:

• Hacer nuestros tests rápidos.

• Aislar sistemas externos.

• Testear casos extremos.

Test doubles• Tipos:

• Dummy: Implementación no funcional.

• Fake: Implementación completamente funcional pero no usable en un entorno real.

• Stub: Implementación parcialmente funcional preparada únicamente para poder ser usada en el test.

• Spy: Stub con memoria.

• Mock: Spy con expectaciones sobre las llamadas a recibir que las auto-comprueba él mismo.

Tests UnitariosPros Contras

Rápidos No pueden probar la ausencia de errores

Permiten testear todos los casos Los doubles no son confiables

Ayudan a encontrar problemas pronto

Los doubles están acoplados a sus implementaciones

Facilitan el cambio

Buena documentación

Escuelas de Tests Unitarios

Chicago / Classical London / Mockist

Énfasis Algoritmo Envío de mensajes

Enfoque Resultado, estado y efectos colaterales

Roles, responsabilidades e

interacciones

LibroTest-Driven

Development by Example

Growing Object Oriented Software Guided by Tests

Unit Testing :: Chicago School• Pros:

• Menor riesgo de expectaciones incorrectas.

• Tests estables.

• Menos mantenimiento.

• Contras:

• Ciclo largo de Red-Green-Refactor.

• Explosión combinatoria de los casos a testear.

• Un simple bug rompe muchos tests.

• Más debugging para encontrar la raíz del error.

Unit Testing :: London School• Pros:

• Facilita el enfoque.

• Baby steps.

• Contras:

• Alto riesgo de expectaciones incorrectas (el refactoring no detecta cambios en los colaboradores)

• Acople del test a la implementación.

• Test frágiles.

Glosario• Test Unitarios:!

• Test del código y la lógica de negocio de una funcionalidad (operaciones con el contrato del módulo).

• Test double: La infraestructura y los servicios externos.

• Riesgo:

• Test demasiado profundo que no permita testear de manera simple todas las casuísticas

by Akamon

…pero los test unitarios no son suficientes…

Queremos saber si las integraciones con los sistemas

externos funcionan correctamente.

Infrastructure

External ServicesAPIs

DBs

Con

tract

Domain (Business Logic)

Tests de Integración

Pros Contras

Confiables Lentos

Encontrar problemas/cambios con servicios de terceros

Imposible de testear algunos casos extremos

Buena documentación

• Test de integración:!

• Test de las implementaciones de los contratos/interfaces de la infraestructura y los servicios externos.

• Test double: Nada.

by AkamonGlosario

…pero con test unitario e integración todavía no es

suficiente…

Applications

APIs

Background

Website

APIsAPIs ?Domain

Module User

Module Analytics

Module Marketing

Module Device

Module Economy

Module Game

Module Game Event

Tests de AceptaciónPros Contras

Amigables y entendibles para usuarios no técnicos Lentos

Gran confianza Complicado de testear algunos casos

Buena documentación Imposible testear algunos casos extremos

Complicado localizar errores

Complicados de escribir (estado inicial)

Glosario

• Test de aceptación:!

• Test de una funcionalidad (end-to-end black-box mode).

• Test double: Nada.

by Akamon

Nuestra pirámide de tests

Acceptance

Integration

Unit

Librerías mock

https://github.com/Akamon/to-mock-or-not-to-mock

PHPUnit_MockObject/** @test */!public function it_should_publish_a_message()!{! $body = 'my message';! $message = new Message($body);! $serializedMessage = ['body' => $body];!! $serializer = $this->getMock(SerializerInterface::class, ['serialize']);! $serializer! ->expects($this->once())! ->method('serialize')! ->with($this->identicalTo($message))! ->will($this->returnValue($serializedMessage));!! $sender = $this->getMock(SenderInterface::class, ['send']);! $sender! ->expects($this->once())! ->method('send')! ->with($this->equalTo($serializedMessage))! ->will($this->returnValue(true));!! $publisher = new Publisher($serializer, $sender);! $this->assertTrue($publisher->send($message));!}

Mockery/** @test */!public function it_should_publish_a_message()!{! $body = 'my message';! $message = new Message($body);! $serializedMessage = ['body' => $body];!! $serializer = Mockery::mock(SerializerInterface::class);! $serializer! ->shouldReceive('serialize')! ->with(Mockery::mustBe($message))! ->once()! ->andReturn($serializedMessage);!! $sender = Mockery::mock(SenderInterface::class);! $sender! ->shouldReceive('send')! ->with($serializedMessage)! ->once()! ->andReturn(true);!! $publisher = new Publisher($serializer, $sender);! $this->assertTrue($publisher->send($message));!}

Phake/** @test */!public function it_should_publish_a_message()!{! $body = 'my message';! $message = new Message($body);! $serializedMessage = ['body' => $body];!! $serializer = Phake::mock(SerializerInterface::class);! Phake::when($serializer)! ->serialize($message)! ->thenReturn($serializedMessage);!! $sender = Phake::mock(SenderInterface::class);! Phake::when($sender)! ->send($serializedMessage)! ->thenReturn(true);!! $publisher = new Publisher($serializer, $sender);! $this->assertTrue($publisher->send($message));!! Phake::verify($serializer, Phake::times(1))->serialize($message);! Phake::verify($sender, Phake::times(1))->send($serializedMessage);!}

Prophecy/** @var Prophet */!private $prophet;!!protected function setup()!{! $this->prophet = new Prophet();!}!!protected function tearDown()!{! $this->prophet->checkPredictions();!}!!/** @test */!public function it_should_publish_a_message()!{! $body = 'my message';! $message = new Message($body);! $serializedMessage = ['body' => $body];!! $serializer = $this->prophet->prophesize(SerializerInterface::class);! $serializer! ->serialize($message)! ->shouldBeCalled()! ->willReturn($serializedMessage);!! $sender = $this->prophet->prophesize(SenderInterface::class);! $sender! ->send($serializedMessage)! ->shouldBeCalled()! ->willReturn(true);!! $publisher = new Publisher($serializer->reveal(), $sender->reveal());! $this->assertTrue($publisher->send($message));!}

ComparativaPHPUnit 4.1 Mockery 0.9 Phake 1.1 Prophecy 1.0 Notas

Invocation Count Constraint Ok Muy bueno Muy bueno Ok

Mockery/Phake son mejores. Métodos atMost() y atLeast()

disponibles.

Ordered Expectations Ok Bueno Ok No Mockery es mejor. Simplemente usando ordered([group]).

Argument Matchers Bueno Ok Ok Ok PHPUnit es mejor. Sobre todo con la funcionalidad delta

Partial Mocking Ok Muy bueno Ok No La construcción es mucho más simple con Mockery.

Mocking Demeter Chains And Fluent

InterfacesOk Muy bueno Ok Ok Muy sencillo con Mockery y un poco

rebuscado con los otros.

Test Doubles Ok Bueno Ok BuenoProphecy es el único con spies y Mockery el único que gestiona

static, final & private

Otro punto de vista

Property-Based Testing• Aproximación totalmente diferente.

• No se escriben los tests, se generan.

• QuickCheck: Canonical framework escrito en Haskell.

• ¿Cómo funciona?:

• Describe las entradas y salidas permitidas y las transiciones de estado.

• Genera aleatóriamente un gran número de casos de test y busca fallos.

• Devuelve el mínimo ejemplo de fallo.

• Casos de uso: Comportamientos no determinísticos y sistemas concurrentes.

Conclusiones

En el mundo del testing lo más importante es determinar la unidad o sistema a testear.

Los tipos de tests, los doubles e incluso los frameworks dependen de la unidad o sistema a

testear.

Consejos

• Evita Minimiza los dobles:

• Están acoplados a la implementación ➙ Limitan la refactorización pura.

• No son confiables ➙ Pueden tener un comportamiento diferente al real.

by Akamon

Consejos

• Los test unitarios testean código no funcionalidad:

• TDD por si solo no es suficiente.

• BDD por si solo puede ser suficiente (si no te importa la lentitud).

• TDD + BDD = WIN

by Akamon

Consejos

• Separa la lógica del test de los datos del test:

• Usa el @dataProvider de PHPUnit (no para los doubles).

• Usa el Scenario Outline de Behat.

by Akamon

• La unidad a testear:

• Mockists are dead. Long live classicists.

• Unit Tests: Isolation

• Mock aren’t stubs: Dummy, Fake, Stub and Mock

• TTDD (Tautological TDD): An anti-pattern

• The depth of tests

• Avoid Testing Implementation Details, Test Behaviours

• The Failures of "Intro to TDD"

• The London School of Test Driven Development

Referencias

• Contract tests (a.k.a integration tests):

• Integrated tests are scam (Collaboration & Contract tests)

• Integration contract tests

Referencias

• La pirámide de los tests:

• Test Pyramid

• Testing Pyramid: A case study

• Inverting the testing pyramid

• Testing ice-crean corn anti-pattern

Referencias

Referencias

• Property-Based testing:

• Better than unit tests

• Powerful testing with test.check

• Testing the Hard Stuff and Staying Sane

• Entrevistas a veteranos del TDD:

• Ron Jeffries (One of the founders of Extreme Programming & Agile Manifesto)

• Steve Freeman (Co-author of Growing Object-Oriented Software Guided by Tests)

• James Shore (Author of The Art of Agile Development)

• J.B. Rainsberger (Author of JUnit Recipes : Practical Methods for Programmer Testing

Referencias

¿Preguntas?

¡Gracias!

Imágeneshttp://transmedialshakespeare.files.wordpress.com/2011/01/3459513455_d1288a14b9_o.jpeg

http://info.fonality.com/Portals/65551/images/Presentation.jpg

http://www.renders-graphiques.fr/image/upload/normal/organisateur_bloc_notes_agenda-.png

http://www.luxfacta.com/wp-content/uploads/2014/01/programar.jpg

http://www.kinderlandshop.es/WebRoot/StoreES2/Shops/eb0950/5020/E112/E380/66B2/C9CA/AC10/1414/0340/C05_1.jpg

http://www.allpurposeabrasives.com.au/uploads/images/Quality%20Assurrance.jpg

http://news.liv.ac.uk/wp-content/uploads/2013/03/knowledgeHOMEb.jpg

http://www.worldnpa.org/site/wp-content/uploads/2013/01/hand-writing.jpg

http://ievasapple.com/photo/images/my%20point%20of%20view.JPG

http://www.snegmortgageteam.ca/wp-content/uploads/2013/12/mortgage-glossary.jpg

http://birddogrealestate.net/wp-content/uploads/2012/09/Home-Toolbox.jpg

http://www.balticblues-events.com/sites/default/files/images/ideas/photos/32-Live-Cooking1.jpg

http://www.youwall.com/papel/on_my_way_wallpaper_fa2bb.jpg

http://inheritancethefilm.com/wp-content/uploads/2013/06/thankyou.jpg

http://www.ngn.com.au/wp-content/uploads/2013/07/Websites-on-white.png

http://hn-marketing.co.uk/wp-content/uploads/2012/09/shutterstock_12553684.jpg

http://picturesofmoney.org/wp-content/uploads/2013/04/Animated-American-Money-Falling-Into-a-Pile.jpg

http://st.gdefon.com/wallpapers_original/wallpapers/18716_palma_more_plyazh_pesok_oblaka_tropiki_2560x1600_(www.GdeFon.ru).jpg

http://i.imgur.com/DbTGPys.gif

http://media.tumblr.com/e96b538708be71104f21689d3a820b9c/tumblr_inline_n54iazp56x1raprkq.gif

http://i.imgur.com/8Lpsys5.gif