- Cette question ne concerne pas les cadres de tests unitaires.
- Cette question ne concerne pas la rédaction de tests unitaires.
- Cette question concerne l' endroit où placer le code UT écrit et comment / quand / où le compiler et l'exécuter.
En travaillant efficacement avec Legacy Code , Michael Feathers affirme que
bons tests unitaires ... courez vite
et cela
Un test unitaire qui prend 1 / 10ème de seconde est un test unitaire lent.
Je pense que ces définitions ont un sens. Je pense aussi que cela implique que vous devez conserver un ensemble de tests unitaires et un ensemble de tests de code qui prennent plus longtemps séparément, mais je suppose que c'est le prix que vous payez pour appeler seulement un test unitaire s'il fonctionne (très) rapidement .
Il est évident que le problème en C ++ est que pour « exécuter » votre unité de test ( de s ), vous devez:
- Modifiez votre code (production ou test unitaire, en fonction du "cycle" dans lequel vous vous trouvez)
- Compiler
- Lien
- Unité de démarrage d' essai Executable ( s )
Edit (après un vote bizarre) : Avant d’entrer dans les détails, je vais essayer de résumer le point ici:
Comment organiser efficacement le code de test unitaire C ++, de sorte qu'il soit à la fois efficace de modifier le code (de test) et de l'exécuter?
Le premier problème consiste alors à décider où placer le code de test unitaire afin que:
- il est "naturel" de l'éditer et de l'afficher en combinaison avec le code de production associé.
- il est facile / rapide de démarrer le cycle de compilation pour l'unité en cours de modification
Le deuxième problème, lié, est alors de savoir quoi compiler pour que le retour d’information soit instantané.
Options extrêmes:
- Chaque unité Unit-Test-Test-Unit réside dans un fichier cpp distinct et ce fichier cpp est compilé + lié séparément (avec le fichier unité de code source qu’il teste) à un seul exécutable qui exécute ensuite ce test unitaire.
- (+) Ceci minimise le temps de démarrage (compilation + lien!) Pour la même unité de test.
- (+) Le test est très rapide car il ne teste qu'une seule unité.
- (-) L'exécution de toute la suite nécessitera un nombre incroyable de processus. Peut être un problème à gérer.
- (-) Les frais généraux liés aux débuts du processus deviendront visibles
- L’autre côté serait d’avoir - toujours - un fichier cpp par test, mais tous les fichiers cpp de test (ainsi que le code qu’ils testent!) Sont liés dans un seul exécutable (par module / par projet / choisissez votre choix).
- (+) Le temps de compilation serait toujours correct, car seul le code modifié sera compilé.
- (+) Exécuter la suite entière est facile, puisqu'il n'y a qu'un seul exe à exécuter.
- (-) Il faudra du temps pour que la suite soit liée, car chaque recompilation d’un objet déclenchera une nouvelle liaison.
- (-) (?) La combinaison prendra plus de temps, bien que si tous les tests unitaires sont rapides, le temps sera correct.
Alors, comment sont gérés les tests unitaires C ++ du monde réel ? Si je ne fais que ça tous les soirs / toutes les heures, la deuxième partie importe peu, mais la première, à savoir comment "coupler" le code UT au code de production, de sorte qu'il soit "naturel" pour les développeurs de conserver les deux Je pense que la concentration compte toujours. (Et si les développeurs ont le code UT dans le focus, ils voudront le lancer, ce qui nous ramène à la deuxième partie.)
Histoires du monde réel et expérience appréciée!
Remarques:
- Cette question laisse intentionnellement une plate-forme et un système de marque / projet non spécifiés.
- Questions marquées UT & C ++ est un bon point de départ, mais malheureusement, trop de questions, et surtout de réponses, sont trop centrées sur les détails ou sur des cadres spécifiques.
- Il y a quelque temps, j'ai répondu à une question similaire sur la structure des tests unitaires de boost. Je trouve que cette structure manque pour les "vrais" tests unitaires rapides. Et je trouve l’autre question trop étroite, d’où cette nouvelle question.
:-(
Où êtes-vous supposé chercher des réponses à de telles questions si ce n'est dans ce forum?
Pipeline<A,B>.connect(Pipeline<B,C>)
doit être compilé alors que Pipeline<A,B>.connect(Pipeline<C,D>)
ne doit pas être compilé: Le type de sortie du premier étage est incompatible avec le type d’entrée du deuxième étage.