Comment garder le tronc stable lorsque les tests durent longtemps?

9

Nous avons trois ensembles de suites de tests:

  • Une "petite" suite, ne prenant que quelques heures à courir
  • Une suite "moyenne" qui prend plusieurs heures, généralement exécutée tous les soirs (tous les soirs)
  • Une "grande" suite qui prend une semaine + pour fonctionner

Nous avons également un tas de suites de tests plus courtes, mais je ne me concentre pas sur elles ici.

La méthodologie actuelle consiste à exécuter la petite suite avant chaque validation dans le tronc. Ensuite, la suite moyenne s'exécute tous les soirs, et si le matin elle s'est avérée avoir échoué, nous essayons d'isoler lequel des commits d'hier était à blâmer, annulons ce commit et réessayons les tests. Un processus similaire, uniquement à une fréquence hebdomadaire plutôt que nocturne, est effectué pour la grande suite.

Malheureusement, la suite moyenne échoue assez fréquemment. Cela signifie que le coffre est souvent instable, ce qui est extrêmement gênant lorsque vous souhaitez apporter des modifications et les tester. C'est ennuyeux parce que lorsque je quitte le coffre, je ne peux pas savoir avec certitude qu'il est stable, et si un test échoue, je ne peux pas savoir avec certitude si c'est ma faute ou non.

Ma question est la suivante: existe-t-il une méthodologie connue pour gérer ce genre de situations de manière à laisser le coffre toujours en pleine forme? par exemple "s'engager dans une branche spéciale de pré-engagement qui mettra ensuite à jour périodiquement le tronc chaque fois que la nuit passe".

Et est-ce important si c'est un système de contrôle de source centralisé comme SVN ou un système distribué comme git?

Soit dit en passant, je suis un développeur junior avec une capacité limitée à changer les choses, j'essaie simplement de comprendre s'il existe un moyen de gérer cette douleur que je ressens.

Chêne
la source
6
Je n'ai aucune idée du logiciel sur lequel vous travaillez, mais une petite suite de tests qui prend des heures à fonctionner est du WTF. S'ils s'exécutaient plus rapidement, ce serait plus facile, aucun moyen de rationaliser vos tests?
Benjamin Bannier
2
Qu'est-ce qui est si "extrêmement ennuyeux" quand le coffre est instable? Je ne sais pas si vous le savez, mais l'une des stratégies de branchement les plus populaires est même appelée tronc instable
moucheron
1
Il existe de nombreuses façons d'optimiser une suite de tests (comme pour tout autre logiciel). Je ne sais pas pourquoi le vôtre prend autant de temps, mais vous pourriez par exemple être en mesure de réutiliser une partie de l'environnement de test ou simplement utiliser de meilleurs algorithmes / structures de données lors de l'exécution (le profilage aide). Il se peut également que personne n'ait pris le temps d'identifier des échantillons représentatifs et que vous testiez simplement chaque entrée / sortie possible par rapport à une référence. Peut-être que votre système de construction vous permet d'encoder les dépendances de test de code afin que vous n'ayez pas besoin d'exécuter l'ensemble complet. Et je sais que ce n'était pas votre question, c'est pourquoi j'ai fait un commentaire, pas une réponse.
Benjamin Bannier
1
... hmm, votre meilleure option est susceptible d'améliorer les tests et la journalisation des applications afin de trouver plus facilement la raison de l'échec. De cette façon, il faudrait trouver et corriger la cause de l'échec au lieu de gaspiller ses efforts sur des "enquêtes de détective" à la recherche de qui, quand et pourquoi changer une ligne de code particulière ...
moucher
1
@honk Certains tests sont longs à exécuter. Je travaille pour une entreprise qui fabrique des équipements d'acquisition de données et notre test "partiel" dure environ une heure. Les tests doivent faire différents types de mesures et cela prend juste du temps.
Velociraptors

Réponses:

1

La seule façon de résoudre la cause première de l'instabilité est de découpler le code afin que les modifications soient plus isolées, comme d'autres réponses l'ont suggéré.

Cependant, en tant que développeur individuel, si vous voulez une version plus stable sur laquelle vous pouvez travailler personnellement, c'est relativement facile à résoudre. Au lieu de travailler à partir de l'astuce, vous extrayez uniquement la dernière version qui a réussi la suite de tests pendant la nuit dans votre arbre de travail. Si vous pouvez créer des branches d'entités pour chaque modification, dérivez de la dernière version stable.

Oui, votre arbre aura quelques jours de retard, mais la plupart du temps cela n'a pas d'importance. Faites votre travail par rapport à la version stable, afin que vous sachiez que vos modifications sont celles qui ont interrompu tous les tests, puis avant de vous enregistrer, mettez à jour vers la dernière version et effectuez votre intégration normale. Ensuite, après vous être enregistré, revenez à la dernière version stable.

Vous devez encore faire le travail d'intégration compliqué, mais ce que j'aime dans cette méthode, c'est qu'elle isole le travail d'intégration à un moment plus pratique pour moi, et me donne une base de code stable pour le développement quand ce n'est pas pratique. J'ai une bien meilleure idée quand ce sont mes changements qui ont probablement cassé la construction par rapport à ceux de quelqu'un d'autre.

Karl Bielefeldt
la source
1
-1 travailler à partir de succursales est une option viable, mais le recommander sans suggérer de tester pourrait faire plus de mal que de bien. Seuls les tests peuvent montrer si c'est faisable pour un projet spécifique ou non. Par exemple, dans un projet que j'ai réalisé il y a environ 2 ans, un tel test a montré que le travail dans les succursales prenait environ 7 fois plus d' efforts que le tronc instable
moucheron
Merci Karl! Bien que ce ne soit pas ce que j'espérais apprendre, c'est une approche très pratique qui pourrait m'aider à résoudre le problème en question. Et je suis d'accord que travailler quelques jours derrière le tronc ne causera que rarement des problèmes d'intégration.
Oak
12

Je sais que vous essayez d'éviter cela, mais le vrai aperçu ici est de réaliser que quelque chose ne va vraiment pas dans votre base de code: vous devez exécuter une suite complète de tests qui prend une semaine juste pour être sûr que votre code est stable!

La façon la plus avantageuse de résoudre ce problème est de commencer à séparer votre base de code et vos tests en sous-unités (indépendantes).
Les avantages sont énormes:

  • Les tests pour chacune de ces unités s'exécuteront plus rapidement (il y en a tout simplement moins) et ils ne se casseront pas en cas de problème dans l'une des unités indépendantes ou en aval.
  • Un test ayant échoué sera localisé sur une unité particulière, ce qui facilitera la recherche de la source du problème.
  • Vous pouvez séparer les emplacements VCS des différentes unités afin que votre branche "stable" puisse être un mélange de la dernière version testée avec succès de chaque unité, afin qu'une ou deux unités cassées ne déstabilisent pas votre version "stable" .

D'un autre côté, la gestion de votre structure VCS deviendra plus compliquée, mais à une semaine complète pour votre test complet, je pense que vous pouvez prendre la douleur!

Je recommande toujours d'utiliser une stratégie de branches "stable" et "développement" sous une forme ou une autre, mais il existe de nombreuses façons de procéder et vous pouvez choisir celle qui fonctionne le mieux pour votre organisation (méta-référentiels avec des révisions fixes pointant vers des référentiels séparés pour chaque unité, une branche stable et une branche de développement, des branches de fonctionnalités ....)

Joris Timmermans
la source
1
Je n'ai jamais dit que le grand test est un test atomique, c'est une suite de tests . Lorsqu'un développeur individuel apporte une modification à l'élément X, il exécute les tests relatifs à X - quelle que soit la suite de tests dont ils sont issus. Ceci s'ajoute au test hebdomadaire, qui est exécuté pour s'assurer qu'un changement à un endroit n'a pas affecté de manière inattendue un autre endroit. Mais vous faites remarquer que séparer au moins les choses de cette façon aidera à accélérer les tests pour des modules spécifiques, tout en maintenant le risque à peu près au même niveau.
Oak
2
@oak - Eh bien, d'une certaine manière, la suite EST atomique si vous exécutez tout cela est la seule façon dont vous êtes réellement sûr que le code est stable, mais vous faites un bon argument, j'ai donc modifié ma réponse.
Joris Timmermans
4
Nous avons d'énormes suites de tests pour nos compilateurs, dont certaines prennent plusieurs jours à s'exécuter, et je ne pense pas que ce soit rare pour des logiciels aussi complexes qu'un compilateur C ++. Ce n'est pas que la suite définit ce qui doit être considéré comme "stable", mais plutôt qu'il y a des millions de cas différents de génération de code qu'il est impossible de les tester tous les jours.
JesperE
1
@JesperE - c'est compréhensible, si l'énorme suite de tests ne définit pas "stable" mais est un gigantesque test de raison. Je ne m'attendrais pas à ce que la suite complète (ou même la suite moyenne) échoue très souvent.
Joris Timmermans
1

Pour SVN, je ne connais rien de tel que le "pré-commit". Je pense qu'il est susceptible de produire des validations et des annulations lorsque le test échoue. Comme le dit doc-brown, le seul moyen est de valider une branche temporaire et de la fusionner avec trunk plus tard.

En utilisant un distribué comme git ou mercurial, je pense que ce serait possible. Utilisation d'un référentiel "testing" et d'un référentiel "stable". Vous appuyez sur le représentant du test, le testez tous les soirs, et si tout se passe bien, vous passez du test à stable. Sinon, vous annulez le représentant de test. Je ne sais pas trop à quoi ressemblerait l'historique des versions lorsque vous passez du test à stable, mais je pense qu'il est possible d'exclure les éléments annulés cassés lors de cette opération. Un peu d'expérimentation en premier serait le plus sûr.

Une alternative serait également de tester le tronc local de chaque personne tous les soirs. Ensuite, les personnes ayant réussi les tests sont autorisées à le pousser vers le serveur central le matin.

dagnelies
la source
1

À mon humble avis, cela n'a rien à voir avec le VCS que vous utilisez. L'utilisation d'une branche "sous test" peut être une solution, qui peut également être réalisée avec VCS centralisé ou distribué. Mais honnêtement, je pense que la meilleure chose dans votre situation est d'essayer d'optimiser la suite de tests moyenne (il semble qu'elle contient les tests les plus importants) afin qu'elle s'exécute beaucoup plus rapidement, donc vous pouvez l'utiliser pour le pré-commit-to-trunk tests, comme vous le faites maintenant avec votre "petite suite".

Doc Brown
la source
Je pose surtout des questions sur la méthodologie ici - c'est-à-dire, existe-t-il un moyen commun de faire face à une telle situation. Supposons, au moins pour les besoins de cette discussion, que les tests ne peuvent pas être optimisés au-delà de ce qu'ils sont déjà.
Oak
@Oak: quelqu'un ici (vous?) A rejeté ma réponse - mais parfois les choses que vous ne voulez pas entendre sont les seules choses qui vous aideront. Comme vous le voyez dans la discussion ci-dessous votre question, d'autres ont suggéré la même chose, donc ma suggestion ne semble pas être si mauvaise du tout.
Doc Brown
+1, c'est la bonne réponse. La vraie question du PO est "Aide, je me noie dans la merde, quelle méthodologie puis-je utiliser pour m'aider?" et la réponse est que la méthodologie n'est pas vraiment ce qui devrait vous inquiéter.
MrFox
1

Les tests de support défaillants: est-il vrai que la plupart du temps les mêmes tests échouent?

En cas d'échec, y a-t-il toujours les mêmes tests connexes qui échouent?

Si vrai: il se peut que vous puissiez sélectionner sélectivement certains tests moyens qui échouent souvent (un test pour chaque classe d'erreur) et les exécuter dans le petit ensemble.

La plupart des tests d'intégration-tests utilisent-ils une vraie base de données? Si c'est le cas, est-il possible de les remplacer par un plus un qui a une base de données simulée?

k3b
la source
1

Vous devez accélérer vos tests, il n'y a pas d'autre moyen de quadriller ce cercle.

Considérez le problème: vous voulez être sûr que lorsque vous retirez, vous avez du code de travail. Bien sûr, vous pouvez retarder les validations et effectuer des branchements avant la version, mais cela ne fera que retarder l'apparition du problème jusqu'à l'intégration. Comme dans, devrez-vous exécuter la suite d'une semaine après chaque fusion? La méthodologie n'est pas la solution, la solution est purement technique.

Voici ce que je propose:

1) Rendre les tests aussi atmosphériques que possible et maximiser la réutilisation de l'environnement.

2) Obtenez une batterie de tests pour les exécuter. Si au lieu de 8 gros modules, vous vous retrouvez avec 50, vous pouvez faire tourner un tas d'instances ponctuelles Amazon EC2 et exécuter toute la suite en parallèle. Je suis sûr que cela coûtera de l'argent, mais cela fera gagner énormément de temps aux développeurs.

MrFox
la source
0

L'essentiel que vous tenez pour acquis dans votre question est que toutes les validations doivent réussir les tests. Bien que ce soit une bonne règle à suivre et que cela semble logique, parfois ce n'est pas pratique. Votre cas est un exemple (bien que MadKeithV le fasse remarquer), et je peux imaginer garder une branche VCS si vierge pourrait être difficile s'il n'y a pas une coopération suffisante entre les développeurs.

En réalité, ce que vous voulez, c'est savoir d'une manière ou d'une autre quels engagements réussissent ou échouent. Une "branche de pré-validation" comme vous l'avez suggéré fonctionnerait, mais cela pourrait nécessiter des efforts supplémentaires de la part des développeurs lorsqu'ils effectuent des validations, ce qui peut être difficile à vendre.

Une approche similaire qui pourrait être plus facile consiste à laisser le coffre pour que les gens se cassent à leur guise et à avoir une branche pour les commits qui ne sont pas cassés. Un script automatisé peut passer par des validations au fur et à mesure qu'elles sont apportées au tronc, exécuter les tests sur celles-ci et les ajouter à la branche si elles réussissent.

Ou vous pourriez être absurdement simpliste et avoir un script qui répertorie les validations de passage dans un fichier texte (qui peut ou non être lui-même contrôlé par la version).

Ou disposez d'un système de traitement par lots qui accepte les demandes de branches / révisions à tester (de n'importe où dans l'arborescence), les teste et les valide dans le tronc (ou une autre branche) si elles réussissent.

Michael Slade
la source