unit-testing
Test unitario: best practice
Ricerca…
introduzione
Un unit test è la più piccola parte testabile di un'applicazione come funzioni, classi, procedure, interfacce. Il test delle unità è un metodo mediante il quale vengono testate singole unità del codice sorgente per determinare se sono idonee all'uso. I test unitari sono fondamentalmente scritti ed eseguiti dagli sviluppatori di software per assicurarsi che il codice soddisfi il suo design e requisiti e si comporti come previsto.
Buon nome
L'importanza di una buona denominazione può essere meglio illustrata da alcuni esempi negativi:
[Test]
Test1() {...} //Cryptic name - absolutely no information
[Test]
TestFoo() {...} //Name of the function - and where can I find the expected behaviour?
[Test]
TestTFSid567843() {...} //Huh? You want me to lookup the context in the database?
I buoni test hanno bisogno di buoni nomi. Un buon test non prova metodi, scenari di test o requisiti.
Una buona nomenclatura fornisce anche informazioni sul contesto e sul comportamento previsto. Idealmente, quando il test fallisce sulla tua macchina di compilazione, dovresti essere in grado di decidere cosa è sbagliato, senza guardare il codice di test, o ancora più difficile, avendo la necessità di eseguirne il debug.
Un buon naming risparmia tempo per leggere il codice e il debugging:
[Test]
public void GetOption_WithUnkownOption_ReturnsEmptyString() {...}
[Test]
public void GetOption_WithUnknownEmptyOption_ReturnsEmptyString() {...}
Per i principianti potrebbe essere utile iniziare il nome del test con ConfirmThat_ o un prefisso simile. Inizia con un "Garantire che" "aiuta a cominciare a pensare allo scenario o al requisito, che richiede un test:
[Test]
public void EnsureThat_GetOption_WithUnkownOption_ReturnsEmptyString() {...}
[Test]
public void EnsureThat_GetOption_WithUnknownEmptyOption_ReturnsEmptyString() {...}
La denominazione è importante anche per i dispositivi di prova. Assegna un nome al dispositivo di prova dopo la classe sottoposta a test:
[TestFixture]
public class OptionsTests //tests for class Options
{
...
}
La conclusione finale è:
Una buona nomenclatura porta a buoni test che portano a un buon design nel codice di produzione.
Dal semplice al complesso
Come con le lezioni di scrittura - inizia con i casi semplici, quindi aggiungi il requisito (ovvero i test) e l'implementazione (ovvero il codice di produzione) caso per caso:
[Test]
public void EnsureThat_IsLeapYearIfDecimalMultipleOf4() {...}
[Test]
public void EnsureThat_IsNOTLeapYearIfDecimalMultipleOf100 {...}
[Test]
public void EnsureThat_IsLeapYearIfDecimalMultipleOf400 {...}
Non dimenticare la fase di refactoring, una volta terminato con i requisiti - prima rifatta il codice, quindi rifatta i test
Al termine, dovresti avere una documentazione completa, aggiornata e leggibile della tua classe.
Concetto MakeSut
Testcode ha le stesse richieste di qualità, come il codice di produzione. MakeSut ()
- migliora la leggibilità
- può essere facilmente refactored
- supporta perfettamente l'iniezione di dipendenza.
Ecco il concetto:
[Test]
public void TestSomething()
{
var sut = MakeSut();
string result = sut.Do();
Assert.AreEqual("expected result", result);
}
Il più semplice MakeSut () restituisce solo la classe testata:
private ClassUnderTest MakeSUT()
{
return new ClassUnderTest();
}
Quando sono necessarie delle dipendenze, possono essere iniettate qui:
private ScriptHandler MakeSut(ICompiler compiler = null, ILogger logger = null, string scriptName="", string[] args = null)
{
//default dependencies can be created here
logger = logger ?? MockRepository.GenerateStub<ILogger>();
...
}
Si potrebbe dire che MakeSut è solo una semplice alternativa per i metodi di installazione e di smantellamento forniti da framework Testrunner e potrebbe rendere questi metodi un posto migliore per l'installazione e il teardown specifici del test.
Ognuno può decidere da solo, da che parte usare. MakeSut () per me offre una migliore leggibilità e molta più flessibilità. Ultimo ma non meno importante, il concetto è indipendente da qualsiasi framework di testrunner.