À mon avis, les tests unitaires devraient être placés dans un assemblage distinct du code de production. Voici quelques inconvénients du placement de tests unitaires dans le même assembly ou assemblys que le code de production:
- Les tests unitaires sont livrés avec le code de production. La seule chose livrée avec le code produit est le code de production.
- Les assemblages seront inutilement gonflés par les tests unitaires.
- Les tests unitaires peuvent affecter les processus de construction comme la construction automatisée ou continue.
Je ne connais pas vraiment de pros. Avoir un projet supplémentaire (ou 10) n'est pas un inconvénient.
Edit: Plus d'informations sur la construction et l'expédition
Je recommanderais en outre que tout processus de construction automatisé place la production et les tests unitaires dans différents endroits. Dans l'idéal, le processus de génération de test unitaire ne s'exécute que si le code de production est généré et copie les fichiers du produit dans le répertoire des tests unitaires. En procédant de cette façon, les bits réels sont séparés pour l'expédition, etc. De plus, il est assez simple d'exécuter des tests unitaires automatisés à ce stade sur tous les tests d'un répertoire particulier.
Pour résumer, voici l'idée générale d'une construction quotidienne, de tests et d'expédition de bits et autres fichiers:
- La génération de production s'exécute, plaçant les fichiers de production dans un répertoire "production" spécifique.
- Créez uniquement des projets de production.
- Copiez les bits compilés et autres fichiers dans un répertoire "production".
- Copiez les bits et autres fichiers dans un répertoire de release candidate, alias un répertoire de release de Noël serait "Release20081225".
- Si la génération de production réussit, la génération de test unitaire s'exécute.
- Copiez le code de production dans le répertoire "tests".
- Créez des tests unitaires dans le répertoire "tests".
- Exécutez des tests unitaires.
- Envoyez des notifications de build et des résultats de tests unitaires aux développeurs.
- Lorsqu'une version candidate (telle que Release20081225) est acceptée, expédiez ces bits.
#if
. Ce symbole personnalisé peut être basculé à l'aide des paramètres de ligne de commande du compilateur dans vos scripts logiciels CI. Voir msdn.microsoft.com/en-us/library/4y6tbswk.aspx .Projet séparé, mais dans la même solution. (J'ai travaillé sur des produits avec des solutions séparées pour le code de test et de production - c'est horrible. Vous basculez toujours entre les deux.)
Les raisons des projets séparés sont celles exposées par d'autres. Notez que si vous utilisez des tests basés sur les données, vous risquez de vous retrouver avec une quantité assez importante de ballonnement si vous incluez les tests dans l'assemblage de production.
Si vous avez besoin d'accéder aux membres internes du code de production, utilisez InternalsVisibleTo .
la source
[assembly:InternalsVisibleTo("UnitTestProjectName")]
à votreAssemblyInfo.cs
fichier de projet .Je ne comprends pas l'objection fréquente au déploiement de tests avec du code de production. J'ai dirigé une équipe sur une petite microcap (passée de 14 à 130 personnes). Nous avions une demi-douzaine d'applications Java et nous avons trouvé EXTRÊMEMENT appréciable de déployer des tests sur le terrain pour les exécuter sur un spécifiquemachine qui présentait un comportement inhabituel. Des problèmes aléatoires se produisent sur le terrain et pouvoir lancer quelques milliers de tests unitaires au mystère sans coût était inestimable et souvent diagnostiqué des problèmes en quelques minutes ... y compris des problèmes d'installation, des problèmes de RAM floconneux, des problèmes spécifiques à la machine, des problèmes de réseau irréguliers, etc, etc. Je pense qu'il est extrêmement précieux de faire des tests sur le terrain. En outre, des problèmes aléatoires surgissent à des moments aléatoires et il est agréable d'avoir les tests unitaires assis là déjà en attente d'être exécutés à tout moment. L'espace sur le disque dur est bon marché. Tout comme nous essayons de garder les données et les fonctions ensemble (conception OO), je pense qu'il y a quelque chose de fondamentalement précieux à garder le code et les tests ensemble (fonction + tests qui valident les fonctions).
Je voudrais mettre mes tests dans le même projet en C # /. NET / Visual Studio 2008, mais je n'ai pas encore suffisamment étudié cela pour y parvenir.
Un grand avantage de garder Foo.cs dans le même projet que FooTest.cs est que les développeurs sont constamment rappelés lorsqu'une classe manque un test frère! Cela encourage de meilleures pratiques de codage basées sur les tests ... les trous sont plus apparents.
la source
Placez les tests unitaires dans le même projet que le code pour obtenir une meilleure encapsulation.
Vous pouvez facilement tester des méthodes internes, ce qui signifie que vous ne rendrez pas publiques des méthodes qui auraient dû être internes.
C'est aussi très agréable d'avoir les tests unitaires proches du code que vous écrivez. Lorsque vous écrivez une méthode, vous pouvez facilement trouver les tests unitaires correspondants car ils se trouvent dans le même projet. Lorsque vous créez un assembly qui inclut unitTests, toute erreur dans unitTest vous donnera une erreur de compilation, vous devez donc garder votre unittest à jour, juste pour construire. Avoir unittest dans un projet séparé peut amener certains développeurs à oublier de construire le projet unittest et à manquer les tests interrompus pendant un certain temps.
Et vous pouvez supprimer les tests unitaires du code de production, en utilisant des balises de compilation (IF #Debug).
Les tests d'intégration automatique (réalisés sur NUnit) doivent être dans un projet séparé car ils n'appartiennent à aucun projet unique.
la source
Release
construction et que peu de "heisenbugs" peuvent échouer.InternalsVisibleTo
vous permet de tester des méthodes internes à partir d'un projet de testDebug
,Approval
etRelease
; et compilez l'approbation avec toutes les optimisations de version. En outre, les tests unitaires ne sont généralement pas excellents pour détecter les heisenbugs en premier lieu (d'après mon expérience). Vous avez tendance à avoir besoin de tests de régression d'intégration spécifiques pour ceux-ci - et vous pouvez très bien les placer côte à côte.Après avoir passé du temps dans des projets TypeScript, où les tests sont souvent placés dans un fichier à côté du code qu'ils testent, j'ai grandi en préférant cette approche à leur séparation:
Ainsi, lorsque j'ai récemment lancé un nouveau projet .NET Core, je voulais voir s'il était possible d'imiter cette structure dans un projet C # sans expédier les tests ou les assemblys de test avec la version finale.
Jusqu'à présent, l'insertion des lignes suivantes dans le fichier de projet semble bien fonctionner:
Ce qui précède garantit que dans la
Release
configuration tous les fichiers nommés*.Tests.cs
sont exclus de la compilation, et également que les références de package de test unitaire requises sont supprimées.Si vous voulez toujours pouvoir tester les unités dans leur configuration de version, vous pouvez simplement créer une nouvelle configuration dérivée de
Release
appelé quelque chose commeReleaseContainingTests
.Mise à jour: après avoir utilisé cette technique pendant un certain temps, j'ai également trouvé qu'il était utile de personnaliser vos icônes dans VS Code pour que les tests (et d'autres choses) se démarquent un peu plus dans le volet de l'explorateur:
Pour ce faire, utilisez l'extension Material Icon Theme et ajoutez quelque chose comme ce qui suit à vos préférences VS Code JSON:
la source
Mes tests unitaires vont toujours dans un projet séparé. En fait, pour chaque projet que j'ai dans ma solution, il y a un projet de test séparé qui l'accompagne. Le code de test n'est pas du code d'application et ne doit pas être mélangé avec lui. Un avantage à les conserver dans des projets séparés - au moins en utilisant TestDriven.Net - est que je peux cliquer avec le bouton droit sur un projet de test et exécuter tous les tests de ce projet, en testant une bibliothèque entière de code d'application en un seul clic.
la source
Si le framework NUnit est utilisé, il y a une raison supplémentaire de placer les tests dans le même projet. Prenons l'exemple suivant du code de production mélangé à des tests unitaires:
Les tests unitaires ici servent de documentation et de spécification du code testé. Je ne sais pas comment obtenir cet effet d'auto-documentation, les tests étant situés dans un projet séparé. L'utilisateur de la fonction devrait rechercher les tests pour voir ces cas de test, ce qui est peu probable.
Mise à jour : je sais qu'une telle utilisation de l'
TestCase
attribut n'était pas l'intention des développeurs de NUnit, mais pourquoi pas?la source
Je fluctue entre le même projet et différents projets.
Si vous publiez une bibliothèque, publier le code de test avec le code de production est un problème, sinon je trouve que ce n'est généralement pas le cas (bien qu'il y ait une forte barrière psychologique avant d'essayer).
Lorsque je place des tests dans le même projet, je trouve qu'il est plus facile de basculer entre les tests et le code qu'ils testent, et plus facile de les refactoriser / les déplacer.
la source
Je les mets dans des projets séparés. Le nom de l'assemblage reflète celui des espaces de noms, en règle générale pour nous. Donc, s'il existe un projet appelé Company.Product.Feature.sln, il a une sortie (nom d'assembly) de Company.Product.Feature.dll. Le projet de test est Company.Product.Feature.Tests.sln, produisant Company.Product.Feature.Tests.dll.
Il est préférable de les conserver dans une solution unique et de contrôler la sortie via le Gestionnaire de configuration. Nous avons une configuration nommée pour chacune des branches principales (développement, intégration, production) au lieu d'utiliser le débogage et la publication par défaut. Une fois que vous avez configuré vos configurations, vous pouvez ensuite les inclure ou les exclure en cliquant sur la case à cocher "Construire" dans le Gestionnaire de configuration. (Pour obtenir le Gestionnaire de configuration, cliquez avec le bouton droit sur la solution et accédez à Configuration Manager.) Notez que je trouve que le CM dans Visual Studio est parfois bogué. Plusieurs fois, j'ai dû aller dans les fichiers du projet et / ou de la solution pour nettoyer les cibles qu'il avait créées.
De plus, si vous utilisez Team Build (et je suis sûr que les autres outils de build .NET sont identiques), vous pouvez alors associer la build à une configuration nommée. Cela signifie que si vous ne générez pas vos tests unitaires pour votre build "Production", par exemple, le projet de build peut également être conscient de ce paramètre et ne pas les générer car ils ont été marqués comme tels.
De plus, nous avions l'habitude de faire des dépose XCopy de la machine de construction. Le script omettrait simplement de copier tout ce qui est nommé * .Tests.Dll du déploiement. C'était simple, mais cela fonctionnait.
la source
Je dirais de les garder séparés.
En plus des autres raisons mentionnées, le fait d'avoir du code et des tests ensemble biaise les numéros de couverture des tests. Lorsque vous signalez la couverture des tests unitaires, la couverture signalée est plus élevée car les tests sont couverts lorsque vous exécutez des tests unitaires. Lorsque vous signalez la couverture des tests d'intégration, la couverture signalée est inférieure car les tests d'intégration n'exécutent pas de tests unitaires.
la source
Je suis vraiment inspiré par le framework de test unitaire de la bibliothèque Flood NN de Robert Lopez. Il utilise un projet différent pour chaque classe testée unitaire et possède une solution contenant tous ces projets, ainsi qu'un projet principal qui compile et exécute tous les tests.
Le truc sympa est aussi la mise en page du projet. Les fichiers source se trouvent dans un dossier, mais le dossier du projet VS se trouve ci-dessous. Cela vous permet de créer différents sous-dossiers pour différents compilateurs. Tous les projets VS sont livrés avec le code, il est donc très facile pour quiconque d'exécuter tout ou partie des tests unitaires.
la source
Je sais que c'est une question très ancienne, mais je voudrais ajouter mon expérience là-bas, j'ai récemment changé l'habitude de test unitaire de projets séparés à un même.
Pourquoi?
Premièrement, je suis très enclin à garder la même structure de dossier de projet principal avec le projet de test. Donc, si j'ai un fichier sous,
Providers > DataProvider > SqlDataProvider.cs
je crée la même structure dans mes projets de test unitaire commeProviders > DataProvider > SqlDataProvider.Tests.cs
Mais une fois que le projet devient de plus en plus gros, une fois que vous déplacez des fichiers d'un dossier à un autre, ou d'un projet à un autre, il devient très fastidieux de les synchroniser avec les projets de test unitaire.
Deuxièmement, il n'est pas toujours très facile de naviguer de la classe à tester à la classe de test unitaire. C'est encore plus difficile pour JavaScript et Python.
Récemment, j'ai commencé à pratiquer cela, chaque fichier que j'ai créé (par exemple
SqlDataProvider.cs
) je crée un autre fichier avec le suffixe Test, commeSqlDataProvider.Tests.cs
Au début, il semble que cela gonflera les fichiers et les références de bibliothèque, mais à long terme, vous éliminerez le syndrome des fichiers en mouvement à première vue, et vous vous assurerez également que chaque fichier qui est candidat au test aura un fichier paire avec
.Tests
suffixe. Il vous permet de sauter facilement dans le fichier de test (car il est côte à côte) au lieu de parcourir un projet séparé.Vous pouvez même écrire des règles métier pour parcourir le projet et identifier la classe qui n'a pas de fichier .Tests, et les signaler au propriétaire. Vous pouvez également indiquer facilement à votre testeur de cibler les
.Tests
classes.Surtout pour Js et Python, vous n'aurez pas besoin d'importer vos références à partir d'un chemin différent, vous pouvez simplement utiliser le même chemin du fichier cible en cours de test.
J'utilise cette pratique depuis un certain temps et je pense que c'est un compromis très raisonnable entre la taille du projet par rapport à la maintenabilité et la courbe d'apprentissage pour les nouveaux arrivants au projet.
la source
Comme d'autres l'ont répondu - mettez des tests dans des projets séparés
Une chose qui n'a pas été mentionnée est le fait que vous ne pouvez pas exécuter
nunit3-console.exe
contre autre chose que des.dll
fichiers.Si vous prévoyez d'exécuter vos tests via TeamCity, cela posera un problème.
Disons que vous avez un projet d'application console. Lorsque vous compilez, il renvoie un exécutable
.exe
dans lebin
dossier.À partir de,
nunit3-console.exe
vous ne pourrez pas exécuter de tests définis dans cette application console.En d'autres termes, une application console renvoie un
exe
fichier et une bibliothèque de classes renvoie desdll
fichiers.Je viens de me faire mordre aujourd'hui et ça craint :(
la source
J'ai récemment déployé dans docker. Je ne vois pas l'intérêt d'avoir un projet séparé lorsque le Dockerfile peut facilement copier le répertoire / src et quitter le répertoire / test. Mais je suis nouveau sur dotnet et il me manque peut-être quelque chose.
la source
Projets séparés, bien que je débatte avec moi-même s'ils doivent partager le même svn. Pour le moment, je leur donne des dépôts svn séparés, un appelé
"MyProject" - pour le projet lui-même
et un appelé
"MyProjectTests" - pour les tests associés à MyProject.
Ceci est assez propre et présente l'avantage que les engagements dans le projet et les engagements aux tests sont assez séparés. Cela signifie également que vous pouvez remettre le svn du projet si nécessaire, sans avoir à publier vos tests. Cela signifie également que vous pouvez avoir des répertoires branch / trunk / tag pour vos tests et pour votre projet.
Mais je suis de plus en plus enclin à avoir quelque chose comme ce qui suit, dans un seul référentiel svn, pour chaque projet.
Je serais intéressé de savoir ce que les autres pensent de cette solution.
la source