Definitivamente una buena lista. Aquí hay algunos pensamientos al respecto:
Escribe la prueba primero, luego el código.
Estoy de acuerdo, a un alto nivel. Pero, sería más específico: "Primero escriba una prueba, luego escriba el código suficiente para aprobar la prueba y repita". De lo contrario, tendría miedo de que mis pruebas unitarias se parezcan más a pruebas de integración o aceptación.
Diseñar clases usando la inyección de dependencia.
Convenido. Cuando un objeto crea sus propias dependencias, no tienes control sobre ellas. La inversión de control / inyección de dependencia le da ese control, lo que le permite aislar el objeto bajo prueba con simulacros / stubs / etc. Así es como prueba los objetos de forma aislada.
Separe el código de la interfaz de usuario de su comportamiento utilizando Model-View-Controller o Model-View-Presenter.
Convenido. Tenga en cuenta que incluso el presentador / controlador se puede probar usando DI / IoC, entregándole una vista y modelo stubned / simulado. Consulte Presenter First TDD para obtener más información al respecto.
No escriba métodos o clases estáticos.
No estoy seguro de estar de acuerdo con este. Es posible realizar una prueba unitaria de un método / clase estática sin usar simulacros. Entonces, tal vez esta sea una de esas reglas específicas de Rhino Mock que mencionaste.
Programe fuera de interfaces, no de clases.
Estoy de acuerdo, pero por una razón ligeramente diferente. Las interfaces brindan una gran flexibilidad al desarrollador de software, más allá del simple soporte para varios marcos de objetos simulados. Por ejemplo, no es posible admitir DI correctamente sin interfaces.
Aislar las dependencias externas.
Convenido. Oculte las dependencias externas detrás de su propia fachada o adaptador (según corresponda) con una interfaz. Esto le permitirá aislar su software de la dependencia externa, ya sea un servicio web, una cola, una base de datos u otra cosa. Esto es especialmente importante cuando su equipo no controla la dependencia (también conocida como externa).
Marque como virtuales los métodos que pretende simular.
Esa es una limitación de Rhino Mocks. En un entorno que prefiere códigos auxiliares codificados a mano sobre un marco de objeto simulado, eso no sería necesario.
Y, un par de puntos nuevos a considerar:
Utilice patrones de diseño de creación. Esto ayudará con DI, pero también le permitirá aislar ese código y probarlo independientemente de otra lógica.
Escribe pruebas usando la técnica Arrange / Act / Assert de Bill Wake . Esta técnica deja muy claro qué configuración es necesaria, qué se está probando realmente y qué se espera.
No tenga miedo de lanzar sus propias imitaciones / talones. A menudo, encontrará que el uso de marcos de objetos simulados hace que sus pruebas sean increíblemente difíciles de leer. Al lanzar el suyo, tendrá control total sobre sus simulacros / talones y podrá mantener sus pruebas legibles. (Refiérase al punto anterior).
Evite la tentación de refactorizar la duplicación de sus pruebas unitarias en clases base abstractas o métodos de instalación / desmontaje. Al hacerlo, se oculta el código de configuración / limpieza del desarrollador que intenta asimilar la prueba unitaria. En este caso, la claridad de cada prueba individual es más importante que refactorizar la duplicación.
Implementar la integración continua. Registre su código en cada "barra verde". Cree su software y ejecute su conjunto completo de pruebas unitarias en cada registro. (Claro, esta no es una práctica de codificación, per se; pero es una herramienta increíble para mantener su software limpio y completamente integrado).