2009-09-02 8 views
21

Tengo una prueba de unidad llamada TestMakeAValidCall(). Prueba la aplicación de mi teléfono haciendo una llamada válida.Pruebas unitarias: ¿Es malo tener llamadas de prueba unitaria a otras pruebas de unidad?

Estoy a punto de escribir otra prueba llamada TestShowCallMessage() que debe tener una llamada válida para la prueba. ¿Es malo simplemente llamar al TestMakeAValidCall() en esa prueba?

Como referencia esta es mi prueba TestMakeAValidCall().

[TestMethod] 
    public void TestMakeAValidCall() 
    { 
     //Arrange 
     phone.InCall = false; 
     phone.CurrentNumber = ""; 
     // Stub the call to the database 
     data.Expect(x => x.GetWhiteListData()). 
      Return(FillTestObjects.GetSingleEntryWhiteList()); 
     // Get some bogus data 
     string phoneNumber = FillTestObjects.GetSingleEntryWhiteList(). 
      First().PhoneNumber; 
     // Stub th call to MakeCall() so that it looks as if a call was made. 
     phone.Expect(x => x.MakeCall(phoneNumber)). 
      WhenCalled(invocation => 
         { 
          phone.CurrentNumber = phoneNumber; 
          phone.InCall = true; 
         }); 

     //Act 
     // Select the phone number 
     deviceControlForm.SelectedNumber = phoneNumber; 
     // Press the call button to make a call. 
     deviceMediator.CallButtonPressed(); 

     //Assert 
     Assert.IsTrue(phone.InCall); 
     Assert.IsTrue(phone.CurrentNumber == phoneNumber); 
    } 
+0

Gracias por todas las excelentes respuestas. Refactoreé el código duplicado en una llamada separada. Escogí la respuesta con la mayoría de los votos. – Vaccano

Respuesta

51

Actualice la configuración de otro método y llame a ese método desde ambas pruebas. Las pruebas no deben llamar a otras pruebas.

+3

No pruebe otra prueba con la prueba –

+0

¿Alguien podría explicar cómo se vería la refabricación en este caso? –

+1

@Nakata: es difícil mostrar el código exacto para este ejemplo sin saber cómo se estructuran las dependencias, pero esta idea muestra el patrón que utilizo para poner el código de configuración en un contexto de prueba e invocarlo desde allí en múltiples pruebas. https://gist.github.com/tvanfosson/1ca6dd3bb0b796de65b0 – tvanfosson

6

Creo que es una mala idea. Desea que su prueba unitaria pruebe una cosa y una sola. En lugar de crear una llamada a través de su otra prueba, haga una llamada falsa y páselo como argumento.

11

en mi humilde opinión, se debe hacer una de las siguientes:

  • crear un método que devuelve una llamada válida, y lo utilizan por separado para ambas pruebas (no uno llamando a la otra)
  • Mock la llamada válida para ShowCallMessageTest
4

Una prueba de unidad debe probar una unidad/función de su código por definición. Hacer que llame a otras pruebas unitarias lo hace probar más de una unidad. Lo descompongo en pruebas individuales.

2

Sí, las pruebas unitarias deben ser independientes y deben tener como objetivo probar solo una cosa (o al menos un pequeño número de cosas estrechamente relacionadas). Como acotación al margen, las llamadas a data.Expect y phone.Expect en el método de prueba están creando expectativas en lugar de llamadas de código auxiliar, que pueden hacer sus pruebas frágiles si refactoriza ...

+0

Gracias por la corrección en mi terminología. He actualizado los comentarios en mi Código fuente. – Vaccano

6

de ofrecer un punto de venta libre:

Creo firmemente que la prueba de unidad bien diseñada debe depende uno del otro!

Por supuesto, eso solo tiene sentido si el marco de prueba es consciente de estas dependencias de manera que puede dejar de ejecutar la prueba dependiente cuando falla una dependencia. Aún mejor, un marco de este tipo puede pasar el dispositivo de una prueba a otra, de modo que pueda basarse en un dispositivo que crece y se extiende en lugar de reconstruirlo desde cero para cada prueba individual. Por supuesto, el almacenamiento en caché se realiza para tener cuidado. No se introducen efectos secundarios cuando más de una prueba depende del mismo ejemplo.

Implementamos esta idea en el JExample extension for JUnit. Todavía no hay un puerto C#, aunque hay puertos para Ruby y Smalltalk y ... el most recent release of PHPUnit picked up both our ideas: dependencies and fixture reuse.

PS: folks are also using it for Groovy.

+0

Un punto interesante, si se hace correctamente, podría reducir mucho la duplicación. –

1

Unidad contra módulo ... también creemos que las pruebas también deben depender de métodos reutilizables y deben probarse en una prueba de nivel de API para la integración de clases. Muchos simplemente prueban una sola clase pero muchos errores están en esa integración entre el nivel de clase. También usamos verifydesign para garantizar que la API no dependa de la implementación. Esto le permite refactorizar todo el componente/módulo sin tocar una prueba (y lo revisamos una vez y funcionó muy bien).Por supuesto, cualquier cambio arquitectónico lo forzará a refactorizar las pruebas, pero al menos los cambios de diseño en el módulo no causan trabajo de refactorización de prueba (a menos que cambie el comportamiento de la API, por supuesto, implícitamente, como disparar más eventos de lo que solía hacerlo, pero eso " "Sería un cambio de API de todos modos".