Probando una clase de conversión

7

Tengo una clase que se encarga de realizar conversiones de / a tipos de veintitantos. Llamemos a esta clase ConvertUtils .

Para los programadores de C #: esta clase expande la clase Convert de .Net .

Se ve algo como esto:

public static class ConvertUtils {
    public static object ChangeType(object obj, Type newType) {
        if (conversionSupportedByFramework)
            return Convert.ChangeType(obj, newType);
        else
            ConvertSpecialCases(obj, newType);
    }
}

¿Cómo harías para probarlo? Supongo que necesitamos hacer una prueba de caja negra en este código.

Las dos formas en que pensamos, son:

  1. Escribiendo más de 400 pruebas unitarias: cubra todas las combinaciones desde / hasta que podamos imaginar.
  2. Escriba pruebas solo para las nuevas conversiones, las que no son compatibles con la clase Convert ; en realidad, solo se prueba la función ConvertSpecialCases() [que no es nuestro objetivo, como se indicó anteriormente]

La desventaja de la primera posibilidad es tener demasiadas pruebas, lo que prolonga el tiempo de construcción, implica mantener más código, etc.

La contra de la segunda posibilidad es no verificar completamente la responsabilidad de la clase - ¿Qué sucede si una determinada declaración if decide implementar una lógica personalizada (incorrecta), en lugar de dejar que Convert funcione? p.ej. ¿justo antes de if (conversionSupportedByFramework) alguien decide llamar a alguna lógica personalizada?

¿Qué piensas sobre este problema?

    
pregunta Berlo 23.06.2015 - 22:26

4 respuestas

4

No tiene que probar el código de .NET Framework en su caso específico, porque:

  • No puede heredar de la clase Convert , ya que esta clase es estática; incluso si pudiera hacer eso, por ejemplo, si la clase Convert no fuera estática:

  • La clase Convert no tiene métodos virtuales,

  • No hay métodos de instancia,

  • No hay métodos abstractos,

  • Usted no puede anular métodos estáticos en una clase,

  • No deberías ocultar los métodos usando la palabra clave new de todos modos (y si lo haces, el análisis de código te gritará).

La única forma en que puedes joder con la funcionalidad existente es a través de Reflexión. Si usas Reflection para jugar con las partes internas de la clase Convert , entonces sí, tienes que estudiar y probar el impacto que puede tener.

De lo contrario, solo tienes que probar el nuevo código que escribirás en tu clase personalizada.

    
respondido por el Arseni Mourzenko 24.06.2015 - 14:36
3

Esto depende de cómo se vea tu clase de conversión. Si se ve así:

  class MyConvert
  {
       public static Foo1 ToFoo1(Bar1 bar){...}
       public static Foo2 ToFoo2(Bar1 bar){...}
       public static Foo3 ToFoo3(Bar1 bar){...}
       // ...
       public static Foo1 ToFoo1(Bar2 bar){...}
       public static Foo2 ToFoo2(Bar2 bar){...}
       // ...
       public static Foo20 ToFoo20(Bar20 bar){...}
  }

debe implementar al menos una prueba (mejor dos o tres) para cada método. Y si tiene 400 métodos, necesita un pequeño múltiplo de 400 pruebas.

Sin embargo, si su clase tiene un aspecto diferente y tiene algo así como una "clase de representación interna" para todos sus objetos Bar , puede reducir el número de pruebas. Supongamos algo como esto:

  class MyConvert
  {
       public static Foo1 ToFoo1(object bar)
       {
           MyInternalObj myObj = new MyInternalObj(bar);
           return myObj.ToFoo1();
       }
       public static Foo2 ToFoo2(object bar)
       {
           MyInternalObj myObj = new MyInternalObj(bar);
           return myObj.ToFoo2();
       }
      // ...
  }

solo tendrá que escribir pruebas para el constructor de MyInternalObj para todos los tipos de objetos permitidos (al menos 20), y pruebas adicionales para los métodos ToFoo1 , ToFoo2 , ..., de MyInternalObj (también al menos 20, o un pequeño múltiplo de esos).

Sabiendo que su implementación se ve así, pero no desea acceder a MyInternalObj directamente, también puede aplicar las mismas pruebas llamando a MyConvert.ToFoo1 con 20 tipos de barras diferentes, y MyConvert.ToFooXYZ en las 20 variaciones usando la mismo tipo de "barra".

O más general: asegúrate de obtener un buen código y cobertura de sucursal de todo el código que has escrito.

    
respondido por el Doc Brown 24.06.2015 - 13:34
2

El hecho de que su clase sea una clase de conversión, el hecho de que sea estático y el hecho de que expanda una clase de marco existente son irrelevantes. Esta pregunta es una instancia de la pregunta más general de las pruebas de caja negra frente a caja blanca .

  

A falta de muy buena razón para realizar pruebas de caja blanca, todo   las pruebas deben ser caja negra .

Esto significa que su código de prueba no debe hacer suposiciones sobre los aspectos internos del sistema bajo prueba.

Esto, a su vez, significa que su código de prueba no debe asumir que su clase de conversión delegue a otra clase de conversión. (Precisamente porque puede delegar, y de nuevo quién sabe, podría no delegar). Por lo tanto, probar la interfaz pública completa de su clase de conversión es el camino a seguir.

Dicho esto, permítame agregar que, dado que está escribiendo una clase estática que amplía la funcionalidad de otra clase estática, la manera de reducir su código de prueba es absteniéndose expresamente de duplicar la funcionalidad de la clase de marco existente. Si desea una de las conversiones proporcionadas por la clase de marco, invoque la clase de marco. Si desea una de las conversiones proporcionadas por su clase, invoque su clase. No hay ninguna razón para envolver la funcionalidad de una clase de marco estático dentro de una clase personalizada estática, ni siquiera hay ningún envoltorio real, solo se pretende, ya que la funcionalidad de la clase marco todavía está disponible públicamente para cualquier pieza de código que desee para invocarlo.

    
respondido por el Mike Nakis 25.06.2015 - 12:34
0

Primero, determine si sus cambios afectarán otros métodos públicos de la clase Convert. Si lo desean, averigüe cuáles son los afectados. Ahora estás mejor equipado para tomar una decisión.

En caso de que no haya impacto en otros métodos y funcionalidades públicos, entonces solo enfócate en las cosas nuevas que agregues o en las que cambies.

Si el cambio afecta otras áreas de la clase Converter, comience a probar lo que ha agregado o cambiado, luego pruebe los métodos que sus modificaciones han afectado.

Otro consejo es que, si sus cambios afectan las características existentes, cuando pruebe las existentes, dé prioridad a las que ya está usando. Probablemente no serán un gran número.

Otra cosa a considerar es la siguiente. Para métodos que no han cambiado, use la clase original de Converter. Usa tu nuevo solo para los elementos cambiantes. Cuando esté seguro de que su nueva clase de Converter está funcionando, haga todas las modificaciones. Incluso si utiliza muchos de estos métodos de Convertidor, hacer el cambio no será demasiado difícil porque las firmas del método no cambiarán y, dado que confía en que el nuevo Convertidor esté funcionando, su software no debería tener impacto.

    
respondido por el EduardoFernandes 24.06.2015 - 05:13

Lea otras preguntas en las etiquetas