Tengo algo como esto:
public byte[] EncodeMyObject(MyObject obj)
He estado haciendo pruebas unitarias como esta:
byte[] expectedResults = new byte[3]{ 0x01, 0x02, 0xFF };
Assert.IsEqual(expectedResults, EncodeMyObject(myObject));
EDITAR: Las dos formas que he visto propuestas son:
1) Usar valores esperados codificados, como el ejemplo anterior.
2) Usar un decodificador para decodificar el conjunto de bytes codificados y comparar los objetos de entrada / salida.
El problema que veo con el método 1 es que es muy frágil y requiere muchos valores codificados.
El problema con el método 2 es que probar el codificador depende de que el decodificador funcione correctamente. Si el codificador / decodificador se rompen por igual (en el mismo lugar), entonces las pruebas podrían producir falsos positivos.
Estas pueden muy bien ser las únicas formas de probar este tipo de método. Si ese es el caso, entonces está bien. Estoy haciendo la pregunta para ver si hay mejores estrategias para este tipo de pruebas. No puedo revelar las partes internas del codificador particular en el que estoy trabajando. Le pregunto en general cómo resolvería este tipo de problema, y no creo que las partes internas sean importantes. Suponga que un objeto de entrada dado siempre producirá la misma matriz de bytes de salida.
fuente
myObject
va demyObject
a{ 0x01, 0x02, 0xFF }
? ¿Se puede descomponer y probar ese algoritmo? La razón por la que pregunto es ahora, parece que tienes una prueba que demuestra que una cosa mágica produce otra cosa mágica. Su única confianza es que la única entrada produce la única salida. Si puede desglosar el algoritmo, puede ganar más confianza en el algoritmo y depender menos de las entradas y salidas mágicas.Respuestas:
Estás en una situación un poco desagradable allí. Si tuviera un formato estático en el que estaba codificando, su primer método sería el camino a seguir. Si fuera solo su propio formato, y nadie más tuviera que decodificar, el segundo método sería el camino a seguir. Pero realmente no encajas en ninguna de esas categorías.
Lo que haría es tratar de desglosar las cosas por nivel de abstracción.
Entonces comenzaría con algo en el nivel de bits, que probaría algo como
Entonces, la idea es que el escritor de bits sepa cómo escribir los tipos de campos más primitivos, como los ints.
Se implementarían tipos más complejos usando y probando algo como:
Tenga en cuenta que esto evita cualquier conocimiento de cómo se empaquetan los bits reales. Eso fue probado por la prueba anterior, y para esta prueba, simplemente asumiremos que funciona.
Luego, en el siguiente nivel de abstracción tendríamos
así que, nuevamente, no tratamos de incluir el conocimiento de cómo se codifican realmente las cadenas de caracteres, las fechas o los números. En esta prueba, solo estamos interesados en la codificación producida por encodeObject.
El resultado final es que si se cambia el formato de las fechas, tendrá que corregir las pruebas que realmente involucran fechas, pero todos los demás códigos y pruebas no se preocupan por cómo se codifican realmente las fechas y una vez que actualiza el código para hacer ese trabajo, todas esas pruebas pasarán bien.
fuente
Depende Si la codificación es algo completamente fijo, donde se supone que cada implementación crea exactamente la misma salida, no tiene sentido verificar nada más que verificar que las entradas de ejemplo se asignen exactamente a las salidas esperadas. Esa es la prueba más obvia, y probablemente también la más fácil de escribir.
Si hay margen de maniobra con salidas alternativas, como en el estándar MPEG (por ejemplo, hay ciertos operadores que puede aplicar a la entrada, pero puede cambiar el esfuerzo de codificación por la calidad de salida o el espacio de almacenamiento), entonces es mejor aplicar el definió una estrategia de decodificación para la salida y verifique que sea la misma que la entrada o, si la codificación tiene pérdidas, que esté razonablemente cerca de la entrada original. Es más difícil de programar, pero lo protege contra cualquier mejora futura que pueda hacerse a su codificador.
fuente
Prueba eso
encode(decode(coded_value)) == coded_value
ydecode(encode(value)) == value
. Puede dar una entrada aleatoria a las pruebas si lo desea.Todavía es posible que tanto el codificador como el decodificador se rompan de manera complementaria, pero eso parece bastante improbable a menos que tenga un malentendido conceptual del estándar de codificación. Hacer pruebas codificadas del codificador y decodificador (como ya lo estás haciendo) debería protegerte contra eso.
Si tiene acceso a otra implementación de esto que se sabe que funciona, al menos puede usarla para tener la seguridad de que su implementación es buena incluso si fuera imposible usarla en las pruebas unitarias.
fuente
decode(encode(char))
no sería igualchar
(sería igualchar+2
).Prueba a los requisitos .
Si los requisitos son '' codificar a un flujo de bytes que cuando se decodifica produce un objeto equivalente '', simplemente pruebe el codificador decodificando. Si está escribiendo tanto el codificador como el decodificador, simplemente pruébelos juntos. No pueden tener "errores coincidentes". Si trabajan juntos, entonces la prueba pasa.
Si hay otros requisitos para el flujo de datos, tendrá que probarlos examinando los datos codificados.
Si el formato codificado está predefinido, entonces deberá verificar los datos codificados con el resultado esperado, como lo hizo, u (mejor) obtener un decodificador de referencia en el que se pueda confiar para realizar la verificación. El uso de un decodificador de referencia elimina la posibilidad de que haya malinterpretado la especificación del formato.
fuente
Dependiendo del marco de prueba y el paradigma que esté utilizando, aún puede usar el patrón Arrange Act Assert para esto como ha dicho.
Debe conocer los requisitos
EncodeMyObject()
y puede usar este patrón para probar cada uno de ellos para criterios válidos e inválidos, organizando cada uno de ellos y codificando el resultado esperado paraexpected
, de manera similar para el decodificador.Dado que los esperados están codificados, estos serán frágiles si tiene un cambio masivo.
Es posible que pueda automatizar con algo controlado por parámetros (eche un vistazo a Pex ) o si está haciendo DDD o BDD eche un vistazo a gerkin / pepino .
fuente
Puedes decidir qué es importante para ti.
¿Es importante para usted que un Objeto sobreviva al viaje de ida y vuelta, y el formato exacto del cable no es realmente importante? ¿O es el formato de cable exacto una parte importante de la funcionalidad de su codificador y decodificador?
Si es lo primero, asegúrese de que los objetos sobrevivan al viaje de ida y vuelta. Si el codificador y el decodificador están rotos de manera exactamente complementaria, realmente no te importa.
Si es lo último, entonces debe probar que el formato del cable es el esperado para las entradas dadas. Esto significa probar el formato directamente o utilizar una implementación de referencia. Pero después de probar lo básico, puede obtener valor de las pruebas adicionales de ida y vuelta, que deberían ser más fáciles de escribir en volumen.
fuente