J'écris des tests pour un projet composé de plusieurs sous-modules. Chaque cas de test que j'ai écrit s'exécute indépendamment les uns des autres et j'efface toutes les données entre les tests.
Même si les tests sont exécutés indépendamment, je songe à appliquer un ordre d'exécution, car certains cas requièrent plusieurs sous-modules. Par exemple, un sous-module génère des données et un autre exécute des requêtes sur les données. Si le sous-module générant les données contient une erreur, le test du sous-module de requête échouera également, même si le sous-module lui-même fonctionne correctement.
Je ne peux pas travailler avec des données factices, car la fonctionnalité principale que je teste est la connexion à un serveur distant Black Box, qui récupère uniquement les données du premier sous-module.
Dans ce cas, est-il correct d'appliquer un ordre d'exécution pour les tests ou est-ce une mauvaise pratique? J'ai l'impression qu'il y a une odeur dans cette configuration, mais je ne trouve pas de meilleur moyen de contourner le problème.
edit: la question est de Comment structurer des tests où un test est la configuration d'un autre test? comme le "précédent" test n'est pas une configuration, mais teste le code qui effectue la configuration.
la source
Réponses:
Ceci est la partie clé pour moi. Vous pouvez parler de "tests unitaires" et de "leur exécution indépendante", mais ils semblent tous s'appuyer sur ce serveur distant et sur le "premier sous-module". Donc, tout semble étroitement lié et dépend de l'état externe. En tant que tel, vous écrivez en fait des tests d'intégration. Il est tout à fait normal que ces tests soient exécutés dans un ordre spécifique car ils dépendent fortement de facteurs externes. Un test ordonné, avec l'option de quitter rapidement le test en cas de problème, est parfaitement acceptable pour les tests d'intégration.
Mais il serait également intéressant de jeter un regard neuf sur la structure de votre application. Le fait de pouvoir simuler le premier sous-module et le premier serveur externe vous permettrait potentiellement d’écrire de vrais tests unitaires pour tous les autres sous-modules.
la source
Oui, c'est une mauvaise pratique.
Généralement, un test unitaire est destiné à tester une seule unité de code (par exemple une seule fonction basée sur un état connu).
Lorsque vous souhaitez tester une chaîne d'événements susceptibles de se produire dans la nature, vous souhaitez un style de test différent, tel qu'un test d'intégration. Cela est encore plus vrai si vous comptez sur un service tiers.
Pour effectuer des tests unitaires comme celui-ci, vous devez trouver un moyen d'injecter les données factices, par exemple en implémentant une interface de service de données reflétant la demande Web mais renvoyant des données connues à partir d'un fichier de données factice local.
la source
L'ordre d'exécution forcée que vous proposez n'a de sens que si vous interrompez également l'exécution du test après le premier échec.
L'abandon du test lors du premier échec signifie que chaque test ne peut détecter qu'un seul problème et qu'il ne peut pas en détecter de nouveaux tant que tous les problèmes précédents n'ont pas été corrigés. Si le premier test à exécuter détecte un problème qui prend un mois à résoudre, aucun test ne sera exécuté au cours de ce mois.
Si vous n'abandonnez pas le test lors du premier échec, l'ordre d'exécution appliqué ne vous rapporte rien, car chaque test ayant échoué doit faire l'objet d'une enquête. Même si ce n'est que pour confirmer que le test sur le sous-module de requête échoue en raison de l'échec également identifié sur le sous-module générateur de données.
Le meilleur conseil que je puisse vous donner est d'écrire les tests de manière à pouvoir facilement identifier le moment où une défaillance dans une dépendance entraîne l'échec du test.
la source
L'odeur à laquelle vous faites référence est l'application du mauvais ensemble de contraintes et de règles à vos tests.
Les tests unitaires sont souvent confondus avec "test automatisé" ou "test automatisé par un programmeur".
Les tests unitaires doivent être petits, indépendants et rapides.
Certaines personnes lisent à tort ceci comme "des tests automatisés écrits par un programmeur doivent être indépendants et rapides" . Mais cela signifie simplement que si vos tests ne sont pas petits, indépendants et rapides, ils ne sont pas des tests unitaires. Par conséquent, certaines des règles relatives aux tests unitaires ne doivent pas, ne peuvent pas ou ne doivent pas s'appliquer à vos tests. Un exemple trivial: vous devez exécuter vos tests unitaires après chaque construction, ce que vous ne devez pas faire pour les tests automatisés qui ne sont pas rapides.
Bien que vos tests ne soient pas des tests unitaires signifie que vous pouvez ignorer une règle et être autorisés à établir une certaine interdépendance entre les tests, vous avez également découvert qu'il existe d'autres règles que vous avez peut-être manquées et que vous devrez réintroduire - ce qui correspond à la portée d'une autre question. .
la source
Comme indiqué ci-dessus, ce que vous exécutez semble être un test d'intégration. Toutefois, vous indiquez que:
Et cela peut être un bon endroit pour commencer la refactorisation. Le module qui exécute des requêtes sur les données ne doit pas dépendre d'une implémentation concrète du premier module (génération de données). Au lieu de cela, il serait préférable d’injecter une interface contenant les méthodes permettant d’accéder à ces données. Celles-ci peuvent ensuite être simulées pour tester les requêtes.
par exemple
Si tu as:
Préférez plutôt:
Cela supprime la dépendance des requêtes sur votre source de données et vous permet de configurer des tests unitaires facilement répétables pour des scénarios particuliers.
la source
Les autres réponses mentionnent que la commande de tests est mauvaise (ce qui est vrai la plupart du temps), mais il existe une bonne raison de faire respecter l’ordre lors de l’exécution de tests: vous assurer que vos tests lents (c’est-à-dire les tests d’intégration) s’exécutent après vos tests plus rapides (tests). qui ne dépendent pas d’autres ressources extérieures). Cela garantit que vous exécutez plus de tests plus rapidement, ce qui peut accélérer la boucle de rétroaction.
la source