¿Necesito probar todo?

28

Voy a comenzar mi primer proyecto real en Ruby on Rails , y me estoy obligando a escribir pruebas TDD . No veo ventajas reales en escribir pruebas, pero como parece muy importante, lo intentaré.

¿Es necesario probar cada parte de mi aplicación, incluidas las páginas estáticas?

Matteo Pagliazzi
fuente
99
Esto realmente no es una pregunta de ruby ​​on rails. Es más una pregunta de TDD.
Jon Strayer
44
@ JonStrayer: ¿Lo es? ¿Está seguro de que la respuesta sería la misma para RoR que para .NET? Sugeriría que, por diseño, RoR ha reducido deliberadamente el costo de las pruebas, mientras que no tener la seguridad de tipo en forma de compilador aumenta enormemente el beneficio de las pruebas.
pdr
1
Por alguna razón, esta pregunta me hace querer publicar una macro de imagen del Capitán Nero gritando "¡¡¡PRUEBE TODO !!!"
Mason Wheeler
3
No ver la verdadera ventaja de escribir pruebas y escribirlas por fe ciega realmente no suena bien. Continúe sin escribir pruebas, después de un tiempo experimentará una regresión inesperada y sabrá por qué está probando.
ZJR
1
Espere hasta que decida reestructurar su código. Cada vez que se introducen cambios masivos, debe verificar la funcionalidad. Sin pruebas, deberá revisar su aplicación y probar todas las funcionalidades manualmente. Introduce otra gran actualización y tendrás que volver a hacerlo. Las pruebas unitarias son solo una forma "barata" de asegurarse de que todo funcione como se espera.
Evan Plaice

Respuestas:

47

TDD no se trata de pruebas, se trata de diseño. Escribir las pruebas te obliga a pensar cómo se supone que funciona la clase y qué tipo de interfaz necesitas. Las pruebas son un efecto secundario feliz que facilita la refactorización posterior.

Entonces, con eso en mente, ¿cuál es el comportamiento de una página estática y cuál es la interfaz?

Mi primera respuesta sería "ninguno" y "ninguno".

Jon Strayer
fuente
así que no hay pruebas para páginas estáticas?
Matteo Pagliazzi
TDD es, hasta cierto punto, sobre diseño. Pero aún necesitas una arquitectura. Sin una arquitectura en mente, es difícil imaginar cómo uno crecería orgánicamente de un montón de pruebas.
Robert Harvey
@MatteoPagliazzi Dependiendo del nivel de la prueba (pruebas unitarias / pruebas de integración / etc.), quizás una o dos, para confirmar que las páginas estáticas son accesibles. Pero eso es demasiado alto para pruebas unitarias.
Izkata
1
@RobertHarvey No dije que no probara nada. Dije que no pruebe las páginas estáticas.
Jon Strayer
@JonStrayer: los TDD'ers tienden a mostrar TDD como un elixir mágico para el diseño; Pido disculpas si eso no es lo que querías decir. :)
Robert Harvey
32

Siempre es un análisis de costo-beneficio. ¿Cuál es el costo de la función para usted? Si el costo es alto, pruebe bien y a fondo. Si el costo es bajo, pruebe a la ligera o no lo haga.

También hay que considerar el costo del tiempo de comercialización. Tal vez sea mejor para usted ofrecer una función que funcione en su mayor parte que llegar tarde a una función completamente funcional.

Es casi imposible responder estas preguntas en la OMI general.

Creo que es más importante preservar la capacidad de prueba en el caso de que alguna característica resulte ser más importante de lo que originalmente creías.

Doug T.
fuente
Además, supongo que los errores en una página estática serían MUCHO más fáciles de corregir que los errores lógicos, los errores de diseño y el tipo de cosas que TDD normalmente se usa para prevenir. Es probable que descubrir y corregir errores de páginas estáticas sea bastante fácil, y tengo la impresión de que TDD se utiliza para acortar ambos procesos cuando tardan más de lo deseado. : D
Gordon Gustafson
No supondría eso. Si alguna vez ha lidiado con comportamientos oscuros de la versión del navegador o problemas extraños con la memoria de JavaScript, probablemente haya hecho un buen entrenamiento. Más a veces, ya que los lenguajes de back-end pueden ser un poco más confiables y estándar. a veces. Tal vez estás hablando de estática como en html y sin javascript.
Michael Durrant
8

Yo diría que sí". Si tiene pruebas que cubren incluso las características y el código más simples, puede estar seguro de que agregar un nuevo código no hace que el código en el lugar deje de funcionar. Del mismo modo, poner a prueba cada error que encuentre evita que las regresiones sigan apareciendo.

Bruce Ediger
fuente
"entonces puede confiar en que agregar un nuevo código no hace que el código en el lugar deje de funcionar" de esa manera, ¿no debería tocar ningún fragmento de código que haya escrito antes y simplemente agregar nuevos métodos?
Matteo Pagliazzi
Bueno no. Pero las dependencias imprevistas y no planificadas entre el código que actualmente "funciona" pueden ocasionar problemas si agrega un nuevo código que cambie esas dependencias. Además, si se equivoca en la prueba, lo cual creo que es bastante común, debe modificar la prueba en sí misma y luego, tal vez, modificar el código que surge de esa prueba.
Bruce Ediger
@Andy Eso es una tontería absoluta. Probar los establecedores y captadores de propiedades es trivial y VITAL. Si no funcionan, generalmente toda la clase se desmorona. Por ejemplo, en una aplicación multiproceso, si el conjunto no impide la obtención simultánea, obtendrá un problema de datos corruptos que puede tardar horas en llegar al fondo, porque la fuente de datos será correcta, pero el resultado será O no, si su conjunto no actualiza también el tiempo de actualización, entonces sus datos pueden volverse imposibles de sincronizar. Usted entiende la idea. Si los acomodadores y captadores fueran genuinamente triviales, podría hacer pública la propiedad
deworde
@deworde Me temo que hacer que los miembros de instancias sean seguros no es tan común. Es más habitual controlar el acceso al tipo seguro que no es de Thead que tratar de hacerlos seguros para subprocesos. De todos modos, qué probar es una cuestión de costo-beneficio, como dice otra respuesta. puede pasar tiempo escribiendo pruebas para getters o setters o puede probar el comportamiento real que se supone que encapsula su sistema.
Andy
3

Sí, deberías probar todo ...

No necesariamente podrá escribir pruebas automatizadas para todo. Para sus páginas estáticas, considere el uso de Selenium http://seleniumhq.org/ para asegurarse de que las cosas estén correctas.

Desde mi experiencia, algunas cosas de front-end son casi imposibles de escribir para casos de prueba, pero es por eso que realmente querría probar usando el globo ocular Mark 1.

Schleis
fuente
Estoy en desacuerdo. Si no puede hacer que suceda ya sea a través de una simulación o pasando datos, entonces, ¿por qué tenerlo en su código? Los getters y setters no necesitan sus propias pruebas puestas a prueba a través de otras pruebas unitarias del sistema para verificar la funcionalidad esperada.
Schleis
Claro, los setters / getters se prueban indirectamente con otras pruebas, pero cuando alguien dice "probar todo", supongo que significan crear pruebas específicamente para ese tipo de cosas. Siempre le digo a la gente que "pruebe las cosas importantes". Cosas como setters y getters no encajan en esa definición para mí.
Andy
2

Las pruebas son tan importantes como la codificación. Debe escuchar el dicho "Si algo puede salir mal, lo hará". INMO, de las muchas técnicas de ingeniería de software que se emplean para mejorar la calidad, Testing es la más valiosa para ayudarlo a encontrar problemas temprano.

Si bien probar todo no es posible (especialmente con equipos pequeños y sistemas grandes), no significa que omita las pruebas por completo. ¿Vale la pena la prueba? Consulte la sección "Búsqueda temprana de fallas" en Ver Wiki-SoftwareTesting .

Ninguna posibilidad
fuente
2

Las pruebas TDD también pueden ser especificaciones vivas si se escriben de esa manera. Los nombres de los métodos de prueba deben tener sentido para un usuario comercial.

Chriseyre2000
fuente
2

Como otros han mencionado, en las pruebas de Ruby on Rails es mucho más importante que en (la mayoría) de otros idiomas. Esto se debe a la falta de un compilador.

Los lenguajes como Delphi , C ++, VB.NET , etc. son lenguajes compilados, y su compilador recogerá muchos errores como errores tipográficos en las llamadas a un método. En Ruby on Rails solo sabrá si hay un error tipográfico o un error en su código si se ejecuta esa línea de código en particular o si está utilizando un IDE que muestra advertencias visuales.

Como CADA línea de código es importante (de lo contrario no estaría allí), debe probar cada método que escriba. Esto es mucho más simple de lo que parece si sigues algunas herramientas básicas de TBDD.

Descubrí que los Rails Cast on Test de Ryan Bates fueron invaluables para mí y realmente resaltaron la simplicidad de TBDD si se realiza correctamente.

jamesc
fuente
1

Si realmente está utilizando la metodología TDD, entonces no escribe código sin tener primero una prueba unitaria que está tratando de aprobar.

wessiyad
fuente
2
sí ... pero, por ejemplo, en una página estática, ¿qué debo probar? la existencia de eso? que el contenido y los enlaces existen? tal vez estoy equivocado pero parece una pérdida de tiempo ...
Matteo Pagliazzi
1
Tiendo a pensar que la metodología TDD se aplica a su lógica. ¿Es su página estática un archivo html? ¿Una vista MVC que nunca cambia? Si este último caso, supongo que podría probar que su controlador devuelve la vista adecuada. Creo que lo más importante es recordar que TDD debería ayudar a desarrollar en contra de su especificación no sólo "prueba" ...
wessiyad
Supongo que simplemente sirve una página estática con un componente del marco. Si ninguno de sus métodos toca esa página, de hecho no hay nada que probar. Tampoco necesitas probar Rails. Creo que alguien tiene eso cubierto.
Erik Reppen
0

Yo diría que no comience con TDD. Tome una decisión informada cuando haya pasado más tiempo aprendiendo estrategias de arquitectura en general. TDD no le permitirá omitir esa tarea, aunque puede comenzar a creer que sí.

Aquí está mi problema con eso. Cuando dices que parece una gran cantidad de tiempo perdido en cosas que nunca romperán, los TDDers dicen que lo apreciarás cuando esa cosa que no anticipaste en una gran cadena de dependencias se rompa. Cuando señala que es imposible predecir tales cosas antes de escribir su aplicación, que es uh ... por qué probamos, le dicen que realmente se trata más del diseño y no de las pruebas, aunque las pruebas son útiles.

¿Pero no son las cadenas gigantes de dependencias vinculadas impredecibles el producto del diseño horrible?

Entonces, ¿cuál es?

Aquí hay un pensamiento. No tengamos enormes cadenas complejas de dependencias en primer lugar al considerar los siguientes dos principios de diseño orientado a objetos de Design Patterns:

"Programa para una interfaz, no una implementación"

Es decir, a tus objetos no debería importarles quién llama o cómo se hicieron. Solo que los argumentos apropiados se introdujeron y que los métodos que llaman desde otros objetos están dirigidos a funcionar como se esperaba. Su cadena de dependencia en la mayoría de los casos debe estar en un punto de enlace, la llamada al método por parte de la persona que llama y el lugar donde los argumentos se dejan caer en sus métodos. Ahí es donde se registra, valida y envía mensajes útiles para la depuración cuando las cosas se resuelven.

Y:

"Favorecer la composición de objetos sobre la herencia de clases"

¿Quién es el muñeco? ¿El tipo que le hizo algo a una clase en un intrincado esquema de herencia en cascada que involucra como 30 clases que resultan en la ruptura del caso marginal, o el desarrollador que ideó esa arquitectura en primer lugar? TDD podría ayudarlo a llegar al fondo de los problemas dentro de esa torre inclinada de clase Pisa antes de lo que podría haberlo hecho, pero ¿eso hace que sea menos doloroso intentar modificar uno de los puntos finales de ese desastre de código la próxima vez?

Y ahí es donde llego a lo que me molesta. ¿TDD realmente ayuda a diseñar o permite una mala arquitectura? Me parece que tiene potencial para ser una estrategia autocumplida. Cuanto más no tenga su propio equipo la responsabilidad de una arquitectura pobre, más útiles serán esos componentes de prueba granulares, pero en última instancia, su aplicación se convertirá en una PITA cada vez más grande para trabajar (suponiendo que nunca pensaron mucho en la arquitectura al principio lugar). Y no reconocer las consecuencias de eso es, sin duda, el error más costoso que puede cometer al trabajar en una aplicación que debe actualizarse y modificarse con el tiempo.

Erik Reppen
fuente
-1

Para responder la pregunta, piense en "qué podría salir mal aquí". En particular, si cambia el "código" (marcado / lo que sea), ¿cómo va a confiar en que no ha roto la página? Bueno, para una página estática:

  • puede que no se procese
  • podría presentar incorrectamente
  • el JS podría no cargar
  • los caminos para las imágenes pueden no funcionar
  • los enlaces pueden estar rotos

Personalmente, recomendaría:

  • escriba una prueba de selenio [1] que verifique la cadena que espera en la página (cerca de la parte inferior si es posible). Esto valida que se procesa.
  • compruebe que no hay errores de JS (creo que el selenio lo permite)
  • ejecute las páginas estáticas a través de un validador html y, si es posible, un verificador de enlaces.
  • No he encontrado una herramienta que me guste para validar JS, pero es posible que tenga éxito con jslint o jshint.

La conclusión aquí es que desea algo que sea repetible, fácil de usar y que se ejecute automáticamente en su corredor de prueba.

Paul Biggar
fuente
-1

Solo para agregar a todas las respuestas ya excelentes, aquí está mi pensamiento sobre qué evaluar y qué no evaluar:

Hacer prueba:

  • lógica de negocios
  • lógica de aplicación
  • funcionalidad
  • comportamiento,
  • entonces, todo, realmente, excepto :

No probar:

  • constantes
  • presentación

Entonces no tiene sentido hacerse una prueba que diga:

assert wibble = 3

y un código que dice

wibble = 3

Y tampoco tiene sentido probar cosas de presentación, como si el ícono está en azul perywinkle, qué fuente ha utilizado para los encabezados, etc.

Entonces, pregunta, "debería probar páginas estáticas", y la respuesta es: las prueba en la medida en que son parte de la funcionalidad, la lógica comercial o el comportamiento de su sitio.

Entonces, en nuestra aplicación, tenemos una prueba que verifica que los términos y condiciones estén disponibles en todas las partes del sitio, para usuarios anónimos, para usuarios que han iniciado sesión, desde el tablero, dentro de las pantallas de la aplicación, etc. Simplemente verifica que haya un enlace llamado "términos y condiciones" en cada página, que el enlace funciona, y luego la prueba dice que cuando llega a la página, "parece" los Ts & Cs, lo suficiente para asegurarse de que es la página correcta, sin "probar una constante" o "probar la presentación" ... para que pueda verificar que el texto sea correcto, por ejemplo, sin verificar el tamaño de fuente o el diseño de texto en particular ...

hwjp
fuente