Quelles sont les meilleures pratiques pour nommer les classes de test unitaire et les méthodes de test?
Cela a été discuté sur SO avant, à Quelles sont les conventions de dénomination populaires pour les tests unitaires?
Je ne sais pas si c'est une très bonne approche, mais actuellement dans mes projets de test, j'ai des mappings un à un entre chaque classe de production et une classe de test, par exemple Product
et ProductTest
.
Dans mes classes de test, j'ai ensuite des méthodes avec les noms des méthodes que je teste, un trait de soulignement, puis la situation et ce à quoi je m'attends, par exemple Save_ShouldThrowExceptionWithNullName()
.
unit-testing
naming-conventions
James Newton-King
la source
la source
test<MethodUnderTest>_<state>
par exempletestPop_emptyStack
google-styleguide.googlecode.com/svn/trunk/javaguide.html 5.2.3 Noms de méthode. En cas de doute, suivez Google.Réponses:
J'aime la stratégie de nommage de Roy Osherove , c'est la suivante:
[UnitOfWork_StateUnderTest_ExpectedBehavior]
Il contient toutes les informations nécessaires sur le nom de la méthode et de manière structurée.
L'unité de travail peut être aussi petite qu'une méthode unique, une classe ou aussi grande que plusieurs classes. Il doit représenter toutes les choses qui doivent être testées dans ce cas de test et qui sont sous contrôle.
Pour les assemblages, j'utilise la
.Tests
terminaison typique , qui je pense est assez répandue et la même chose pour les classes (se terminant parTests
):[NameOfTheClassUnderTestTests]
Auparavant, j'utilisais Fixture comme suffixe au lieu de Tests, mais je pense que ce dernier est plus courant, puis j'ai changé la stratégie de dénomination.
la source
UpdateManager.Update()
. Ayant cela à l'esprit, j'ai tendance à appeler mes testsWhenUpdating_State_Behaviour
ouWhenUpdating_Behaviour_State
. De cette façon, je teste une action particulière d'une classe tout en évitant de mettre un nom de méthode dans un nom de test. Mais la chose la plus importante est que je dois avoir une idée de la logique métier qui échoue quand je vois le nom d'un test qui échoueJ'aime suivre la norme de dénomination «Devrait» pour les tests tout en nommant le banc d'essai après l'unité sous test (c'est-à-dire la classe).
Pour illustrer (en utilisant C # et NUnit):
Pourquoi "Devrait" ?
Je trouve que cela oblige les rédacteurs du test à nommer le test avec une phrase du type "Devrait [être dans un état] [après / avant / quand] [l'action a lieu]"
Oui, écrire «devrait» partout devient un peu répétitif, mais comme je l'ai dit, cela oblige les écrivains à penser correctement (cela peut donc être bon pour les novices). De plus, cela donne généralement un nom de test anglais lisible.
Mise à jour :
J'ai remarqué que Jimmy Bogard est aussi un fan de 'should' et a même une bibliothèque de tests unitaires appelée Should .
Mise à jour (4 ans plus tard ...)
Pour les personnes intéressées, mon approche des tests de nommage a évolué au fil des ans. L'un des problèmes avec le modèle Should que je décris ci-dessus n'est pas facile à savoir en un coup d'œil quelle méthode est en cours de test. Pour OOP, je pense qu'il est plus logique de commencer le nom du test avec la méthode sous test. Pour une classe bien conçue, cela devrait aboutir à des noms de méthode de test lisibles. J'utilise maintenant un format similaire à
<method>_Should<expected>_When<condition>
. Évidemment, selon le contexte, vous voudrez peut-être remplacer les verbes Should / When par quelque chose de plus approprié. Exemple:Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()
la source
increasesBalanceWhenDepositIsMade()
.J'aime ce style de dénomination:
etc. Il montre clairement à un non-testeur quel est le problème.
la source
should
je préféreraiwill
doncOrdersWithNoProductsWillFail()
Will
n'est pas vraiment appropriée et ce faisant, vous dites en fait à tort au lecteur qu'en aucun cas le test échouera ... si vous utilisezWill
pour exprimer quelque chose dans le futur qui pourrait ne pas arriver, vous êtes l'utiliser de manière incorrecte alors queShould
c'est le meilleur choix ici car cela indique que vous voulez / souhaitez que quelque chose se produise mais que cela ne soit pas ou ne puisse pas, lorsque le test s'exécute, il vous indique s'il a échoué / réussi, vous ne pouvez donc pas vraiment impliquer que au préalable, c'est l'explication logique, quelle est la vôtre? pourquoi évitez-vousShould
?Kent Beck suggère:
Un appareil de test par «unité» (classe de votre programme). Les montages d'essai sont des classes elles-mêmes. Le nom du dispositif de test doit être:
Les cas de test (les méthodes de test) ont des noms comme:
Par exemple, avoir la classe suivante:
Un appareil d'essai serait:
la source
Noms de classe . Pour les noms d'appareils de test, je trouve que "Test" est assez courant dans le langage omniprésent de nombreux domaines. Par exemple, dans un domaine d'ingénierie:
StressTest
et dans un domaine cosmétique:SkinTest
. Désolé d'être en désaccord avec Kent, mais utiliser "Test" dans mes montages de test (StressTestTest
?) Est déroutant."Unité" est également beaucoup utilisé dans les domaines. Par exemple
MeasurementUnit
. Une classe est-elle appeléeMeasurementUnitTest
test de "Measurement" ou "MeasurementUnit"?Par conséquent, j'aime utiliser le préfixe "Qa" pour toutes mes classes de test. Par exemple
QaSkinTest
etQaMeasurementUnit
. Il n'est jamais confondu avec les objets de domaine, et l'utilisation d'un préfixe plutôt que d'un suffixe signifie que tous les appareils de test cohabitent visuellement (utile si vous avez des contrefaçons ou d'autres classes de support dans votre projet de test)Espaces de noms . Je travaille en C # et je garde mes classes de test dans le même espace de noms que la classe qu'ils testent. C'est plus pratique que d'avoir des espaces de noms de test séparés. Bien sûr, les classes de test sont dans un projet différent.
Noms des méthodes de test . J'aime nommer mes méthodes WhenXXX_ExpectYYY. Il rend la condition préalable claire et aide à la documentation automatisée (à la TestDox). Ceci est similaire aux conseils du blog de test de Google, mais avec plus de séparation des conditions préalables et des attentes. Par exemple:
la source
J'utilise le concept Given-When-Then . Jetez un œil à ce court article http://cakebaker.42dh.com/2009/05/28/given-when-then/ . L'article décrit ce concept en termes de BDD, mais vous pouvez également l'utiliser dans TDD sans aucune modification.
la source
Voir: http://googletesting.blogspot.com/2007/02/tott-naming-unit-tests-responsably.html
Pour les noms de méthode de test, je trouve personnellement l'utilisation de noms verbeux et auto-documentés très utile (à côté des commentaires Javadoc qui expliquent davantage ce que fait le test).
la source
Je pense que l'une des choses les plus importantes est d'être cohérent dans votre convention de nommage (et d'accord avec les autres membres de votre équipe). Souvent, je vois des tas de conventions différentes utilisées dans le même projet.
la source
J'ai récemment trouvé la convention suivante pour nommer mes tests, leurs classes et contenir des projets afin de maximiser leurs descriptifs:
Disons que je teste la
Settings
classe dans un projet dans l'MyApp.Serialization
espace de noms.Je vais d'abord créer un projet de test avec l'
MyApp.Serialization.Tests
espace de noms.Dans ce projet et bien sûr l'espace de noms, je vais créer une classe appelée
IfSettings
(enregistrée sous IfSettings.cs ).Disons que je teste la
SaveStrings()
méthode. -> Je nommerai le testCanSaveStrings()
.Lorsque je lance ce test, il affiche l'en-tête suivant:
MyApp.Serialization.Tests.IfSettings.CanSaveStrings
Je pense que cela me dit très bien ce qu'il teste.
Bien sûr, il est utile qu'en anglais le nom "Tests" soit le même que le verbe "tests".
Il n'y a pas de limite à votre créativité pour nommer les tests, de sorte que nous obtenons des titres de phrases complets pour eux.
Habituellement, les noms de test devront commencer par un verbe.
Les exemples comprennent:
DetectsInvalidUserInput
)ThrowsOnNotFound
)WillCloseTheDatabaseAfterTheTransaction
)etc.
Une autre option consiste à utiliser "cela" au lieu de "si".
Ce dernier me permet d'économiser des touches et décrit plus exactement ce que je fais, car je ne sais pas, que le comportement testé est présent, mais je teste s'il l'est.
[ Modifier ]
Après avoir utilisé la convention de dénomination ci-dessus pendant un peu plus longtemps maintenant, j'ai constaté que le préfixe If peut prêter à confusion lorsque vous travaillez avec des interfaces. Il se trouve que la classe de test IfSerializer.cs ressemble beaucoup à l'interface ISerializer.cs dans "Open Files Tab". Cela peut devenir très ennuyeux lors de la commutation entre les tests, la classe testée et son interface. En conséquence, je choisirais maintenant That plutôt que If comme préfixe.
De plus, j'utilise maintenant - uniquement pour les méthodes de mes classes de test car cela n'est pas considéré comme la meilleure pratique ailleurs - le "_" pour séparer les mots dans mes noms de méthode de test comme dans:
Je trouve cela plus facile à lire.
[ Fin de l'édition ]
J'espère que cela donnera naissance à plus d'idées, car je considère que nommer les tests est très important car cela peut vous faire économiser beaucoup de temps qui aurait autrement été consacré à essayer de comprendre ce que font les tests (par exemple, après la reprise d'un projet après une interruption prolongée) .
la source
Dans VS + NUnit, je crée généralement des dossiers dans mon projet pour regrouper les tests fonctionnels. Ensuite, je crée des classes d'appareils de test unitaire et je les nomme d'après le type de fonctionnalité que je teste. Les méthodes [Test] sont nommées selon les lignes suivantes
Can_add_user_to_domain
:la source
Je dois ajouter que le fait de conserver vos tests dans le même package mais dans un répertoire parallèle à la source testée élimine le ballonnement du code une fois que vous êtes prêt à le déployer sans avoir à faire un tas de modèles d'exclusion.
Personnellement, j'aime les meilleures pratiques décrites dans "JUnit Pocket Guide" ... c'est difficile de battre un livre écrit par le co-auteur de JUnit!
la source
le nom du cas de test pour la classe Foo doit être FooTestCase ou quelque chose comme ça (FooIntegrationTestCase ou FooAcceptanceTestCase) - puisqu'il s'agit d'un cas de test. voir http://xunitpatterns.com/ pour quelques conventions de dénomination standard comme test, cas de test, dispositif de test, méthode de test, etc.
la source