visual unitarias unit test studio pruebas hacer ejemplo como unit-testing testing

unit-testing - unitarias - unit test c# ejemplo



Unidad que prueba un método que llama a otro método (12)

¿Cuál es la mejor manera de probar un método unitario que llama a varios métodos, por ejemplo:

modify(string value) { if(value.Length > 5) replaceit(value); else changeit(value); }

Este pseudo código tiene un método de modificación que (actualmente) llama a replaceit() o changeit() . Ya he escrito pruebas para replaceit y changeit , por lo que escribir una nueva prueba para modificar será del 99% el mismo conjunto de código. Necesito probarlo porque puede cambiar en el futuro.

Entonces, ¿copio y pego el código de prueba existente? Mueva el código de prueba a una función común? ¿Alguna otra idea? No estoy seguro de la mejor práctica aquí.


¿Cuál es "el código de prueba" en este caso? Configurar y verificar los resultados? Si es así, lo refactorizaría en un método diferente y lo usaría de cada una de las pruebas. Solo haría esto si hubiera una cantidad significativa de esto: hay un beneficio de legibilidad al poder ver todo lo que hace una prueba, simplemente leyendo el código de ese método.

Los métodos de prueba complicados a menudo me molestan para comenzar, para ser honesto, a menudo no pueden evitarse de manera realista, pero si puede simplificarlos, vale la pena hacerlo.


Al probar condiciones de contorno como if (value.length > 5) , debe asegurarse de que los datos de prueba contengan valores de value que tengan una longitud de 4 , 5 o 6 .


Básicamente necesitas 2 pruebas.

1) Pasa una cuerda como "The Quick Brown Fox Jumps!" (longitud mayor que cinco) asegura que el valor se ve afectado por replaceit(...)

2) Pase una cuerda como "Foo" (la longitud es menos de cinco) y asegúrese de que el valor se vea afectado por el changeit(...)

Su prueba (en pseudo código) podría verse así:

testLongValue() { string testValue = "A value longer than 5 chars"; string expected = "Replaced!"; string actual = modify(testValue); assertEqual(expected, actual); } testShortValue() { string testValue = "len4"; string expected = "Changed!"; string actual = modify(testValue); assertEqual(expected, actual); }

Obviamente, podría darte un ejemplo más realista si supiera lo que se supone que deben hacer replacit () y changeit (), pero esto debería darte la idea. Si muta la referencia del valor original en lugar de devolverlo, puede usar testValue como el valor real después de que se produce la llamada.


Bueno, no, tu código de prueba no va a ser el 99% igual, porque en realidad estás probando algo diferente aquí, a menos que replaceit, changeit y modify all devuelvan los mismos valores.

No estoy seguro de por qué la dificultad. La prueba para el método de modificación debe tener aproximadamente cuatro líneas de longitud. Como ya está probando la funcionalidad subyacente y todo lo que quiere hacer es asegurarse de que este método en particular no se rompa, escribir una prueba que pruebe las dos posibles rutas de código en esta función, los valores de retorno esperados deberían ser suficientes.


En orden de preferencia

  1. modify (test) solo tiene 2 escenarios (cada brazo del if stmt), así que escribiría 2 pruebas para modificar el formulario.
    Si el resultado esperado de replaceit (valor) es fácil de determinar ...

.

public TestModifyIfValueLength..() { string expectedValue = .. ;// literal result of replaceit(value) Assert.Equals( expectedValue, modify("asd") ); }

  1. De lo contrario, considere usar un stub (use la subclase y anule el changeit, replaceit) para verificar que se haya llamado al método correcto.
  2. Si el talón es demasiado trabajo, haz lo que se burla. Extraiga una interfaz y configure las expectativas en changeit, replaceit.

Suposiciones

  • Usted tiene pruebas para replaceit (value) y changeit (value), que prueban (p. Ej., Todas las condiciones de frontera para) esos 2 métodos de forma exhaustiva.
  • replaceit () y changeit () son métodos públicos. De lo contrario, debería considerar escribir pruebas solo contra los métodos públicos. Debes tener la libertad de modificar / eliminar métodos privados sin que el código de prueba lo sepa.

Este es un escenario clásico de prueba basado en el comportamiento frente a basado en el comportamiento.

En este ejemplo ridículamente simple, probar la salida está bien. En algún momento, sin embargo, se encontrará con pruebas en las que inspeccionar el estado después de la ejecución es complicado. En su lugar, desea verificar el comportamiento (por ejemplo, verificar que se haya llamado a changeit con un valor específico).

En ese momento, es probable que deba buscar en un marco de objeto falso como Rhino.Mocks (.Net) o Mockito (Java) y comenzar a escribir más código basado en la interfaz.


Igual que Justin Standard, además de pasar null como valor (lo que obviamente fallará para el fragmento de código que nos proporciona;)) La regla básica para la prueba de unidades es "probar solo lo que es específico para el método bajo prueba". Y es bastante ... raro tener un método que no llame a otro.


Puede crear un func de los métodos y burlarse de esos funcs. O bien, puede crear un método virtual y usar el simulacro de Rhino: simulacro parcial, puede simular esos métodos virtuales.


Si ya escribió pruebas para replaceit () y changeit (), la prueba de modificación simplemente verificaría que se devuelvan resultados diferentes según el valor de ''valor''. Sin embargo, simplemente volverás a aplicar la lógica del método en la prueba, lo cual es un poco absurdo.

En este caso, no modificaría la prueba hasta que tenga una lógica más compleja, o mejor, es utilizada por otro método que es más significativo de probar.


Si ya ha probado replaceit() y changeit() independiente, entonces lo único que le queda por probar es la condición if. Pruebe modify() con algunos valores para asegurarse de que llama a la función correcta en las condiciones correctas (esas condiciones son null y las Strings de longitud 4, 5 y 6 para el código de ejemplo que proporcionó).


Solo prueba modify .

Se supone que la Modify devuelve ciertos valores cuando se le dan ciertos valores.

No importa cómo modificar su trabajo, solo que hace su trabajo.

Y si, en el futuro, cambias, modify para usar diferentes métodos (o ningún método), no afecta, no debe, y no afectará tus pruebas.

Dicho esto, también prueba replaceit'' and changeit`.


Tienes un número de opciones. Cuál es el mejor depende de detalles que no están claros en su pregunta.

  • prueba modify como si fuera un método no relacionado. Ventaja: en algún momento podría convertirse en uno.
  • simplemente prueba que tienes la declaración if correcta. Es decir, simplemente pruebe lo suficiente como para que las pruebas lo obliguen a escribir la implementación que necesita (cuando llamar a replaceit y changeit es la implementación más simple que podría funcionar . Si está practicando TDD, esto debería ser algo natural para usted. Ventaja: prueba alta cobertura sin mucho esfuerzo duplicado.
  • Método de subclase y sustitución (esta es una técnica de interrupción de dependencia del libro "Trabajar eficazmente con código heredado"): pruebe el método en una subclase que introduzca únicamente con fines de prueba, que anula el reemplazo y changeit con respuestas changeit o de manera que establezcan variables de detección (variables que indican si el método ha sido llamado con el (los) valor (es) correcto (s)). Ventaja: posiblemente pueda simplificar sus pruebas (o no), a veces incluso hacer las pruebas posibles.
  • Extraiga una nueva clase para los métodos replaceit y changeit , incluida una interfaz para esa clase. Stub o Mock esa interfaz cuando se prueba modify . Ventaja: ambos pueden hacer que su diseño sea más comprobable y mejor desacoplado / reutilizable en general (o no).