Presentation in Spanish given at DeSymfony Day 2014 in Barcelona about different approaches of testing with my teammate Jordi Llonch.
We created a GitHub repository comparing the main libraries available in PHP: https://github.com/Akamon/to-mock-or-not-to-mock
11. 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
16. Test doubles
• Implementación alternativa de un colaborador
(clase o servicio)
• Objetivo:
• Hacer nuestros tests rápidos.
• Aislar sistemas externos.
• Testear casos extremos.
17. 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.
18. Tests Unitarios
Pros 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
19. Escuelas de Tests Unitarios
Chicago / Classical London / Mockist
Énfasis Algoritmo Envío de mensajes
Enfoque
Resultado, estado y
efectos colaterales
Roles,
responsabilidades e
interacciones
Libro
Test-Driven
Development by
Example
Growing Object
Oriented Software
Guided by Tests
20. 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.
21. 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.
22. 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
26. Tests de Integración
Pros Contras
Confiables Lentos
Encontrar problemas/cambios
con servicios de terceros
Imposible de testear algunos
casos extremos
Buena documentación
27. • Test de integración:
• Test de las implementaciones de los contratos/
interfaces de la infraestructura y los servicios
externos.
• Test double: Nada.
by Akamon
Glosario
28. …pero con test unitario e
integración todavía no es
suficiente…
30. Tests de Aceptación
Pros 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)
31. Glosario
• Test de aceptación:
• Test de una funcionalidad (end-to-end black-box
mode).
• Test double: Nada.
by Akamon
34. Comparativa
PHPUnit 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
Interfaces
Ok Muy bueno Ok Ok
Muy sencillo con Mockery y un poco
rebuscado con los otros.
Test Doubles Ok Bueno Ok Bueno
Prophecy es el único con spies y
Mockery el único que gestiona
static, final & private
36. 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 aleatoriamente 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.
37. 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.
38. 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
39. 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
40. 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
41. • 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
42. • Test doubles:
• Tests doubles
• Mocks, fakes, stubs and dummies
• The little mocker
Referencias
44. • La pirámide de los tests:
• Test Pyramid
• Testing Pyramid: A case study
• Inverting the testing pyramid
• Testing ice-crean corn anti-pattern
Referencias
46. • 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