Unité-test avec dépendances entre les tests
Comment faire les tests unitaires quand vous avez
- en général, certains tests unitaires
- essais plus sophistiqués vérifiant les cas de bordures, selon les cas généraux
pour donner un exemple, imaginez tester un lecteur CSV (je viens d'inventer une notation pour la démonstration),
def test_readCsv(): ...
@dependsOn(test_readCsv)
def test_readCsv_duplicateColumnName(): ...
@dependsOn(test_readCsv)
def test_readCsv_unicodeColumnName(): ...
Je m'attends à ce que les sous-tests ne soient effectués que si le test parent réussit. La raison derrière cela est que faire ces tests prend du temps. De nombreux rapports d'échec qui remontent à une seule raison ne seraient pas instructifs non plus. Bien sûr, je pourrais inclure tous les cas de bord dans le test principal, mais je me demande s'il y a une façon plus structurée de le faire.
j'ai trouvé ces questions liées mais différentes,
- Comment structurer les tests unitaires qui ont des dépendances?
- "1519220920 de Tests Unitaires, - Est-il mauvais formulaire pour avoir un test unitaire appelant d'autres tests unitaires
mise à JOUR:
j'ai trouvé TestNG qui a un grand support intégré pour les dépendances de test. Vous pouvez écrire des tests comme celui-ci,
@Test{dependsOnMethods = ("test_readCsv"))
public void test_readCsv_duplicateColumnName() {
...
}
5 réponses
personnellement, je ne m'inquiéterais pas de créer des dépendances entre les tests unitaires. Ça ressemble à une odeur de code pour moi. Quelques points:
- si un test échoue, laissez les autres ne parviennent pas à se faire une bonne idée de l'échelle du problème que le changement de code adverse a fait.
- les échecs des tests devraient être l'exception plutôt que la norme, alors pourquoi gaspiller l'effort et créer des dépendances quand la grande majorité du temps (espérons!) aucun la prestation est dérivée? Si les échecs se produisent souvent, votre problème n'est pas avec les dépendances de test unitaire, mais avec les échecs fréquents de test.
- les tests unitaires devraient être très rapides. S'ils sont lents, alors concentrez vos efforts sur l'augmentation de la vitesse de ces tests plutôt que de prévenir les échecs ultérieurs. Pour ce faire, découplez davantage votre code et utilisez l'injection de dépendances ou la moquerie.
Proboscis est une version python de TestNG (qui est une bibliothèque Java).
voir packages.python.org/proboscis /
il supporte les dépendances, p.ex.
@test(depends_on=[test_readCsv])
public void test_readCsv_duplicateColumnName() {
...
}
Je ne suis pas sûr de la langue à laquelle vous faites référence (comme vous ne le mentionnez pas spécifiquement dans votre question) mais pour quelque chose comme PHPUnit il y a une étiquette @depends qui ne lancera un test que si le test depended upon a déjà réussi.
selon la langue ou l'Unité de test que vous utilisez, il peut également y avoir quelque chose de similaire disponible
j'ai implémenté un plugin pour Nose (Python) qui ajoute le support pour les dépendances de test et la priorisation de test.
comme mentionné dans les autres réponses/commentaires, c'est souvent une mauvaise idée, mais il peut y avoir des exceptions où vous voudriez faire cela (dans mon cas, c'était la performance pour les tests d'intégration - avec une énorme surcharge pour entrer dans un État testable, minutes vs heures).
Vous pouvez le trouver ici: nosedep .
un exemple minimal est:
def test_a:
pass
@depends(before=test_a)
def test_b:
pass
pour s'assurer que test_b
est toujours exécuté avant test_a
.
conformément aux pratiques exemplaires et aux principes d'essai à l'unité, l'essai à l'unité ne devrait pas dépendre d'autres méthodes.
chaque cas d'essai doit vérifier le comportement isolé du béton.
si un test échoue, vous saurez exactement ce qui est arrivé à notre code.