web-dev-qa-db-fra.com

Quel est l'intérêt d'exécuter des tests unitaires sur un serveur CI?

Pourquoi exécuter des tests unitaires sur un serveur CI?

Certes, au moment où quelque chose est commis à maîtriser, un développeur a déjà exécuté tous les tests unitaires avant et corrigé toutes les erreurs qui auraient pu se produire avec leur nouveau code. N'est-ce pas là l'intérêt des tests unitaires? Sinon, ils viennent de commettre du code cassé.

99
Steve

Certes, au moment où quelque chose est commis à maîtriser, un développeur a déjà exécuté tous les tests unitaires avant et corrigé toutes les erreurs qui auraient pu se produire avec leur nouveau code.

Ou pas. Il peut y avoir plusieurs raisons à cela:

  • Le développeur n'a pas la discipline pour le faire
  • Ils ont oublié
  • Ils n'ont pas tout validé et ont poussé un ensemble de validations incomplet (merci Matthieu M.
  • Ils n'ont exécuté que quelques tests, mais pas toute la suite (merci nhgrif )
  • Ils ont testé sur leur branche avant la fusion (merci nhgrif * 2)

Mais le vrai point est d'exécuter les tests sur une machine qui n'est pas la machine du développeur. Celui qui est configuré différemment.

Cela permet de détecter les problèmes où les tests et/ou le code dépendent de quelque chose de spécifique à une boîte de développeur (configuration, données, fuseau horaire, paramètres régionaux, etc.).

Autres bonnes raisons pour que les builds CI exécutent des tests:

  • Test sur différentes plates-formes autres que les principales plates-formes de développement, ce qui peut être difficile à faire pour un développeur. (merci TZHX )
  • Acceptation/Intégration/De bout en bout/Des tests très longs peuvent être exécutés sur le serveur CI qui ne serait généralement pas exécuté sur une boîte de développeur. (merci Ixrec )
  • Un développeur peut effectuer un petit changement avant de pousser/valider (pensant que c'est un changement sûr et donc ne pas exécuter les tests). (merci Ixrec * 2)
  • La configuration du serveur CI n'inclut généralement pas tous les outils de développement et la configuration et est donc plus proche du système de production
  • Les systèmes CI construisent le projet à partir de zéro à chaque fois, ce qui signifie que les versions sont répétables
  • Un changement de bibliothèque peut provoquer des problèmes en aval - un serveur CI peut être configuré pour créer toutes les bases de code dépendantes , pas seulement celle de la bibliothèque
225
Oded

En tant que développeur qui n'exécute pas tous les tests d'intégration et unitaires avant de s'engager dans le contrôle de code source, je proposerai ma défense ici.

Je devrais construire, tester et vérifier qu'une application fonctionne correctement sur:

  • Microsoft Windows XP et Vista avec le compilateur Visual Studio 2008.
  • Microsoft Windows 7 avec compilateur Visual Studio 2010.
    • Oh, et le MSI construit pour chacun d'eux.
  • RHEL 5 et 6 avec 4.1 et 4.4 respectivement (de même CentOS)
    • 7 bientôt. Woop-de-woop.
  • Fedora Workstation avec GCC pour les trois dernières versions récentes.
  • Debian (et dérivés comme Ubuntu) pour les trois dernières versions récentes.
  • Mac OSX dans les trois dernières versions récentes.
    • Et les packages (rpm, dmg, etc.)

Ajoutez le Fortran (avec les compilateurs Intel et GNU), Python (et ses versions varient en fonction du système d'exploitation) et les composants de script bash/bat et, eh bien , Je pense que vous pouvez voir les choses dégénérer

Donc, c'est seize machines que je devrais avoir, juste pour exécuter quelques tests quelques fois par jour. Ce serait presque un travail à plein temps de gérer l'infrastructure pour cela. Je pense que presque tout le monde conviendrait que c'est déraisonnable, surtout en le multipliant par le nombre de personnes dans le projet. Nous avons donc laissé nos serveurs CI faire le travail.

Les tests unitaires ne vous empêchent pas de commettre du code cassé, ils vous disent s'ils savoir vous avez cassé quelque chose. Les gens peuvent dire que "les tests unitaires devraient être rapides" et parler des principes et des modèles de conception et des méthodologies, mais en réalité, il est parfois préférable de laisser les ordinateurs que nous avons conçus pour des tâches répétitives et monotones faire ceux-ci et ne s'impliquer que s'ils dites-nous qu'ils ont trouvé quelque chose.

75
TZHX

Outre l'excellente réponse Oded:

  • Vous testez le code du référentiel. Cela peut fonctionner sur votre machine avec vos fichiers ... que vous avez oublié de valider. Cela peut dépendre d'une nouvelle table qui ne dispose pas du script de création (en liquidibase par exemple), de certaines données de configuration ou de fichiers de propriétés.
  • Vous évitez les problèmes d'intégration de code. Un développeur télécharge la dernière version, crée un test unitaire et d'intégration, ajoute du code, réussit tous les tests sur sa machine, valide et pousse. Un autre développeur vient de faire de même. Les deux modifications sont correctes, mais lorsqu'elles sont fusionnées, cela provoque un bogue. Cela peut être la fusion du référentiel ou simplement qu'il n'est pas détecté comme un conflit. Par exemple. Dev 1 supprime le fichier qui n'était pas utilisé du tout. Codes Dev 2 par rapport à ce fichier et tests sans modifications Dev 1.
  • Vous développez un script à déployer automatiquement à partir du référentiel. Le fait d'avoir un script de construction et de déploiement universel résout de nombreux problèmes. Certains développeurs peuvent avoir ajouté une option lib ou compiling qui n'est pas partagée par tout le monde. Non seulement cela vous fait gagner du temps, mais surtout, cela rend le déploiement sûr et prévisible. De plus, vous pouvez revenir dans votre référentiel vers la version 2.3.1 et déployer cette version avec un script qui fonctionne avec cette version. Il comprend des objets de base de données tels que des vues, des procédures stockées, des vues et des déclencheurs qui doivent être versionnés. (Ou vous ne pourrez pas revenir à une version utilisable).
  • Autres tests: Comme l'intégration, les performances et les tests de bout en bout. Cela peut être lent et peut inclure des outils de test comme Selenium. Vous pouvez avoir besoin d'un ensemble complet de données avec une vraie base de données au lieu d'objets fictifs ou HSQL.

J'ai travaillé une fois sur une entreprise qui avait beaucoup de bugs sur le déploiement en raison du processus de fusion et de déploiement. Cela a été causé par un cadre propriétaire étrange qui a rendu les tests et l'IC difficiles. Ce n'était pas une expérience heureuse de constater que le code qui fonctionnait parfaitement sur le développement n'est pas arrivé directement à la production.

23
Borjab

On pourrait penser que non, mais les développeurs sont humains et ils oublient parfois.

En outre, les développeurs ne parviennent souvent pas à extraire le dernier code. Leurs derniers tests peuvent bien fonctionner puis au moment de l'enregistrement, quelqu'un d'autre commet un changement de rupture.

Vos tests peuvent également s'appuyer sur une ressource locale (non vérifiée). Quelque chose que vos tests unitaires locaux ne détecteraient pas.

Si vous pensez que tout ce qui précède est fantaisiste, il y a un niveau au-dessus de CI (sur TFS au moins) appelé Gated où les builds qui ont des tests qui échouent sont abandonnées et ne sont pas validées dans la base de code.

22
Robbie Dee

au moment où quelque chose s'engage à maîtriser

J'ai généralement configuré mon CI pour qu'il s'exécute à chaque validation. Les branches ne sont pas fusionnées dans master tant que la branche n'a pas été testée. Si vous comptez sur l'exécution de tests sur le maître, cela ouvre une fenêtre pour que la construction soit interrompue.

L'exécution des tests sur une machine CI concerne des résultats reproductibles. Parce que le serveur CI a un environnement propre connu extrait de votre VCS, vous savez que les résultats du test sont corrects. Lors de l'exécution locale, vous pouvez oublier de valider le code nécessaire à leur passage, ou avoir du code non validé qui les fait passer alors qu'ils devraient échouer.

Il peut également faire gagner du temps aux développeurs en exécutant différentes suites en parallèle, en particulier si certains sont des tests lents de plusieurs minutes qui ne sont pas susceptibles d'être exécutés localement après chaque modification.

Dans mon travail actuel, notre déploiement de production est basé sur la réussite de CI à tous les tests. Les scripts de déploiement empêcheront le déploiement à moins qu'ils ne passent. Il est donc impossible d'oublier accidentellement de les exécuter.

CI faisant partie du flux de travail soulage également les développeurs. En tant que développeur, exécutez-vous généralement un linter, un analyseur statique, un test unitaire, une couverture de code et un test d'intégration pour chaque changement? CI peut, complètement automatiquement et sans avoir à y penser - réduisant la fatigue de décision.

14
Daenyth

Au moment où quelque chose est commis à maîtriser, un développeur devrait avoir déjà exécuté tous les tests unitaires ... mais que se passe-t-il s'ils ne l'ont pas? Si vous n'exécutez pas les tests unitaires sur le serveur CI, vous ne le saurez pas jusqu'à ce que quelqu'un d'autre récupère les modifications sur sa machine et découvre que les tests viennent de se casser sur eux.

De plus, le développeur peut avoir fait une erreur et référencé une ressource locale spécifique à sa machine. Lorsqu'ils archivent le code et que l'exécution du CI échoue, le problème est immédiatement identifié et peut être corrigé.

4
David Arno

En supposant (contrairement à d'autres réponses) que les développeurs sont assez disciplinés et exécutent des tests unitaires avant de s'engager, il peut y avoir plusieurs raisons:

  • l'exécution de tests unitaires peut prendre du temps pour une configuration spéciale. Par exemple, l'exécution de tests unitaires avec le vérificateur de mémoire (comme valgrind) peut prendre beaucoup plus de temps. Bien que tous les tests unitaires réussissent, la vérification de la mémoire peut échouer.
  • le résultat n'est pas si important pour certains paramètres spéciaux - par exemple, l'exécution de tests unitaires pour vérifier la couverture du code nécessite des indicateurs de compilation spéciaux. Pour les développeurs normaux, la couverture du code n'est pas si importante - c'est plus pour les personnes qui prennent soin que le code conserve une certaine qualité, comme les chefs d'équipe.
3
BЈовић

Il est possible d'imaginer des cas où le changement A ne rompt pas le test, et le changement B ne rompt pas le test, mais A et B ensemble le font. Si A et B sont créés par des développeurs différents, seul le serveur CI détectera le nouveau bogue. A et B peuvent même être deux parties de la même phrase plus longue.

Imaginez un train conduit par les deux locomotives A et B. Peut-être qu'une seule est plus que suffisante et c'est la solution à appliquer. Cependant, si les deux "correctifs" sont appliqués en supprimant les deux, le train ne bougera pas.

De plus, tous les développeurs n'exécutent pas tous les tests unitaires, contrairement à la plupart des bons développeurs.

3
h22

Posons une question équivalente:

Pourquoi voudriez-vous construire le code sur un serveur CI?

Certes, au moment où quelque chose est commis à maîtriser, un développeur a déjà construit le code avant et corrigé toutes les erreurs qui pourraient se produire avec leur nouveau code. N'est-ce pas là l'intérêt du code du bâtiment? Sinon, ils viennent de commettre du code cassé.


Il y a plusieurs raisons de faire du CI, mais le principal point du CI est de se faire une idée de l'état du code au fil du temps. Le principal avantage (sur plusieurs) que cela offre, est que nous pouvons savoir quand la construction se casse, comprendre ce qui l'a cassé, puis le réparer.

Si le code n'est jamais cassé, pourquoi utilisons-nous même CI? Pour fournir des versions pour les tests, les versions nocturnes seraient suffisantes.

2
Peter