Domanda

Di solito cerco di evitare la duplicazione e di aderire al principio DRY. Tuttavia, mi chiedo un caso come questo:

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());
    }

Se il requisito è che l'etichetta sia "blah" e qualcuno cambia FEATURE_LABEL in " bleh " ;, il test passerà anche se non soddisfa più il requisito. È un posto valido per violare il DRY?

È stato utile?

Soluzione

Sì, usa un valore letterale qui.

Citando me stesso da una domanda sui letterali :

I letterali hardcoded dovrebbero apparire nei test unitari per i valori dei test, a meno che non vi sia un così grande riutilizzo di un valore all'interno di una singola classe di test che una costante locale sia utile.

I test unitari sono una descrizione dei valori previsti senza astrazione o reindirizzamento. Immagina di leggere il test: vuoi le informazioni letteralmente di fronte a te.

Altri suggerimenti

Per testare qualcosa, qualsiasi cosa, una considerazione importante è che le condizioni del test siano indipendenti da ciò che stai testando. Altrimenti, i tuoi test non hanno un significato unico e affidabile; si trasformano in altri test ogni volta che l'oggetto in esame cambia.

Non è una cosa molto positiva.

La stessa idea si applica ai test unitari. In un contesto come sopra la stringa che stai testando dovrebbe essere assolutamente indipendente da ciò che è all'interno della classe testata. In altre parole, sì, puoi e dovresti violare il principio DRY qui.

Un modo diverso di esprimere ciò che gli altri hanno già detto: se il test non può mai fallire, non ha senso mantenerlo. Quindi questo non avrebbe senso:

assertEquals(Feature.FEATURE_LABEL, Feature.FEATURE_LABEL);

Supponiamo, ad esempio, che hai un limite per un elenco. Non ha senso testare il limite == limite, il test dovrebbe provare a inserire più di elementi limite nell'elenco.

OTOH, se vuoi assicurarti che le costanti siano usate nel posto giusto (cioè dovrebbe essere usato come etichetta di alcuni elementi dell'interfaccia utente), ha senso usare il test usando la costante di stringa (invece di un nuovo letterale).

Detto questo, per i miei test dell'interfaccia utente, uso gli scraper che raccolgono tutte le stringhe visibili e confrontano la stringa (lunga) risultante con il contenuto di un file. Questo è un test catch-all molto semplice per modifiche impreviste nell'interfaccia utente e funziona meglio per le interfacce utente in HTML (scarico l'HTML e lo confronto) ma lo stesso modello può essere applicato a qualsiasi interfaccia utente.

Vorrei attenermi al riferimento per il momento.

Il fatto è che se il requisito cambia, dovrebbe innescare qualcuno che cambia un test. Probabilmente il modo giusto per cambiare il test è cambiarlo nel nuovo valore come letterale, vederlo fallire, cambiare la statica di produzione, vederlo passare, quindi cambiare il test per usare di nuovo anche la statica di produzione e vederlo ancora passare.

Ha senso?

Penso che ciò che hai sia buono, e sì, è un uso valido di DRY: se questo valore finirà in diversi test, non vuoi cambiarne alcuni se il valore cambia. Ma dovresti anche aggiungere un test aggiuntivo, quello che convalida il valore di Feature.FEATURE_LABEL.

Questo è un buon posto per applicare " una e solo due volte " ;: se avessi un solo test in cui è stato testato il valore di FEATURE_LABEL, allora userei solo la stringa letterale. È solo se hai più test che lo utilizzano da dove inizierei a utilizzare il riferimento (e aggiungerei un test per il valore).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top