Prueba de unidad código funcional tipificado estáticamente

15

Quería preguntarle a la gente, en cuyo caso tiene sentido hacer una prueba unitaria del código funcional estático, tal como está escrito en haskell, scala, ocaml, nemerle, f # o haXe (lo último es lo que realmente me interesa, pero Quería aprovechar el conocimiento de las comunidades más grandes).

Pido esto porque desde mi entendimiento:

  • Un aspecto de las pruebas unitarias es tener las especificaciones en forma ejecutable. Sin embargo, cuando se emplea un estilo declarativo, que asigna directamente las especificaciones formalizadas a la semántica del lenguaje, ¿es incluso realmente posible expresar las especificaciones en forma ejecutable de forma separada, eso agrega valor?

  • El aspecto más obvio de las pruebas unitarias es rastrear errores que no pueden revelarse a través del análisis estático. Dado que el tipo de código funcional seguro es una buena herramienta para codificar muy cerca de lo que entiende su analizador de estática, parece que puede cambiar una gran cantidad de seguridad hacia el análisis estático. Sin embargo, no se puede cubrir un error simple como usar x en lugar de y (ambos son coordenadas) en su código. OTOH tal error también podría surgir al escribir el código de prueba, por lo que no estoy seguro de que valga la pena el esfuerzo.

  • Las pruebas unitarias introducen redundancia, lo que significa que cuando los requisitos cambian, el código que los implementa y las pruebas que cubren este código deben modificarse. Por supuesto, esta sobrecarga es casi constante, por lo que se podría argumentar que realmente no importa. De hecho, en lenguajes como Ruby realmente no se compara con los beneficios, pero dada la forma en que la programación funcional está tipificada estáticamente para muchas de las pruebas de unidad terrestre a las que están destinadas, parece que es una sobrecarga constante que uno simplemente puede reducir sin penalización.

A partir de esto, deduciría que las pruebas unitarias son algo obsoletas en este estilo de programación. Por supuesto, tal afirmación solo puede llevar a guerras religiosas, así que permítanme resumir esto en una pregunta simple:

Cuando utiliza un estilo de programación de este tipo, ¿en qué medida utiliza las pruebas unitarias y por qué (qué calidad espera obtener de su código)? O al revés: ¿tiene criterios por los cuales puede calificar una unidad de código funcional estáticamente tipificado como cubierto por el analizador estático y, por lo tanto, sin necesidad de cobertura de prueba unitaria?

    
pregunta back2dos 24.11.2011 - 11:11
fuente

4 respuestas

8
  

Un aspecto de las pruebas unitarias es tener las especificaciones en forma ejecutable.   Sin embargo, al emplear un estilo declarativo, que mapea directamente el   Especificaciones formalizadas a la semántica del lenguaje, ¿es posible en realidad?   Para expresar las especificaciones en forma ejecutable de forma separada, eso agrega   valor?

Si tiene especificaciones que se pueden asignar directamente a las declaraciones de funciones, está bien. Pero típicamente esos son dos niveles de abstracciones completamente diferentes. Las pruebas unitarias están destinadas a probar piezas individuales de código, escritas como pruebas de caja blanca por el mismo desarrollador que está trabajando en la función. Las especificaciones normalmente se ven como "cuando ingrese este valor aquí y presiono este botón, esto y eso debería suceder". Normalmente, una especificación de este tipo lleva a más de una función a desarrollar y probar.

  

Sin embargo, un simple error como usar x   en lugar de y (ambos son coordenadas) en su código no se pueden cubrir.   Sin embargo, tal error también podría surgir al escribir el código de prueba,   así que no estoy seguro de que valga la pena el esfuerzo.

Su idea errónea es que las pruebas unitarias son en realidad para encontrar errores en su código de primera mano; eso no es cierto, al menos, solo es parcialmente cierto. Están diseñados para evitar que introduzcas errores más adelante cuando tu código evolucione. Entonces, cuando primero probaste tu función y tu prueba de unidad funcionaba (con "x" y "y" correctamente colocadas), y luego, mientras refaccionas usas x en lugar de y, entonces la prueba de unidad te lo mostrará.

  

Las pruebas unitarias introducen redundancia, lo que significa que cuando los requisitos   Cambio, el código que los implementa y las pruebas que cubren este código.   ambos deben ser cambiados. Esta sobrecarga, por supuesto, es constante, por lo que   Se podría argumentar, que en realidad no importa. De hecho, en idiomas.   como Ruby, realmente no lo compara con los beneficios, pero dado cómo   La programación funcional estática mecanizada cubre gran parte del terreno.   las pruebas unitarias están destinadas a, se siente como si fuera una sobrecarga constante   Uno puede simplemente reducir sin penalización.

En ingeniería, la mayoría de los sistemas de seguridad dependen de la redundancia. Por ejemplo, dos roturas en un automóvil, un paracaídas redundante para un buzo, etc. La misma idea se aplica a las pruebas unitarias. Por supuesto, tener más código para cambiar cuando cambian los requisitos puede ser una desventaja. Así que, especialmente en las pruebas unitarias, es importante mantenerlas en seco (siga el principio "No se repita"). En un lenguaje de tipo estático, es posible que tenga que escribir algunas pruebas unitarias menos que en un lenguaje de tipo débil. Especialmente las pruebas "formales" pueden no ser necesarias, lo que es bueno, ya que le da más tiempo para trabajar en las pruebas de unidad importantes que prueban cosas importantes. Y no piense solo porque tiene tipos estáticos, no necesita pruebas unitarias, todavía hay mucho espacio para introducir errores mientras refactoriza.

    
respondido por el Doc Brown 24.11.2011 - 13:31
fuente
5
  

Un aspecto de las pruebas unitarias es tener las especificaciones en forma ejecutable. Sin embargo, cuando se emplea un estilo declarativo, que asigna directamente las especificaciones formalizadas a la semántica del lenguaje, ¿es posible realmente expresar las especificaciones en forma ejecutable de forma separada, eso agrega valor?

Es muy poco probable que pueda completamente expresar sus especificaciones como restricciones de tipo.

  

Cuando utiliza un estilo de programación de este tipo, ¿en qué medida utiliza las pruebas unitarias y por qué (qué calidad espera obtener de su código)?

De hecho, una de las principales ventajas de este estilo es que las funciones puras son más fáciles de probar por unidad: no es necesario configurar el estado externo ni verificarlo después de la ejecución.

A menudo, la especificación (o parte de ella) de una función se puede expresar como propiedades relacionando el valor devuelto con los argumentos. En este caso, utilice QuickCheck (para Haskell) o ScalaCheck (para Scala) puede permitirle escribir estas propiedades como expresiones del idioma y verificar que contengan entradas aleatorias.

    
respondido por el Alexey Romanov 24.11.2011 - 11:55
fuente
1

Puedes pensar en las pruebas unitarias como un ejemplo de cómo usar el código, junto con una descripción de por qué es valioso.

Aquí hay un ejemplo, en el que estaba el tío Bob tan amable de emparejarme conmigo en el "Game of Life" de John Conway . Creo que es un excelente ejercicio para este tipo de cosas. La mayoría de las pruebas son de sistema completo, que prueban todo el juego, pero esa primera prueba solo una función, la que calcula a los vecinos alrededor de una celda. Puede ver que todas las pruebas están escritas en forma declarativa, con el comportamiento que estamos buscando claramente explicado.

También es posible simular las funciones utilizadas en las funciones; ya sea pasándolos a la función (el equivalente de inyección de dependencia), o con marcos como Midje de Brian Marick .

    
respondido por el Lunivore 11.12.2011 - 20:14
fuente
0

Sí, las pruebas unitarias ya tienen sentido con el código funcional estático. Un ejemplo simple:

prop_encode a = (decode . encode $ a) == a

Puedes forzar prop_encode con tipo estático.

    
respondido por el Zhen 24.11.2011 - 11:55
fuente

Lea otras preguntas en las etiquetas