unit-testing
Tests unitaires: meilleures pratiques
Recherche…
Introduction
Un test unitaire est la plus petite partie testable d'une application, comme les fonctions, les classes, les procédures, les interfaces. Le test unitaire est une méthode par laquelle des unités individuelles de code source sont testées pour déterminer si elles sont aptes à être utilisées. Les tests unitaires sont essentiellement écrits et exécutés par les développeurs de logiciels pour s’assurer que le code correspond à sa conception et à ses exigences et se comporte comme prévu.
Bonne appellation
L'importance d'une bonne dénomination peut être mieux illustrée par quelques mauvais exemples:
[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?
Les bons tests nécessitent de bons noms. Un bon test ne teste pas les méthodes, les scénarios de test ou les exigences.
Une bonne dénomination fournit également des informations sur le contexte et le comportement attendu. Dans l'idéal, lorsque le test échoue sur votre machine de génération, vous devriez être capable de décider ce qui ne va pas, sans regarder le code de test, ou encore plus dur, avec la nécessité de le déboguer.
Un bon nommage vous évite d'avoir à lire du code et à déboguer:
[Test]
public void GetOption_WithUnkownOption_ReturnsEmptyString() {...}
[Test]
public void GetOption_WithUnknownEmptyOption_ReturnsEmptyString() {...}
Pour les débutants, il peut être utile de lancer le nom du test avec EnsureThat_ ou un préfixe similaire. Commencez avec un "EnsureThat_" pour commencer à réfléchir au scénario ou à l'exigence, qui nécessite un test:
[Test]
public void EnsureThat_GetOption_WithUnkownOption_ReturnsEmptyString() {...}
[Test]
public void EnsureThat_GetOption_WithUnknownEmptyOption_ReturnsEmptyString() {...}
Le nommage est également important pour les appareils de test. Nommez le banc d'essai après la classe testée:
[TestFixture]
public class OptionsTests //tests for class Options
{
...
}
La conclusion finale est la suivante:
Une bonne dénomination conduit à de bons tests qui conduisent à une bonne conception du code de production.
Du simple au complexe
Identique à, avec les classes d'écriture - commencez par les cas simples, puis ajoutez la condition (aka tests) et l'implémentation (aka code de production) au cas par cas:
[Test]
public void EnsureThat_IsLeapYearIfDecimalMultipleOf4() {...}
[Test]
public void EnsureThat_IsNOTLeapYearIfDecimalMultipleOf100 {...}
[Test]
public void EnsureThat_IsLeapYearIfDecimalMultipleOf400 {...}
N'oubliez pas l'étape de refactoring, lorsque vous avez terminé avec les exigences - refactorisez d'abord le code, puis modifiez les tests
Une fois terminé, vous devriez avoir une documentation complète, à jour et lisible de votre classe.
Concept MakeSut
Testcode a les mêmes exigences de qualité que le code de production. MakeSut ()
- améliore la lisibilité
- peut être facilement restructuré
- soutient parfaitement l'injection de dépendance.
Voici le concept:
[Test]
public void TestSomething()
{
var sut = MakeSut();
string result = sut.Do();
Assert.AreEqual("expected result", result);
}
Le plus simple MakeSut () renvoie simplement la classe testée:
private ClassUnderTest MakeSUT()
{
return new ClassUnderTest();
}
Lorsque des dépendances sont nécessaires, elles peuvent être injectées ici:
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>();
...
}
On pourrait dire que MakeSut est juste une alternative simple aux méthodes d'installation et de démontage fournies par les frameworks Testrunner et pourrait être une meilleure solution pour la configuration et le démontage spécifiques aux tests.
Tout le monde peut décider par lui-même de la manière à utiliser. Pour moi, MakeSut () offre une meilleure lisibilité et beaucoup plus de flexibilité. Enfin, le concept est indépendant de toute structure testrunner.