Domanda

Quali sono le migliori pratiche per la denominazione di classi di test unit e metodi di test?

Questo è stato discusso in precedenza su SO, a Quali sono alcune convenzioni di denominazione popolari per i test unitari?

Non so se si tratta di un approccio molto valido, ma attualmente nei miei progetti di test ho mappature one-to-one tra ciascuna classe di produzione e una classe di test, ad es. Product e ProductTest.

Nelle mie classi di test ho quindi metodi con i nomi dei metodi che sto testando, un carattere di sottolineatura, quindi la situazione e ciò che mi aspetto che accada, ad es. Save_ShouldThrowExceptionWithNullName().

È stato utile?

Soluzione

Mi piace La strategia di denominazione di Roy Osherove , è il seguente:

[UnitOfWork_StateUnderTest_ExpectedBehavior]

Ha tutte le informazioni necessarie sul nome del metodo e in modo strutturato.

L'unità di lavoro può essere piccola come un singolo metodo, una classe o grande come più classi. Dovrebbe rappresentare tutte le cose che devono essere testate in questo caso di test e che sono sotto controllo.

Per gli assiemi uso il tipico .Tests finale, che penso sia abbastanza diffuso e lo stesso per le classi (che termina con Tests):

[NameOfTheClassUnderTestTests]

Precedentemente ho usato Fixture come suffisso invece di Test ma penso che quest'ultimo sia più comune, quindi ho cambiato la strategia di denominazione.

Altri suggerimenti

Mi piace seguire il " Dovrebbe " standard di denominazione per test mentre nomina il dispositivo di prova dopo l'unità sottoposta a test (ovvero la classe).

Per illustrare (usando C # e NUnit):

[TestFixture]
public class BankAccountTests
{
  [Test]
  public void Should_Increase_Balance_When_Deposit_Is_Made()
  {
     var bankAccount = new BankAccount();
     bankAccount.Deposit(100);
     Assert.That(bankAccount.Balance, Is.EqualTo(100));
  }
}

Perché " Dovrebbe " ?

Trovo che costringe gli autori del test a nominare il test con una frase lungo le righe di " Dovrebbe [essere in qualche stato] [dopo / prima / quando] [l'azione ha luogo] " ;

Sì, scrivendo " Dovrebbe " ovunque diventa un po 'ripetitivo, ma come ho detto costringe gli scrittori a pensare nel modo corretto (quindi può essere buono per i principianti). Inoltre, in genere si ottiene un nome test inglese leggibile.

Aggiorna :

Ho notato che Jimmy Bogard è anche un fan di 'should' e ha persino una libreria di test unitari chiamata dovrebbe .

Aggiornamento (4 anni dopo ...)

Per gli interessati, il mio approccio ai test di denominazione si è evoluto nel corso degli anni. Uno dei problemi con il modello Dovrebbe che descrivo sopra come non sia facile sapere a colpo d'occhio quale metodo è in fase di test. Per OOP penso che abbia più senso iniziare il nome del test con il metodo in esame. Per una classe ben progettata ciò dovrebbe tradursi in nomi di metodi di prova leggibili. Ora uso un formato simile a <method>_Should<expected>_When<condition>. Ovviamente, a seconda del contesto, potresti voler sostituire i verbi Should / When con qualcosa di più appropriato. Esempio: Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()

Mi piace questo stile di denominazione:

OrdersShouldBeCreated();
OrdersWithNoProductsShouldFail();

e così via. Rende davvero chiaro a un non tester quale sia il problema.

Kent Beck suggerisce:

  • Un dispositivo di prova per 'unità' (classe del programma). Le apparecchiature di prova sono le classi stesse. Il nome del dispositivo di prova dovrebbe essere:

    [name of your 'unit']Tests
    
  • I casi di test (i metodi del dispositivo di test) hanno nomi come:

    test[feature being tested]
    

Ad esempio, con la seguente classe:

class Person {
    int calculateAge() { ... }

    // other methods and properties
}

Un dispositivo di prova sarebbe:

class PersonTests {

    testAgeCalculationWithNoBirthDate() { ... }

    // or

    testCalculateAge() { ... }
}

Nomi delle classi . Per i nomi dei dispositivi di prova, trovo che & Quot; Test & Quot; è abbastanza comune nel linguaggio onnipresente di molti domini. Ad esempio, in un dominio di ingegneria: StressTest e in un dominio di cosmetici: SkinTest. Mi dispiace non essere d'accordo con Kent, ma usando & Quot; Test & Quot; nelle mie prove (StressTestTest?) è confuso.

&

quot; Unità quot &; è anche molto usato nei domini. Per esempio. MeasurementUnit. Una classe chiamata MeasurementUnitTest è una prova di & Quot; Misura & Quot; oppure " MeasurementUnit " ;?

Quindi mi piace usare il " Qa " prefisso per tutte le mie classi di test. Per esempio. QaSkinTest e QaMeasurementUnit. Non viene mai confuso con gli oggetti di dominio e l'utilizzo di un prefisso anziché di un suffisso significa che tutte le apparecchiature di test convivono visivamente (utile se nel progetto di test sono presenti falsi o altre classi di supporto)

namespace . Lavoro in C # e mantengo le mie classi di test nello stesso spazio dei nomi della classe che stanno testando. È più conveniente che avere spazi dei nomi di prova separati. Naturalmente, le classi di test fanno parte di un progetto diverso.

Nomi dei metodi di prova . Mi piace nominare i miei metodi WhenXXX_ExpectYYY. Rende chiara la precondizione e aiuta con la documentazione automatizzata (alla TestDox). Questo è simile ai consigli sul blog di test di Google, ma con una maggiore separazione dei presupposti e delle aspettative. Ad esempio:

WhenDivisorIsNonZero_ExpectDivisionResult
WhenDivisorIsZero_ExpectError
WhenInventoryIsBelowOrderQty_ExpectBackOrder
WhenInventoryIsAboveOrderQty_ExpectReducedInventory

Uso il concetto Dato-Quando-Allora . Dai un'occhiata a questo breve articolo http://cakebaker.42dh.com / 2009/05/28 / data-quando-allora / . L'articolo descrive questo concetto in termini di BDD, ma è possibile utilizzarlo anche in TDD senza modifiche.

Vedi: http://googletesting.blogspot.com/2007/02 /tott-naming-unit-tests-responsibly.html

Per i nomi dei metodi di prova, trovo personalmente molto utile l'uso di nomi dettagliati e autocompattati (insieme ai commenti Javadoc che spiegano ulteriormente cosa sta facendo il test).

Penso che una delle cose più importanti sia coerente nella tua convenzione di nomina (e d'accordo con gli altri membri del tuo team). Molte volte vedo un sacco di convenzioni diverse utilizzate nello stesso progetto.

Di recente ho escogitato la seguente convenzione per nominare i miei test, le loro classi e contenere i progetti al fine di massimizzarne le descrizioni:

Diciamo che sto testando la classe Impostazioni in un progetto nello spazio dei nomi MyApp.Serialization .

Per prima cosa creerò un progetto di test con lo spazio dei nomi MyApp.Serialization.Tests .

All'interno di questo progetto e ovviamente lo spazio dei nomi creerò una classe chiamata IfSettings (salvata come IfSettings.cs).

Diciamo che sto testando il metodo SaveStrings () . - gt &; Chiamerò il test CanSaveStrings () .

Quando eseguo questo test mostrerà la seguente intestazione:

MyApp.Serialization.Tests.IfSettings.CanSaveStrings

Penso che questo mi dica molto bene, cosa sta testando.

Naturalmente è utile che in inglese il sostantivo " Test " è lo stesso del verbo " test " ;.

Non c'è limite alla tua creatività nel nominare i test, in modo da ottenere titoli completi per loro.

Di solito i Testnames dovranno iniziare con un verbo.

Gli esempi includono:

  • Detects (ad esempio DetectsInvalidUserInput)
  • Lanci (ad esempio ThrowsOnNotFound)
  • Will (ad es. WillCloseTheDatabaseAfterTheTransaction)

ecc.

Un'altra opzione è quella di utilizzare " che " anziché " se " ;.

Quest'ultimo però mi salva la pressione dei tasti e descrive più esattamente ciò che sto facendo, poiché non so, che è presente il comportamento testato, ma sto testando < strong> se lo è.

[ Modifica ]

Dopo aver usato la convenzione di denominazione sopra per un po 'più a lungo, ho scoperto che il prefisso If può essere fonte di confusione, quando si lavora con le interfacce. Accade semplicemente che la classe di test IfSerializer.cs sia molto simile all'interfaccia ISerializer.cs nella & Quot; Apri la scheda File & Quot; . Questo può diventare molto fastidioso quando si passa avanti e indietro tra i test, la classe da testare e la sua interfaccia. Di conseguenza ora sceglierei Quello su Se come prefisso.

Inoltre ora uso - solo per i metodi nelle mie classi di test in quanto non è considerata la migliore pratica altrove - il " _ " per separare le parole nei nomi dei miei metodi di prova come in:

  • [Test] public void detects_invalid_User_Input () *

Trovo che sia più facile da leggere.

[ Fine modifica ]

Spero che questo generi altre idee, dal momento che considero test di denominazione di grande importanza in quanto può farti risparmiare un sacco di tempo che altrimenti sarebbe stato speso cercando di capire cosa stanno facendo i test (ad esempio dopo aver ripreso un progetto dopo un iato prolungato).

In VS + NUnit di solito creo cartelle nel mio progetto per raggruppare test funzionali. Quindi creo le classi di dispositivi di unit test e le denomino in base al tipo di funzionalità che sto testando. I metodi [Test] sono denominati lungo le linee di Can_add_user_to_domain:

- MyUnitTestProject   
  + FTPServerTests <- Folder
   + UserManagerTests <- Test Fixture Class
     - Can_add_user_to_domain  <- Test methods
     - Can_delete_user_from_domain
     - Can_reset_password

Dovrei aggiungere che il mantenimento dei test nello stesso pacchetto, ma in una directory parallela al sorgente in fase di test, elimina il gonfiore del codice una volta che sei pronto a distribuirlo senza dover fare un mucchio di schemi di esclusione.

Personalmente mi piacciono le migliori pratiche descritte in " JUnit Pocket Guide " ... è difficile battere un libro scritto dal coautore di JUnit!

il nome del test case per la classe Foo dovrebbe essere FooTestCase o qualcosa del genere (FooIntegrationTestCase o FooAcceptanceTestCase), poiché si tratta di un caso di test. vedi http://xunitpatterns.com/ per alcune convenzioni di denominazione standard come test, test case, test fixture, test method , ecc.

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