¿Deben codificarse los resultados esperados de una prueba unitaria, o pueden depender de variables inicializadas? ¿Los resultados codificados o calculados aumentan el riesgo de introducir errores en la prueba unitaria? ¿Hay otros factores que no he considerado?
Por ejemplo, ¿cuál de estos dos es un formato más confiable?
[TestMethod]
public void GetPath_Hardcoded()
{
MyClass target = new MyClass("fields", "that later", "determine", "a folder");
string expected = "C:\\Output Folder\\fields\\that later\\determine\\a folder";
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
[TestMethod]
public void GetPath_Softcoded()
{
MyClass target = new MyClass("fields", "that later", "determine", "a folder");
string expected = "C:\\Output Folder\\" + string.Join("\\", target.Field1, target.Field2, target.Field3, target.Field4);
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
EDITAR 1: En respuesta a la respuesta de DXM, ¿es la opción 3 una solución preferida?
[TestMethod]
public void GetPath_Option3()
{
string field1 = "fields";
string field2 = "that later";
string field3 = "determine";
string field4 = "a folder";
MyClass target = new MyClass(field1, field2, field3, field4);
string expected = "C:\\Output Folder\\" + string.Join("\\", field1, field2, field3, field4);
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
c#
unit-testing
Hand-E-Food
fuente
fuente
Respuestas:
Creo que el valor esperado calculado da como resultado casos de prueba más robustos y flexibles. Además, al usar buenos nombres de variables en la expresión que calculan el resultado esperado, es mucho más claro de dónde vino el resultado esperado en primer lugar.
Dicho esto, en su ejemplo específico NO confiaría en el método "Softcoded" porque usa su SUT (sistema bajo prueba) como entrada para sus cálculos. Si hay un error en MyClass donde los campos no se almacenan correctamente, su prueba realmente pasará porque su cálculo de valor esperado usará la cadena incorrecta al igual que target.GetPath ().
Mi sugerencia sería calcular el valor esperado donde tenga sentido, pero asegúrese de que el cálculo no dependa de ningún código del SUT.
En respuesta a la actualización de OP a mi respuesta:
Sí, según mi conocimiento pero con una experiencia algo limitada en hacer TDD, elegiría la opción # 3.
fuente
¿Qué pasa si el código es el siguiente?
Su segundo ejemplo no detectaría el error, pero el primer ejemplo sí.
En general, recomendaría contra la codificación suave porque puede ocultar errores. Por ejemplo:
¿Puedes detectar el problema? No cometerías el mismo error en una versión codificada. Es más difícil obtener los cálculos correctos que los valores codificados. Es por eso que prefiero trabajar con valores codificados que con valores codificados.
Pero hay excepciones. ¿Qué pasa si su código tiene que ejecutarse en Windows y Linux? ¡La ruta no solo tendrá que ser diferente, sino que también deberá usar separadores de ruta diferentes! Calcular el camino usando funciones que abstraen la diferencia entre podría tener sentido en ese contexto.
fuente
En mi opinión, ambas sugerencias son menos que ideales. La forma ideal de hacerlo es esta:
En otras palabras, la prueba debe funcionar exclusivamente en función de la entrada y la salida del objeto, y no en función del estado interno del objeto. El objeto debe tratarse como un cuadro negro. (No tengo en cuenta otros problemas, como lo inapropiado de usar string.Join en lugar de Path.Combine, porque esto es solo un ejemplo).
fuente
target.Dispose(); Assert.IsTrue(target.IsDisposed);
(un ejemplo muy simple)Hay dos aspectos en la discusión:
1. Uso del objetivo en sí para el caso de prueba
La primera pregunta es ¿debería / puede usar la clase en sí misma para confiar y realizar parte del trabajo en el trozo de prueba? - La respuesta es NO ya que, en general, nunca debe asumir el código que está probando. Si esto no se hace correctamente, con el tiempo los errores se vuelven inmunes a algunas pruebas unitarias.
2. Hardcoding
debería codificar duro ? De nuevo la respuesta es no . porque, como cualquier software, la codificación dura de la información se vuelve difícil cuando las cosas evolucionan. Por ejemplo, cuando desea que la ruta anterior se modifique nuevamente, debe escribir una unidad adicional o seguir modificando. Un mejor método es mantener la entrada y la fecha de evaluación derivadas de la configuración separada que se puede adaptar fácilmente.
Por ejemplo, así es como corregiría el trozo de prueba.
fuente
Hay muchos conceptos posibles, hicimos algunos ejemplos para ver la diferencia
Para resumir: en general, su primera prueba codificada tiene más sentido para mí porque es simple, directo al punto, etc. Si comienza a codificar una ruta demasiadas veces, simplemente póngala en el método de configuración.
Para obtener más pruebas estructuradas futuras, iría a consultar fuentes de datos para que pueda agregar más filas de datos si necesita más situaciones de prueba.
fuente
Los marcos de prueba modernos le permiten proporcionar parámetros a su método. Aprovecharía esos:
Hay varias ventajas para esto, en mi opinión:
fuente