Si tiene una enumeración solo con valores (no hay métodos como uno podría hacer en Java), y esta enumeración es parte de la definición comercial del sistema, ¿debería uno escribir pruebas unitarias para ello?
Estaba pensando que deberían escribirse, incluso si pudieran parecer simples y redundantes. Considero que lo que concierne a la especificación de negocios debe escribirse explícitamente en una prueba, ya sea con unit / Integration / ui / etc. pruebas o mediante el uso del sistema de tipos del lenguaje como método de prueba. Dado que los valores que debe tener una enumeración (por ejemplo, en Java), desde el punto de vista de la empresa, no pueden probarse utilizando el sistema de tipos, creo que debería haber una prueba unitaria para eso.
Esta pregunta no es similar a esta, ya que no aborda el mismo problema que el mío. En esa pregunta hay una función comercial (savePeople) y la persona está preguntando sobre la implementación interna (forEach). Allí, hay una capa intermedia de negocios (la función de salvar personas) que encapsula la construcción del lenguaje (para cada uno). Aquí la construcción del lenguaje (enum) es la que se usa para especificar el comportamiento desde el punto de vista empresarial.
En este caso, el detalle de implementación coincide con la "naturaleza verdadera" de los datos, es decir: un conjunto (en el sentido matemático) de valores. Podría decirse que podría usar un conjunto inmutable, pero los mismos valores aún deberían estar presentes allí. Si usa una matriz, se debe hacer lo mismo para probar la lógica empresarial. Creo que el enigma aquí es el hecho de que la construcción del lenguaje coincide muy bien con la naturaleza de los datos. No estoy seguro de haberme explicado correctamente
fuente
Respuestas:
No, son solo estado.
Básicamente, el hecho de que esté utilizando una enumeración es un detalle de implementación ; ese es el tipo de cosas que es posible que desee refactorizar en un diseño diferente.
La prueba de integridad de las enumeraciones es análoga a la prueba de que todos los enteros representables están presentes.
Sin embargo, probar los comportamientos que admiten las enumeraciones es una buena idea. En otras palabras, si comienza desde un conjunto de pruebas aprobadas y comenta cualquier valor de enumeración único, entonces al menos una prueba debe fallar (los errores de compilación se consideran fallas).
fuente
Hearts
,Spades
,Diamonds
,Clubs
] si ¿Alguna vez solo cardas si una carta es roja / negra?null_ptr
error. Ahora que tiene un código de error a través de la enumeración. El código que busca unnull_ptr
error también busca el código a través de la enumeración. Por lo tanto, puede tener un valor de5
(por ej.). Ahora necesita agregar otro código de error. Se cambia la enumeración (digamos que agregamos una nueva a la parte superior de la enumeración) El valor denull_ptr
es ahora6
. ¿Es esto un problema? ahora devuelve un código de error6
y prueba6
. Mientras todo sea lógicamente coherente, está bien, a pesar de que este cambio rompa su prueba teórica.No prueba una declaración de enumeración . Puede probar si la entrada / salida de la función tiene los valores de enumeración esperados. Ejemplo:
Usted no escribir pruebas que verifican entonces enumeración
Parity
define los nombres de lasEven
yOdd
. Tal prueba no tendría sentido ya que simplemente estaría repitiendo lo que ya está indicado por el código. Decir lo mismo dos veces no lo hace más correcto.Usted hace las pruebas de verificación de escritura
GetParity
digamos volveránEven
a 0,Odd
de 1 y así sucesivamente. Esto es valioso porque no está repitiendo el código, está verificando el comportamiento del código, independientemente de la implementación. Si el código dentroGetParity
fuera completamente reescrito, las pruebas seguirían siendo válidas. De hecho, los principales beneficios de las pruebas unitarias son que le dan la libertad de reescribir y refactorizar el código de manera segura, al garantizar que el código siga funcionando como se esperaba.Pero si tiene una prueba que garantiza que una declaración enum define los nombres esperados, cualquier cambio que realice en la enumeración en el futuro requerirá que también cambie la prueba. Esto significa que no es solo el doble de trabajo, también significa que se pierde cualquier beneficio de la prueba unitaria. Si tiene que cambiar el código y probarlo al mismo tiempo , entonces no hay protección contra la introducción de errores.
fuente
Si existe el riesgo de que el cambio de la enumeración rompa su código, entonces seguro, cualquier cosa con el atributo [Flags] en C # sería un buen caso porque agregar un valor entre 2 y 4 (3) sería un bit 1 y 2 en lugar de un Artículo discreto.
Es una capa de protección.
Debería considerar tener un código de práctica de enumeración con el que todos los desarrolladores estén familiarizados. No confíe en que las representaciones textuales de la enumeración son comunes, pero esto podría entrar en conflicto con sus pautas de serialización.
He visto a personas "corregir" el uso de mayúsculas en las entradas de enumeración, ordenarlas alfabéticamente o por algún otro grupo lógico que rompió otros bits de código incorrecto.
fuente
No, una prueba que comprueba que una enumeración contiene todos los valores válidos y nada más esencialmente está repitiendo la declaración de la enumeración. Solo estaría probando que el lenguaje implementa correctamente la construcción enum, que es una prueba sin sentido.
Dicho esto, debe probar el comportamiento que depende de los valores de enumeración. Por ejemplo, si está utilizando los valores de enumeración para serializar entidades a json o lo que sea, o almacenando los valores en una base de datos, debe probar el comportamiento de todos los valores de la enumeración. De esa manera, si se modifica la enumeración, al menos una de las pruebas debería fallar. En cualquier caso, lo que estaría probando es el comportamiento en torno a su enumeración, no la declaración de enumeración en sí.
fuente
Su código debería funcionar correctamente independientemente de los valores reales de una enumeración. Si ese es el caso, entonces no se necesitan pruebas unitarias.
Pero es posible que tenga un código donde cambiar un valor de enumeración romperá las cosas. Por ejemplo, si un valor de enumeración se almacena en un archivo externo, y después de cambiar la lectura del valor de enumeración, el archivo externo dará el resultado incorrecto. En ese caso, tendrá un GRAN comentario cerca de la enumeración advirtiendo a cualquiera que no modifique ningún valor, y puede escribir una prueba unitaria que verifique los valores numéricos.
fuente
En general, simplemente comprobar que una enumeración tiene una lista codificada de valores no es de mucho valor, como dicen otras respuestas, porque entonces solo necesita actualizar la prueba y la enumeración juntas.
Una vez tuve el caso de que un módulo usaba tipos de enumeraciones de otros dos módulos y se asignaba entre ellos. (Una de las enumeraciones tenía lógica adicional, la otra era para el acceso a la base de datos, ambas tenían dependencias que debían aislarse entre sí).
En este caso, agregué una prueba (en el módulo de mapeo) que verificó que todas las entradas de enumeración en la enumeración de origen también existen en la enumeración de destino (y, por lo tanto, que la asignación siempre funcionaría). (En algunos casos, también revisé al revés).
De esta manera, cuando alguien agrega una entrada de enumeración a una de las enumeraciones y se olvida de agregar la entrada correspondiente a la otra, una prueba comienza a fallar.
fuente
Las enumeraciones son simplemente tipos finitos, con nombres personalizados (con suerte significativos). Una enumeración solo puede tener un valor, como el
void
que contiene solonull
(algunos idiomas lo llamanunit
y usan el nombrevoid
de una enumeración sin elementos). Puede tener dos valores, comobool
cual tienefalse
ytrue
. Puede tener tres, comocolourChannel
conred
,green
yblue
. Y así.Si dos enumeraciones tienen el mismo número de valores, entonces son "isomórficas"; es decir, si cambiamos todos los nombres sistemáticamente, podemos usar uno en lugar de otro y nuestro programa no se comportará de manera diferente. En particular, nuestras pruebas no se comportarán de manera diferente.
Por ejemplo,
result
contenerwin
/lose
/draw
es isomorfo a lo anteriorcolourChannel
, ya que podemos reemplazar, por ejemplo ,colourChannel
conresult
,red
conwin
,green
conlose
yblue
condraw
, y siempre que lo hagamos en todas partes (productores y consumidores, analizadores y analizadores, entradas de bases de datos, archivos de registro, etc. ) entonces no habrá cambios en nuestro programa. Cualquier "colourChannel
prueba" que hayamos escrito pasará, ¡aunque ya nocolourChannel
haya más!Además, si una enumeración contiene más de un valor, siempre podemos reorganizar esos valores para obtener una nueva enumeración con el mismo número de valores. Dado que el número de valores no ha cambiado, la nueva disposición es isomorfa a la anterior, y por lo tanto podríamos cambiar todos los nombres y nuestras pruebas aún pasarían (tenga en cuenta que no podemos simplemente cambiar la definición; debemos todavía cambia todos los sitios de uso también).
Lo que esto significa es que, en lo que respecta a la máquina, las enumeraciones son "nombres distinguibles" y nada más . Lo único que podemos hacer con una enumeración es ramificar si dos valores son iguales (por ejemplo,
red
/red
) o diferentes (por ejemplo,red
/blue
). Así que eso es lo único que puede hacer una 'prueba unitaria', por ejemploComo dice @ jesm00, tal prueba está verificando la implementación del lenguaje en lugar de su programa. Estas pruebas nunca son una buena idea: incluso si no confía en la implementación del lenguaje, debe probarlo desde el exterior , ya que no se puede confiar en ejecutar las pruebas correctamente.
Entonces esa es la teoría; ¿Qué hay de la práctica? El problema principal con esta caracterización de las enumeraciones es que los programas del "mundo real" rara vez son autónomos: tenemos versiones heredadas, implementaciones remotas / integradas, datos históricos, copias de seguridad, bases de datos en vivo, etc., por lo que nunca podemos realmente "cambiar" todas las apariciones de un nombre sin perder algunos usos.
Sin embargo, tales cosas no son la 'responsabilidad' de la enumeración en sí: cambiar una enumeración podría interrumpir la comunicación con un sistema remoto, pero a la inversa, ¡podríamos solucionar ese problema cambiando una enumeración!
En estos escenarios, la enumeración es una pista falsa: ¿y si un sistema necesita que sea esta manera, y otro necesita que sea que manera? ¡No pueden ser ambas cosas, no importa cuántas pruebas escribamos! El verdadero culpable aquí es la interfaz de entrada / salida, que debería producir / consumir formatos bien definidos en lugar de "cualquier número entero que elija la interpretación". Entonces, la solución real es probar las interfaces de E / S: con pruebas unitarias para verificar que está analizando / imprimiendo el formato esperado, y con pruebas de integración para verificar que el otro lado acepte el formato.
Todavía podemos preguntarnos si la enumeración se está "ejercitando lo suficientemente bien", pero en este caso la enumeración es nuevamente una pista falsa. Lo que realmente nos preocupa es el conjunto de pruebas en sí . Podemos ganar confianza aquí de dos maneras:
red
, y solo probamosred
, entonces tenemos una cobertura del 100%. Un verificador de propiedades (intentará) generar contraejemplos a nuestras afirmaciones, como generar los valoresgreen
yblue
que olvidamos probar.fuente
No. Las pruebas unitarias son para unidades de prueba.
https://en.wikipedia.org/wiki/Unit_testing
Una prueba automatizada para una enumeración declarada probaría la integridad del lenguaje y la plataforma en la que se ejecuta, en lugar de la lógica en el código creado por el desarrollador. No serviría para ningún propósito útil: la documentación se incluye ya que el código que declara la enumeración sirve como documentación, así como también el código que lo probaría.
fuente
Se espera que pruebe el comportamiento observable de su código, los efectos de las llamadas a métodos / funciones en el estado observable. Mientras el código haga lo correcto, está bien, no necesita probar nada más.
No necesita afirmar explícitamente que un tipo de enumeración tiene las entradas que espera, al igual que no afirma explícitamente que una clase realmente existe o que tiene los métodos y atributos que espera.
En realidad, al probar el comportamiento, usted afirma implícitamente que las clases, los métodos y los valores involucrados en la prueba existen, por lo que no es necesario que lo haga explícitamente.
Tenga en cuenta que no necesita nombres significativos para que su código haga lo correcto, eso es solo una conveniencia para las personas que leen su código. Se podría hacer su trabajo de código con los valores de enumeración como
foo
,bar
... y métodos comofrobnicate()
.fuente