2011-12-27 2 views
6

seguo la convenzione di denominazioneEsiste un modo per proteggere i nomi dei test delle unità che seguono il metodo MethodName_Condition_ExpectedBehaviour rispetto al refactoring?

MethodName_Condition_ExpectedBehaviour

quando si tratta di nominare mie unità di test che testano metodi specifici.

ad esempio:

[TestMethod] 
public void GetCity_TakesParidId_ReturnsParis(){...} 

Ma quando ho bisogno di rinominare il metodo in prova, strumenti come ReSharper non mi offrono per rinominare questi test.

C'è un modo per impedire che tali casi vengano visualizzati dopo la ridenominazione? Come cambiare le impostazioni di ReSharper o seguire una convenzione di denominazione dei test unitaria migliore, ecc.?

+0

Com'è collegato a Java? Il tag 'java' deve essere rimosso tra i tag. Ad ogni modo, in Java (con JUnit ad esempio) se si scrive un test per un metodo specifico, non ci sarà alcuna connessione tra il test e il metodo sotto test ed Eclipse, NetBeans, ecc.non ti offrirà di rifattorizzare il nome del metodo di prova. Non posso commentare il comportamento di ReSharper. –

+0

"Cambiare il nome del metodo" è un grande caso d'uso per te? Se è .. forse puoi omettere questo cambiamento-magnete dai nomi dei test. Per esempio. [class] TestCityRepository ha il metodo di prova ShouldRetrieveCityById. In questo modo sei isolato dal nome del metodo di implementazione .. – Gishu

risposta

7

Un modello recente è quello di gruppi di test in classi interne con il metodo si prova!.

Per esempio (omettendo attributi di test):

public CityGetterTests 
{ 
    public class GetCity 
    { 
     public void TakesParidId_ReturnsParis() 
     { 
      //... 
     } 

     // More GetCity tests 
    } 
} 

Vedi Structuring Unit Tests from Phil Haack's blog per i dettagli.

La cosa bella di questo layout è che, quando il nome del metodo cambia, devi solo cambiare il nome della classe interna invece di tutti i i singoli test.

+0

Mi piace molto l'idea! A proposito, dove hai imparato a conoscere questo modello? Qualche risorsa o un articolo o ...? (Grazie!) – pencilCake

1

Ho anche iniziato con questa conversione, ma ho avuto la sensazione che non sia molto buono. Ora uso nomi in stile BDD come should_return_Paris_for_ParisID.

che rende il mio test più leggibile e alsow mi permette di refactoring nomi dei metodi, senza preoccuparsi di mio test :)

+0

Quindi non hai menzionato il nome del metodo nel nome del test unitario? – pencilCake

+0

no, questo mi consente di rinominarlo in un secondo momento senza effetti collaterali :) Penso di testare scenari, non metodi particolari –

+0

Forse la tua strada può essere collegata con un commento del tipo: Method In Test: GetCity. In modo che ReSharper offrirà di rinominare questo TESTO quando si rinomina il metodo. – pencilCake

0

Penso che la chiave qui è quello che si dovrebbe essere test.

Hai menzionato TDD nei tag, quindi spero che stiamo cercando di aderire a questo qui. In questo paradigma, i test si sta scrivendo hanno due scopi:

  1. To supporto il codice una volta che è scritto, in modo da poter refactoring senza temere che hai rotto qualcosa

  2. Per guidaci verso un modo migliore di progettare i componenti - scrivere il test prima ti costringe davvero a pensare a ciò che è necessario per risolvere il problema in questione.

So che all'inizio sembra che questa domanda riguardi il primo punto, ma in realtà penso che riguardi il secondo. Il problema che stai avendo è che hai componenti in calcestruzzo che stai testando invece di un contratto.

In termini di codice, questo significa che penso che dovremmo testeremo interfacce invece di metodi di classe, perché altrimenti esponiamo il nostro test per una serie di problemi connessi con il test componenti invece di contratti - strategie di successione, oggetto costruzione, e qui, ribattezzando.

È vero che anche i nomi delle interfacce cambiano, ma saranno molto più rigidi dei nomi dei metodi. Quello che il TDD ci offre qui non è solo un modo per supportare il cambiamento attraverso un'imbracatura di test - fornisce l'intuizione per capire che potremmo farci qualcosa nel modo sbagliato!

Prendiamo ad esempio il blocco di codice che ha dato:

[TestMethod] 
public void GetCity_TakesParidId_ReturnsParis(){...} 
{ 
    // some test logic here 
} 

E diciamo che stiamo testando il metodo GetCity() il nostro oggetto, CityObtainer - quando ho impostato questo oggetto verso l'alto? Perché l'ho fatto? Se realizzo GetMatchingCity() è un nome migliore, quindi hai il problema descritto sopra!

La soluzione che propongo è che pensiamo a ciò che questo metodo realmente significa precedenza nel processo, mediante l'uso di interfacce:

public interface ICityObtainer 
{ 
    public City GetMatchingCity(); 
} 

Scrivendo in questo "outside-in" stile di senso , siamo costretti a pensare a ciò che vogliamo dall'oggetto molto prima nel processo, e diventare l'attenzione dovrebbe ridurre la sua volatilità. Questo non elimina il tuo problema, ma potrebbe attenuarlo un po '(e, penso, è comunque un approccio migliore).

Idealmente, andiamo un passo ulteriore, e noi non hanno nemmeno scrivere alcun codice prima di iniziare la prova:

[TestMethod] 
public void GetCity_TakesParId_ReturnsParis 
{ 
    ICityObtainer cityObtainer = new CityObtainer(); 
    var result = cityObtainer.GetCity("paris"); 

    Assert.That(result.Name, Is.EqualTo("paris"); 
} 

In questo modo, posso vedere quello che veramente voglio dal componente prima ancora che inizi a scriverlo - se GetCity() non è proprio quello che voglio, ma piuttosto GetCityByID(), diventerebbe evidente molto prima nel processo. Come ho detto sopra, non è infallibile, ma potrebbe ridurre un po 'il dolore per questo particolare caso.

Una volta che hai passato attraverso questo, sento che se si sta cambiando il nome del metodo, è perché sei cambiare i termini del contratto, e che significa dovrebbe andare indietro e riconsiderare il test (poiché è possibile che tu non volessi cambiarlo).

(Come un rapido addendum, se stiamo scrivendo un test con TDD in mente, allora qualcosa sta accadendo all'interno GetCity() che ha una notevole quantità di logica in corso. Pensando alla prova come ad una contratto ci aiuta a separare l'intenzione dalla realizzazione - il test rimarrà valida non importa quello che si cambia dietro l'interfaccia)