Pour donner un exemple légèrement artificiel, disons que je veux tester qu'une fonction renvoie deux nombres et que le premier est plus petit que le second:
def test_length():
result = my_function()
assert len(result) == 2
def test_order()
a, b = my_function()
assert a < b
Ici, en cas d' test_length
échec, test_order
échouera également. Est-ce une meilleure pratique d'écrire test_length
ou de l'ignorer?
EDIT: notez que dans cette situation, les deux tests sont pour la plupart indépendants l'un de l'autre, chacun peut être exécuté de manière isolée, ou ils peuvent être exécutés dans l'ordre inverse, cela n'a pas d'importance. Donc, aucune de ces anciennes questions
- Comment dois-je tester la fonctionnalité d'une fonction qui utilise d'autres fonctions en elle?
- Ai-je besoin d'un test unitaire si j'ai déjà un test d'intégration?
- Comment structurer les tests où un test est la configuration d'un autre test?
- Comment gérer la dépendance du succès entre les tests unitaires
est un double de celui ci-dessus.
unit-testing
Mihai
la source
la source
A
appelsB
et renvoie le même résultat, si vous testez les deuxA
etB
". Il s'agit plus du chevauchement des tests que des fonctions testées. (Bien que ce soit déroutant car ils sont actuellement nommés).lambda: type('', (), {'__len__': lambda self: 2})()
passera la première, mais pas la seconde.Réponses:
Il peut y avoir de la valeur, mais c'est un peu l'odeur. Soit vos tests ne sont pas bien isolés (car ils
test_order
testent vraiment deux choses), soit vous êtes trop dogmatique dans vos tests (faire de deux tests tester la même chose logique).Dans l'exemple, je fusionnerais les deux tests ensemble. Oui, cela signifie que vous avez plusieurs assertions. Dommage. Vous testez toujours une seule chose - le résultat de la fonction. Parfois, dans le monde réel, cela signifie faire deux vérifications.
la source
my_function
ne renvoie pas exactement deux valeurs, sans assertion - car l'affectation entraînera une exception. Il n'est donc pas nécessaire d'utiliser plusieurs assertions et deux vérifications pour tester la même chose.Vos tests doivent être explicites. Il n'est pas complètement déduit que si text_length échoue, test_order échoue.
Je ne sais pas comment cela se passe en Python que vous avez publié, mais si
len(result)
c'est 3, le premier échouera mais le second peut passer (et sinon en Python, alors dans des langues comme JavaScript à coup sûr).Comme vous l'avez dit, vous voulez tester que la fonction retourne deux nombres et qu'ils sont en ordre. C'est deux tests.
la source
It's not completely inferred that if text_length fails test_order fails
- en Python, il est, vous donnera une exception.test_length
implique l'échec detest_order
. Le fait qu'une paire similaire de tests écrits en Javascript ne se comporterait pas de la même manière que ces deux tests python est en quelque sorte hors de propos.La seule valeur
test_length
ici est que, si tout passe, sa présence même indique que la "longueur" a été testée.Il est donc vraiment inutile d'avoir ces deux tests. Gardez seulement
test_order
mais pensez à le renommertest_length_and_order
.Soit dit en passant, je trouve l'utilisation de noms qui commencent par
test
un peu maladroite. Je suis un ardent défenseur des noms de test qui décrivent réellement la condition que vous affirmez.la source
test
verrue est significative pour le framework de test de Python. Ce qui bien sûr n'a pas besoin de changer si vous êtes fan de cela, mais change le poids des arguments nécessaires pour empêcher quelqu'un de l'utiliser ;-)test_that_
, commetest_that_return_values_are_in_order
et ainsi de suite. Peut-être qu'une future version du framework de test contournera cette exigence d'une manière ou d'une autre.Je laisserais ces tests séparés si c'est ainsi qu'ils ont évolué. Oui
test_order
est susceptible d'échouer à chaque foistest_length
, mais vous savez certainement pourquoi.Je suis également d'accord pour dire que si le
test_order
premier est apparu et que vous avez trouvé un échec testable, c'est que le résultat n'était peut-être pas deux valeurs, en ajoutant cette vérification en tant queassert
et en renommant le test pour avoir dutest_length_and_order
sens.Si vous deviez également vérifier que les types de valeurs renvoyées étaient des entiers, j'inclurais cela dans ce test de résultats "omnibus".
Mais notez maintenant que vous avez une batterie de tests pour le résultat de
my_function()
. S'il existe plusieurs contextes (ou, plus probablement, plusieurs paramètres) pour tester, cela peut maintenant être un sous-programme pour tester tous les résultatsmy_function()
.Cependant, lorsque j'écris des tests unitaires, je teste normalement le bord et les mauvais cas séparément de la bonne entrée et de la sortie normale (en partie parce que la plupart de mes tests "unitaires" sont souvent des mini tests d'intégration), et souvent avec plusieurs assertions, qui ne sont cassées que dans des tests séparés s'ils échouent d'une manière où je trouve que je veux plus d'informations sans débogage.
Donc , je ne serais probablement commencer par vos tests séparés et d' étendre
test_length
àtest_length_and_types
et laissertest_order
séparé, en supposant que celui- ci est considérée comme « traitement normal ».la source