2009-01-14 9 views
9

Normalmente trato de evitar la duplicación y cumplir con el principio DRY. Sin embargo, estoy pensando en un caso como este:DRY entre producción y Constantes de código de prueba

public class Feature { 
    final static String FEATURE_LABEL = "blah"; 

    public void doSomething() { ... } 
    ... 
} 

public class FeatureTest { 
    ... 
    @Test 
    public void doSomethingShouldMakeSomethingHappen() { 
     assertEquals(Feature.FEATURE_LABEL, 
      feature.getSomethingHappens().getLabel()); 
    } 

Si el requisito es que la etiqueta sea el "bla" y alguien cambia FEATURE_LABEL a "bleh", la prueba pasará a pesar de que ya no cumple el requerimiento. ¿Es este un lugar válido para violar DRY?

Respuesta

11

Sí, utilice un literal aquí.

Citando a mí mismo de a question on literals:

literales Hardcoded debe aparecer en las pruebas unitarias para los valores de la prueba, a menos que exista tanto la reutilización de un valor dentro de una sola clase de prueba que una constante local es útil.

Las pruebas unitarias son una descripción de los valores esperados sin abstracción ni redirección. Imagínese leyendo la prueba: quiere la información literalmente frente a usted.

1

Me quedaría con la referencia por el momento.

La cosa es que si el requisito cambia que debe provocar que alguien cambie una prueba. Podría decirse que la forma correcta de cambiar la prueba es cambiarla por el nuevo valor como literal, ver que falla, cambiar la producción estática, verla pasar, luego cambiar la prueba para usar nuevamente la estática de producción y ver que aún pase.

¿Tiene sentido?

+0

Acepto que si el requisito cambia, la prueba debería cambiar. Me preocupa que la constante se pueda usar en más de un lugar y el requisito puede cambiar para un lugar, pero seguir siendo el mismo para el otro lugar. –

4

Para probar algo, cualquier cosa, una consideración importante es que las condiciones de prueba son independientes de lo que está probando. De lo contrario, sus pruebas no tienen un único y confiable significado; se transforman en alguna otra prueba cada vez que cambia el objeto bajo examen.

No es algo muy bueno.

La misma idea se aplica a las pruebas unitarias. En un contexto como el anterior, la cadena con la que está probando debe ser absolutamente independiente de lo que está dentro de la clase probada. En otras palabras, sí, puede y debería violar el principio DRY aquí.

2

Una forma diferente de expresar lo que los demás ya dijeron: Si la prueba nunca puede fallar, no tiene sentido mantenerla. Entonces esto no tendría sentido:

assertEquals(Feature.FEATURE_LABEL, Feature.FEATURE_LABEL); 

Digamos, por ejemplo, que tiene un límite para una lista. No tiene sentido probar ese límite == límite, la prueba debe tratar de poner más que elementos de límite en la lista.

OTOH, si quiere asegurarse de que las constantes se usen en el lugar correcto (es decir, debe usarse como la etiqueta de algún elemento de UI), tiene sentido utilizar la prueba utilizando la constante de cadena (en su lugar de un nuevo literal).

Dicho esto, para mis propias pruebas de IU, uso raspadores que recogen todas las cadenas visibles y comparan la cadena resultante (larga) con el contenido de un archivo. Esta es una prueba muy simple para cambios inesperados en la IU y funciona mejor para UI en HTML (descargo el HTML y lo comparo) pero el mismo patrón se puede aplicar a cualquier UI.

0

Creo que lo que tiene es bueno, y sí, es un uso válido de DRY: si este valor va a terminar en varias pruebas, no quiere cambiar varias si el valor cambia. Pero también debe agregar una prueba adicional, la que valida el valor de Feature.FEATURE_LABEL.

Este es un buen lugar para aplicar "una vez y solo dos veces": si solo tuviera una prueba única donde se probó el valor de FEATURE_LABEL, simplemente usaría la cadena literal. Solo si tiene múltiples pruebas para usarlo, comenzaré a usar la referencia (y agregaré una prueba para el valor).

Cuestiones relacionadas