Quali sono alcune convenzioni di denominazione popolari per i test unitari? [chiuso]


204

Generale

  • Seguire gli stessi standard per tutti i test.
  • Sii chiaro su quale sia lo stato di ciascun test.
  • Sii specifico sul comportamento previsto.

Esempi

1) MethodName_StateUnderTest_ExpectedBehavior

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown() 

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown () 

Public void Sum_simpleValues_Calculated ()

Fonte: standard di denominazione per i test unitari

2) Separare ogni parola per Underscore

Public void Sum_Negative_Number_As_1st_Param_Exception_Thrown() 

Public void Sum_Negative_Number_As_2nd_Param_Exception_Thrown () 

Public void Sum_Simple_Values_Calculated ()

Altro

  • Termina i nomi dei metodi con Test
  • Inizia i nomi dei metodi con il nome della classe

Risposte:


94

Sono praticamente con te su questo uomo. Le convenzioni di denominazione che hai usato sono:

  • Chiaro su quale sia ogni stato del test.
  • Specifico sul comportamento previsto.

Cosa ti serve di più dal nome di un test?

Contrariamente alla risposta di Ray, non credo sia necessario il prefisso Test . È un codice di prova, lo sappiamo. Se è necessario eseguire questa operazione per identificare il codice, quindi si verificano problemi maggiori, il codice di test non deve essere confuso con il codice di produzione.

Per quanto riguarda la lunghezza e l'uso del trattino basso, il suo codice di prova , a chi diavolo importa? Solo tu e il tuo team lo vedrete, finché sarà leggibile e chiaro su cosa sta facendo il test, continuate! :)

Detto questo, sono ancora abbastanza nuovo nel testare e bloggare le mie avventure con esso :)


20
Leggera contraddizione "purché sia ​​leggibile e chiara" e "a chi ... importa". Beh, a tutti importa quando non è leggibile e chiaro, quindi è per questo che conta. :-)
David Victor,

1
Un argomento aggiuntivo per il prefisso. Quando stai cercando un file in IDE, puoi facilmente cercare casi di test iniziando con Teste il nome della tua classe. Se il nome della classe e il nome della classe di test sono uguali, dovremo sempre mettere in pausa e leggere il percorso di due file
QUESTO UTENTE HA BISOGNO DI AIUTO

@THISUSERNEEDSHELP Penso che il tuo punto possa essere facilmente superato avendo una buona struttura di cartelle come src / libs & src / test . So che alcuni framework di test runner richiedono un prefisso come test per l'identificazione del codice di test, quindi in quei casi non sarà evitato, ma per il resto può essere un prefisso ripetitivo non richiesto .
negrotico19

@ negrotico19 Sto pensando al caso come in IntelliJ quando tu Search Everywhere(shift shift) o Find a Class By Name(CMD O). Capisco che sarà differenziato dalla struttura delle cartelle o dalla struttura del modulo, ma quando cerchiamo qualcosa, sappiamo già cosa vogliamo cercare. Ad esempio, se sto cercando un test, voglio limitare la mia ricerca teste quindi cercare il nome, piuttosto che cercare il nome e quindi filtrare il test manualmente dagli occhi. È una piccola distinzione, ma è molto più facile "testare [nome classe]" e avere solo un pop-up e ridurre il carico mentale
QUESTO UTENTE HA BISOGNO DI AIUTO

37

Vale anche la pena leggere: Test di unità strutturanti

La struttura ha una classe di test per classe in fase di test. Non è così insolito. Ma ciò che era insolito per me era che aveva una classe nidificata per ogni metodo testato.

per esempio

using Xunit;

public class TitleizerFacts
{
    public class TheTitleizerMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void Name_AppendsTitle()
        {
            // Test code
        }
    }

    public class TheKnightifyMethod
    {
        [Fact]
        public void NullName_ReturnsDefaultTitle()
        {
            // Test code
        }

        [Fact]
        public void MaleNames_AppendsSir()
        {
            // Test code
        }

        [Fact]
        public void FemaleNames_AppendsDame()
        {
            // Test code
        }
    }
}

Ed ecco perché:

Bene, per prima cosa, è un bel modo di organizzare i test. Tutti i test (o fatti) per un metodo sono raggruppati insieme. Ad esempio, se si utilizza il collegamento CTRL + M, CTRL + O per comprimere i corpi del metodo, è possibile eseguire facilmente la scansione dei test e leggerli come una specifica per il codice.

Mi piace anche questo approccio:

MethodName_StateUnderTest_ExpectedBehavior

Quindi forse adeguati a:

StateUnderTest_ExpectedBehavior

Perché ogni test sarà già in una classe nidificata


2
Per coloro che utilizzano il test runner di Resharper in Visual Studio, hanno corretto i bug utilizzando le classi di test nidificate in 8.x. Da allora, questa è diventata di gran lunga la mia struttura preferita.
angularsen,

È importante che il nome diventi davvero lungo con l'approccio MethodName_StateUnderTest_ExpectedBehavior? Ad esempio "InitializeApiConfiguration_MissingApiKey_IllegalArgumentException". È davvero un buon nome di prova?
portfoliobuilder

28

Tendo ad usare la convenzione di MethodName_DoesWhat_WhenTheseConditionscosì per esempio:

Sum_ThrowsException_WhenNegativeNumberAs1stParam

Tuttavia, ciò che vedo molto è far sì che il nome del test segua la struttura di test unitaria di

  • Organizzare
  • atto
  • Asserire

Che segue anche la sintassi BDD / Gherkin di:

  • Dato
  • quando
  • Poi

quale sarebbe nominare la prova nel modo di: UnderTheseTestConditions_WhenIDoThis_ThenIGetThis

quindi al tuo esempio:

WhenNegativeNumberAs1stParam_Sum_ThrowsAnException

Tuttavia preferisco di gran lunga mettere prima il nome del metodo da testare, perché in seguito i test possono essere disposti in ordine alfabetico o visualizzati in ordine alfabetico nella casella a discesa dei membri in VisStudio e tutti i test per 1 metodo sono raggruppati insieme.


In ogni caso, mi piace separare le sezioni principali del nome del test con caratteri di sottolineatura, al contrario di ogni parola , perché penso che faciliti la lettura e la comprensione del test.

In altre parole, mi piace: Sum_ThrowsException_WhenNegativeNumberAs1stParammeglio di Sum_Throws_Exception_When_Negative_Number_As_1st_Param.


22

Noto i miei metodi di prova come altri metodi usando "PascalCasing" senza sottolineature o separatori. Lascio il test postfix per il metodo fuori, perché non aggiunge alcun valore. Che il metodo sia un metodo di prova è indicato dall'attributo TestMethod .

[TestMethod]
public void CanCountAllItems() {
  // Test the total count of items in collection.
}

A causa del fatto che ogni classe Test dovrebbe testare solo un'altra classe, lascio il nome della classe fuori dal nome del metodo. Il nome della classe che contiene i metodi di test è chiamato come la classe sotto test con il postfix "Test".

[TestClass]
public class SuperCollectionTests(){
    // Any test methods that test the class SuperCollection
}

Per i metodi che verificano eccezioni o azioni che non sono possibili, ho il prefisso del metodo di prova con la parola Cannot .

[TestMethod]
[ExpectedException(typeOf(ArgumentException))]
public void CannotAddSameObjectAgain() {
  // Cannot add the same object again to the collection.
}

Le mie convinzioni sui nomi si basano sull'articolo "Suggerimenti TDD: test delle convenzioni e linee guida sui nomi" di Bryan Cook. Ho trovato questo articolo molto utile.


1
+1 per il link al mio post, anche se non è necessario utilizzare un prefisso "Test" nei tuoi test. Assicurarsi che i test specificino il comportamento previsto. Ad esempio, CanRetrieveProperCountWhenAddingMultipleItems ()
bryanbcook,

2
Non mi piace perché non include il comportamento previsto
Johannes Rudolph

5

La prima serie di nomi è più leggibile per me, dal momento che CamelCasing separa le parole e le barre inferiori separano parti dello schema di denominazione.

Tendo anche a includere "Test" da qualche parte, nel nome della funzione o nello spazio dei nomi o nella classe che lo racchiude.


2
@Frank methodName = camelCase MethodName = PascalCase
Metro Puffo

@ metro-puffo: distinzione interessante, non ho mai sentito il termine usato PascalCase e lo faccio da molto tempo. Vedo solo il termine PascalCase nei circoli degli sviluppatori Microsoft, è quello che fai?
Frank Szczerba,

Storia di Pascal Casing e Camel Caring (da: Brad Abrams - blogs.msdn.com/brada/archive/2004/02/03/67024.aspx ) ... "Nel progetto iniziale del Framework abbiamo avuto centinaia di ore di dibattito sullo stile di denominazione. Per facilitare questi dibattiti abbiamo coniato una serie di termini. Con Anders Heilsberg (il designer originale di Turbo Pascal) un membro chiave del team di progettazione, non c'è da meravigliarsi che abbiamo scelto il termine Pascal Casing per lo stile dell'involucro reso popolare dal linguaggio di programmazione Pascal ".
Heliac,

-3

Fintanto che segui una singola pratica, non importa davvero. In genere, scrivo un test unitario singolo per un metodo che copre tutte le varianti di un metodo (ho metodi semplici;) e quindi scrivo set di test più complessi per i metodi che lo richiedono. La mia struttura di denominazione è quindi di solito test (un holdover da JUnit 3).


-8

Uso un prefisso "T" per testare spazi dei nomi, classi e metodi.

Cerco di essere pulito e creare cartelle che replicano gli spazi dei nomi, quindi creare una cartella di test o un progetto separato per i test e replicare la struttura di produzione per i test di base:

AProj
   Objects
      AnObj
         AProp
   Misc
      Functions
         AFunc
   Tests
      TObjects
         TAnObj
            TAnObjsAreEqualUnderCondition
      TMisc
         TFunctions
            TFuncBehavesUnderCondition

Posso facilmente vedere che qualcosa è un test, so esattamente a quale codice originale appartiene (se non riesci a risolverlo, il test è comunque troppo contorto).

Sembra proprio la convenzione di denominazione delle interfacce, (voglio dire, non ti confondi con le cose che iniziano con 'I', né lo farai con 'T').

È facile compilare con o senza i test.

In teoria è comunque buono e funziona abbastanza bene per piccoli progetti.


3
Approccio interessante Alcune persone potrebbero obiettare che il prefisso T è in conflitto con le convenzioni che usi in generici (es. Func (T1, T2, TResult)), ma a me personalmente non importa se c'è un consenso all'interno del team. I nomi sono brevi, il che rende anche le cose più leggibili.
punto

Troppo ungherese (notazione) per me. Inoltre, come dichiarato, il prefisso T viene utilizzato per parametri di tipo generico.
Danny Varod,

Sono d'accordo, la notazione ungherese è stata privata e, a causa del conflitto con parametri di tipo generico standard, in questo caso non vedo un'eccezione (come nel caso delle interfacce).
SonOfPirate,
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.