In TDD dovrei scrivere prima Test o Interface prima?


23

Sto imparando TDD usando c #, per quanto ne so il test dovrebbe guidare lo sviluppo , ovvero scrivere prima un test fallito dopo aver scritto il codice minimo per passare il test, quindi eseguire il refactoring.

Ma si dice anche che " Programma per l'interfaccia, non implementazione ", quindi scrivere prima un'interfaccia . È qui che inizia la mia confusione, se sto scrivendo prima Interface, allora sta violando due cose

  1. Il codice scritto per l'interfaccia non è guidato dal test .

  2. Ovviamente non è il minimo indispensabile, posso scriverlo con una semplice classe.

Dovrei iniziare scrivendo anche test per l'interfaccia? senza alcuna implementazione che cosa ho intenzione di testare?

Se questa domanda sembra sciocca per quello, ma sono assolutamente confuso. Forse sto prendendo le cose troppo alla lettera.


8
"Programma su un'interfaccia" significa separare ciò di cui hai bisogno da un pezzo di codice da come viene fatto. Non significa letteralmente usare un interfaceper tutto. A classfornisce anche un'interfaccia, perché è possibile nascondere i dettagli di implementazione in privatevariabili.
Doval,

@Doval, Sì, non hai bisogno di un'interfaccia per tutto, solo quello che viene chiamato a contract. Questo potrebbe essere sotto forma di una classe astratta, ad esempio, anche se non dovrebbe essere una classe / metodo virtuale perché non dovresti essere in grado di istanziarlo.
trysis

2
TDD dice "scrivi un test che fallisce". Alcuni TDD rigorosi affermano che viene considerato "non riuscito" se non è possibile compilare il test perché il tipo di dati su cui opera non è stato ancora dichiarato.
Solomon Slow,

Risposte:


29

La tua prima violazione ("Il codice scritto per l'interfaccia non è guidata dal test.") Non è valida. Facciamo un esempio banale. Supponiamo di scrivere una classe di calcolatrice e di scrivere un'operazione di aggiunta. Quale test potresti scrivere?

public class CalculatorTest {
    @Test
    public void testAddTwoIntegers() {
        Calculator calc = new Calculator();
        int result = calc.add(2, 2)
        Assert.assertEquals(4, result);
    }
}

Il tuo test ha appena definito l'interfaccia. È il addmetodo, vedi? addaccetta due argomenti e restituisce la loro somma. È possibile in seguito determinare che sono necessari più calcolatori ed estrarre un'interfaccia Java (in questo caso) in quel momento. I tuoi test non dovrebbero cambiare allora, dal momento che hai testato l' interfaccia pubblica di quella classe.

A un livello più teorico, i test sono le specifiche eseguibili per un sistema. Le interfacce verso un sistema dovrebbero essere guidate dagli utenti di quel sistema e i test sono il primo metodo che devi definire per interagire.

Non penso che tu possa separare il design dell'interfaccia dal design del test. Definire le interazioni e progettare i test per loro sono la stessa operazione mentale: quando invio queste informazioni in un'interfaccia, mi aspetto un certo risultato. Quando qualcosa non va nel mio input, mi aspetto questo errore. Puoi fare questo lavoro di progettazione su carta e quindi scrivere i tuoi test da quello, oppure puoi farli allo stesso tempo - non importa.


2
+1 " Non credo che tu possa separare il design dell'interfaccia dal test design " dovrebbe essere in grassetto, IMHO :)
Binary Worrier,

È ancora più facile mostrarlo, se vuoi testare più di un'implementazione di una funzionalità, dice un'importazione XML e un'importazione CSV, puoi testarle esattamente con lo stesso metodo dalla stessa interfaccia sebbene l'implementazione cambierà. Inoltre, i test comportano spesso alcune derisioni e per questa interfaccia sono necessari.
Walfrat,

Dici che il test non deve cambiare, ma new Calculator()l'implementazione è corretta? Se è necessaria una nuova implementazione, forse dovresti fare un MultiplicationCalculator e avresti bisogno di cambiare il test per usarlo new AdditionCalculator()ancora? Oppure mi sfugge qualcosa ?
Steve Chamaillard,

3
@SteveChamaillard Certo, se il tuo progetto ti ha cambiato il nome della classe da Calcolatrice a AdditionCalculator, il test dovrebbe cambiare per corrispondere. Naturalmente, facendo TDD ciò che realmente accadrebbe è che cambieresti prima il test, e il cambio di classe seguirà per far passare il test.
Eric King,

5

Cosa stiamo facendo quando scriviamo un interface? Stiamo scrivendo codice o stiamo progettando?

Non sono un fan del concetto di Test Driven Design, ma adoro Test Driven Development . Personalmente, ho ottenuto i miei migliori risultati quando ho progettato la classe in anticipo progettando l'interfaccia prima di scrivere un test. Non considero l'interfaccia come codice. L'interfaccia è un progetto che implementerò usando TDD. È probabile che cambi un evolversi mentre lavoro, ma è la mia tabella di marcia (insieme al mio elenco di test).

Mi fermerò prima di iniziare a urlare, ma spero che sia un modo utile per pensarci.


4

In TDD dovrei scrivere prima Test o Interface prima?

Tutto dipende da quanto ortodosso / religioso vuoi fare TDD .

Sto imparando TDD

Poiché stai imparando, dovresti sperimentare per ottenere un flusso di lavoro personale, che funzioni per te.

  1. Se vuoi farlo secondo i libri , scrivi all'inizio un test, che ovviamente fallirà, perché stai iniziando senza alcun codice. Quindi scrivi del codice per far passare il test. In questo caso, sei libero di refactificare il codice esistente, dal momento che hai un test che fornisce una sorta di rete di sicurezza per i refactoring. Decidere di utilizzare un interfaccia è una sorta di refactoring.

  2. Oltre a TDD o meno: la domanda se utilizzare un'interfaccia o meno non è interessante in primo luogo. Naturalmente se sei sicuro di avere un comportamento diverso che vuoi diffondere su più oggetti, ha senso pensare a usare un'interfaccia: ad esempio, se hai un qualche tipo di output verso destinazioni diverse, ha senso implementarlo tramite un writer di interfaccia e hanno classi diverse per l'output ( FileWriter , Printer ecc.). Anche se è un detto comune scrivere a un'interfaccia , ma ciò non significa: utilizzare un'interfaccia per tutto . A volte è un livello di riferimento indiretto a molto. Btw. lo stesso vale per i servizi. Ma questo è un argomento diverso.

  3. D'altra parte, è possibile sviluppare test guidati in un altro modo: progettare il codice per verificabilità. Il che significa, si scrive il codice, che è facile da prova - anche se si scrivono i test in seguito . Non importa se si scrivono test prima o dopo, purché si eseguano comunque test.


5
Non posso essere d'accordo con l'ultimo punto "Non importa se scrivi i test prima o dopo, purché esegui comunque i test". Se ti capita di scrivere il test in seguito, non puoi essere sicuro che il test stia testando la cosa giusta.
k4vin,

4
Come ho detto ... Dipende da quanto sei ortodosso ...
Thomas Junk,

2

TDD o BDD significherebbe fare prima le interfacce del tuo dominio e poi scrivere test contro di loro secondo la mia interpretazione. l'implementazione di un'interfaccia ha un comportamento previsto.

è ancora testato prima del codice perché un'interfaccia non contiene logica testabile, è la struttura contro cui si scrive un test.

Lo farei come segue

  1. Scrivi il comportamento semi formale (dato: quando: allora :)

  2. Scrivi l'interfaccia (per ospitare il metodo di incapsulamento del comportamento)

  3. Scrivi il test che identifica (inserisci il dato, chiama il quando, prova il allora)

  4. Scrivi / modifica il calcestruzzo (classe che implementa l'interfaccia) per superare il test


0

Non scrivere mai test prima di aver progettato le interfacce. Quando stai pensando a quali tipi di test scrivere (design del test) non dovresti anche progettare (progettare) contemporaneamente la tua applicazione. Non pensare a due cose contemporaneamente. Hai sentito della separazione delle preoccupazioni? Si applica non solo alla struttura fisica del codice ma anche al processo di pensiero.

Decidi come progettare prima l'applicazione. Ciò significa che progettate le vostre interfacce e le relazioni tra queste interfacce. Fino a quando non l'avrai fatto, non dovresti iniziare a pensare ai test. Una volta che sai quali sono le tue interfacce, puoi prima crearle e poi scrivere test su di esse o scrivere prima test e poi crearli. In quest'ultimo caso ovviamente non sarai in grado di compilare i test. Non vedo alcun danno né violazione della filosofia TDD nella creazione delle interfacce prima dei test.


il ragionamento nella risposta migliore sembra più convincente: "Non penso che tu possa separare il design dell'interfaccia dal design del test. Definire le interazioni e progettare i test per loro sono la stessa operazione mentale - quando invio queste informazioni in un'interfaccia, mi aspetto un certo risultato . Quando qualcosa non va con il mio ingresso, mi aspetto che questo errore ..."
moscerino

@gnat Credo che Nissam qui si riferisca alla interfaceparola chiave C # , non al termine generale "interfaccia".
RubberDuck,

@RubberDuck Anche io la penso così e credo che questo sia un approccio scadente. "Fino a quando non l'avrai fatto, non dovresti iniziare a pensare ai test ..." Come ho scritto, il ragionamento nella risposta migliore sembra più avvincente, sia nel senso generale dell'interfaccia che nel senso della parola chiave concreta
moscerino del

Abbastanza giusto @gnat che non era chiaro dal tuo commento. Personalmente, sono d'accordo con Nissam qui. Trovo che impedisce alle persone di usare TDD come scusa per non progettare affatto. YMMV.
RubberDuck,

-2

Va bene scrivere l'interfaccia / codice / test contemporaneamente purché la loro incorporazione nel progetto sia atomica.

A meno che il tuo capo non sia religioso su TDD, nel qual caso probabilmente dovrai scrivere un'interfaccia vuota -> test -> codice minimo (passaggio inutile) -> più test -> più codice inutile -> più test -> infine scrivi il vero codice - > fatto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.