and php unit-testing phpunit accessor getter-setter

getter and setter php



Unidades de pruebas accesorias(getters y setters) (3)

Buena pregunta,

Por lo general, trato de no probar directamente a los captadores y definidores, ya que veo un mayor beneficio al probar solo los métodos que realmente hacen algo.

Especialmente cuando no utilizo TDD, esto tiene el beneficio adicional de mostrarme los configuradores que no uso en mis pruebas de unidad, mostrándome que otras pruebas están incompletas o que el configurador no se usa / necesita. "Si puedo ejecutar todo el código" real "sin usar ese setter, ¿por qué está ahí?"

Cuando utilizo el establecedor fluido, a veces escribo una prueba para verificar la parte "fluida" de los definidores, pero generalmente esto se cubre en otros exámenes.

Para responder a su lista:

  • Sólo un método de prueba?

Esa es mi opción menos favorita. Todo o nada. Probar solo uno no es fácil de entender para otras personas y parece ''aleatorio'' o necesita ser documentado de alguna manera.

Editar después del comentario:

Sí, para las pruebas "triviales" de obtención / ajuste, solo usaría un método por propiedad, tal vez dependiendo del caso, incluso un solo método para toda la clase (para objetos de valor con muchos captadores y definidores no quiero escribir / mantener muchas pruebas)

  • ¿Cómo escribirías pruebas unitarias para esos métodos?
  • ¿Debo saltarme esas pruebas?

No los saltearía. Tal vez los captadores, dependiendo de cuántos tengas (tiendo a escribir solo los captadores que realmente necesito), pero la tarea de tener una clase completamente cubierta no debería fallar debido a los captadores.

  • ¿Qué pasa con la cobertura de código?
  • ¿Qué hay de @covers anotación?

Con @covers mi toma siempre es "usarla en todas partes o no usarla en absoluto". Mezclar los dos ''estilos'' de prueba quita algunos de los beneficios de la anotación y me parece ''inacabado''.

  • ¿Tal vez algún método de prueba universal para implementar en el caso de prueba abstracta?

Para algo como objetos de valor que podrían funcionar bien. Puede romperse (o se vuelve más complicado) una vez que se pasa a los objetos / matriz con sugerencias de tipo, pero prefiero presonalmente que a las pruebas manuales para 500 captadores y definidores.

Teniendo en cuenta los siguientes métodos:

public function setFoo($foo) { $this->_foo = $foo; return $this; } public function getFoo() { return $this->_foo; }

Suponiendo que se pueden cambiar para que sean más complejos en el futuro:

  • ¿Cómo escribirías pruebas unitarias para esos métodos?
  • Sólo un método de prueba?
  • ¿Debo saltarme esas pruebas?
  • ¿Qué pasa con la cobertura de código?
  • ¿Qué hay de @covers anotación?
  • ¿Tal vez algún método de prueba universal para implementar en el caso de prueba abstracta?

(Yo uso Netbeans 7)

Esto parece una pérdida de tiempo, pero no me importaría si IDE generara esos métodos de prueba automáticamente.

A partir del comentario del blog de Sebastian Bergman :

(Es como probar a los enterradores y establecedores, ¡falla!). En cualquier caso, si fuesen a fallar; ¿No fallarían los métodos que dependen de ellos?

Entonces, ¿qué pasa con la cobertura del código?


Esta es una pregunta común, pero extrañamente no se puede encontrar una trampa en SO.

Podría escribir pruebas unitarias para los accesores, pero la mayoría de los practicantes no lo hacen. es decir, si los accesores no tienen ninguna lógica personalizada, no escribiría pruebas unitarias para verificar si el acceso al campo funciona. En su lugar, confiaría en los consumidores de estos accesores para garantizar que los accesores funcionen. por ejemplo, si getFoo y setFoo no funcionan, los interlocutores de estos métodos deberían interrumpirse. Entonces, al escribir pruebas unitarias para los métodos de llamada, los accesores se verifican.

Esto también significa que la cobertura del código no debería ser un problema. Si encuentra accesores que no están cubiertos después de que se ejecutan todos los paquetes de prueba, tal vez sean redundantes / no utilizados. Borra los.

Intente escribir una prueba que ilustre un escenario en el que un cliente usará ese acceso. por ejemplo, el siguiente fragmento de código muestra cómo la información sobre herramientas (propiedad) para el botón de pausa cambia en función de su modo actual.

[Test] public void UpdatesTogglePauseTooltipBasedOnState() { Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons)); _mainViewModel.TogglePauseCommand.Execute(null); Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_ResumeAllBeacons)); _mainViewModel.TogglePauseCommand.Execute(null); Assert.That(_mainViewModel.TogglePauseTooltip, Is.EqualTo(Strings.Main_PauseAllBeacons)); }


Si haces TDD, deberías escribir una prueba para getter y setter. también. No escriba una sola línea de código sin una prueba, incluso si su código es muy simple.

Es una especie de guerra religiosa usar un tándem de captador y definidor para tu prueba o aislar a cada uno accediendo a miembros de la clase protegida utilizando las capacidades del marco de tu unidad de prueba. Como probador de caja negra, prefiero vincular el código de prueba de mi unidad a la API pública en lugar de vincularlo a los detalles concretos de la implementación. Espero cambio. Quiero animar a los desarrolladores a refactorizar el código existente. Y las clases internas no deben afectar al "código externo" (pruebas de unidad en este caso). No quiero interrumpir las pruebas unitarias cuando cambian los aspectos internos, quiero que se rompan cuando cambie la API pública o cuando cambie el comportamiento. Ok, ok, en caso de una prueba unitaria fallida, no identifique la única fuente del problema. Tengo que buscar en el captador Y en el colocador para averiguar qué causó el problema. La mayoría de las veces, su captador es muy simple (menos de 5 líneas de código: por ejemplo, una devolución y una verificación de nulos opcional con una excepción). Por lo tanto, comprobar esto primero no es gran cosa y no consume mucho tiempo. Y, en la mayoría de los casos, comprobar el camino feliz del colocador solo es un poco más complejo (incluso si tiene algunas comprobaciones de validación).

Intente aislar sus casos de prueba: escriba una prueba para un SUT (Sujeto a prueba) que valide su corrección sin ningún otro método (excepto mi ejemplo anterior). Cuanto más aísle la prueba, más sus pruebas detectan el problema.

Dependiendo de su estrategia de prueba, es posible que desee cubrir solo el camino feliz (programador pragmático). O tristes pathes, también. Prefiero cubrir todos los parches de ejecución. Cuando creo que descubrí todos los parches de ejecución, compruebo la cobertura del código para identificar el código muerto (no para identificar si hay parches de ejecución no cubiertos: el 100% de la cobertura del código es un indicador erróneo).

Es una práctica recomendada para los probadores de caja negra usar phpunit en modo estricto y usar @covers para ocultar la cobertura colateral.

Cuando escriba la prueba unitaria, su prueba en la clase A debe ejecutarse independientemente de la clase B. Por lo tanto, las pruebas unitarias para la clase A no deben llamar / cubrir el método de la clase B.

Si desea identificar el getter / setter obsoleto y otros métodos "muertos" (que no son utilizados por el código de producción) utilice el análisis de código estático para eso. La métrica que le interesa se llama "Acoplamiento aferente a nivel de método (MethodCa)". Desafortunadamente, esta métrica (ca) no está disponible a nivel de método en PHP Depend (consulte: http://pdepend.org/documentation/software-metrics/index.html y http://pdepend.org/documentation/software-metrics/afferent-coupling.html ). Si realmente lo necesita, siéntase libre de contribuir con PHP Depend. Una opción para excluir llamadas de la misma clase sería útil para obtener un resultado sin llamadas "colaterales". Si identifica un "método muerto", intente averiguar si está destinado a ser utilizado en un futuro próximo (la contraparte de otro método que tenga una anotación @depricated), de lo contrario, elimínelo. En caso de que se use solo en la misma clase, hágalo privado / protegido. No aplique esta regla al código de la biblioteca.

Plan B: Si tiene pruebas de aceptación (prueba de integración, prueba de regresión, etc.), puede ejecutar esa prueba sin ejecutar pruebas unitarias al mismo tiempo y sin el modo estricto de phpunits. Esto puede resultar en un resultado de cobertura de código muy similar, como si hubiera analizado su código de producción. Pero en la mayoría de los casos, sus pruebas no unitarias no son tan fuertes como lo es su código de producción. Depende de su disciplina si este plan B es "lo suficiente" al código de producción para obtener un resultado significativo.

Lectura adicional: - Libro: Programador pragmático - Libro: Código limpio