Rien de tel que l'engagement d'une équipe envers l'intégration continue (CI) pour renforcer (ou mettre à mal) l'agilité. L'idée peut paraître inquiétante (en particulier si votre équipe n'a pas encore adopté la CI), mais l'horizon s'éclaircit. Quelles que soient les technologies utilisées par l'équipe, il existe certainement un framework avec CI et tests automatisés qui sera compatible avec sa base de code.
Qu'est-ce que l'intégration continue ?
L'intégration continue (CI) est une bonne pratique Agile et DevOps qui consiste à intégrer systématiquement les changements de code dans la branche principale d'un dépôt et à les tester le plus rapidement et le plus souvent possible. Dans l'idéal, les développeurs intégreront leur code quotidiennement, voire plusieurs fois par jour.
Avantages de l'intégration continue
L'investissement dans l'intégration continue accélère le feedback sur les changements de code. Un feedback désormais disponible en quelques minutes. Une équipe qui s'appuie essentiellement sur des tests manuels recevra peut-être un feedback quelques heures après mais, en réalité, un feedback complet sur les tests arrive plutôt un jour, voire plusieurs après le changement du code. Et entre-temps, d'autres changements y auront été apportés. La correction des bugs devient une expédition archéologique où les développeurs doivent creuser dans différentes couches de code pour atteindre la racine du problème.
Ce n'est vraiment pas rapide.
Préserver la qualité grâce à des builds continus et à l'automatisation des tests
Combien d'entre nous, en téléchargeant le tout dernier code source, se sont rendu compte que sa compilation était impossible ou qu'il contenait un bogue sérieux ? Quel contretemps pour la productivité !
Deux pratiques permettent d'éviter cette situation.
Builds continus : il s'agit de compiler le projet dès qu'une modification est apportée. Dans l'idéal, le delta entre chaque build correspond à un seul lot de modifications.
Automatisation des tests : il s'agit de la validation programmatique du logiciel en vue d'en garantir la qualité. Les tests peuvent déclencher certaines actions dans le logiciel depuis l'interface utilisateur (nous y reviendrons) ou depuis la couche de services administratifs.
Ces deux pratiques peuvent être comparées au beurre et à la confiture sur du pain grillé : le goût est bon séparément mais c'est encore mieux ensemble ! L'intégration continue associe les builds continus et l'automatisation des tests pour s'assurer que chaque build évalue également la qualité de la base de code.
Et souvenez-vous : pour tirer pleinement parti de tous ces avantages, l'équipe doit également s'obliger à interrompre provisoirement le développement et à traiter les blocages immédiatement. L'énergie qu'une équipe investit (et ne vous y trompez pas, c'est bien un investissement) dans la création de tests et la configuration de leur automatisation est réduite à néant si elle laisse croupir les builds problématiques. La protection de l'investissement dans l'intégration continue et la protection de la qualité de la base de code sont bel et bien la même chose.
Tests dans l'intégration continue : unité, API et tests fonctionnels
L'intégration continue comporte deux phases majeures. La première consiste à s'assurer de la compilation du code. (Ou, dans le cas de langages interprétés, le simple assemblage des différentes pièces.) La seconde phase consiste à s'assurer que le code fonctionne comme prévu. Le moyen le plus sûr d'y parvenir est d'utiliser une série de tests automatisés qui valident tous les niveaux du produit.
Tests d'unités
Les tests d'unités sont exécutés très près des composants fondamentaux du code. En termes de garantie de la qualité, ils forment la première ligne de défense.
Avantages : faciles à créer, ils s'exécutent rapidement et reproduisent strictement l'architecture de la base de code.
Inconvénients : les tests d'unités valident uniquement les composants fondamentaux du logiciel. Ils ne reflètent pas les workflows des utilisateurs, lesquels impliquent souvent l'interaction de plusieurs composants.
Dans la mesure où les tests d'unités expliquent comment le code doit fonctionner, les développeurs peuvent les réviser afin d'actualiser leurs connaissances sur cet aspect du code.
Tests sur les API
Un bon logiciel est un logiciel modulaire qui permet une séparation plus claire des tâches entre plusieurs applications. Les API correspondent aux points de contact entre différents modules. Les tests sur les API les valident en déclenchant des appels d'un module vers un autre.
Avantages : généralement faciles à créer, ils s'exécutent rapidement et peuvent facilement reproduire les interactions entre les applications.
Inconvénients : dans les aspects simples du code, les tests sur les API peuvent imiter certains tests d'unités.
Dans la mesure où les API correspondent aux interfaces entre différentes parties de l'application, elles sont particulièrement utiles lors de la préparation d'une livraison. Lorsqu'un build candidat pour une livraison passe tous les tests sur ses API, l'équipe peut être beaucoup plus sûre d'elle au moment de la livrer aux clients.
Tests fonctionnels
Les tests fonctionnels s'appliquent sur des aspects plus larges de la base de code et reproduisent les workflows des utilisateurs. Dans les applications Web, par exemple, HTTPUnit et Selenium interagissent directement avec l'interface utilisateur pour tester le produit.
Avantages : ils sont plus susceptibles de détecter les bugs, étant donné qu'ils imitent les actions des utilisateurs et testent l'interopérabilité de plusieurs composants.
Inconvénients : plus lents que les tests d'unités, ils génèrent parfois des faux négatifs en raison de la latence du réseau ou d'une panne momentanée quelque part dans la stack technique.
Les équipes estiment souvent qu'en s'approchant du workflow réel de l'utilisateur, la vitesse des tests automatisés diminue. HTTPUnit est plus rapide puisqu'il ne s'agit pas d'un navigateur Web à part entière. Selenium fonctionne à la même vitesse que le navigateur Web mais avec l'avantage de s'exécuter sur plusieurs navigateurs Web en parallèle. Malgré ces mises en garde, les tests fonctionnels sont extrêmement utiles et fournissent un feedback beaucoup plus rapidement que ne le feront jamais des testeurs humains.
Et à propos...
Certains testeurs considèrent les tests automatisés comme une menace existentielle. Mais cette opinion manque de vision et ne pourrait être plus éloignée de la vérité. Libérés de la corvée que représentent les tâches répétitives liées aux tests, les testeurs peuvent consacrer leur temps à l'analyse des risques, à la planification des tests et à l'acquisition de nouvelles compétences, comme apprendre à coder !
Accélérer votre intégration continue
Chez Atlassian, nous faisons tout pour que les développeurs continuent à innover et que nos bases de code restent intègres. Nous mettons particulièrement l'accent sur le resserrement de la « boucle de feedback interne », à savoir le temps nécessaire pour mettre en œuvre des changements et obtenir les résultats des tests.
L'exécution de tests automatisés peut rapidement s'allonger et étirer la durée des builds. Une stratégie consiste à paralléliser les tests automatisés sur plusieurs serveurs (ou « agents de build »). Le serveur d'intégration continue exécute ainsi en réalité 2, 20, voire 200 tests simultanément. Grâce aux technologies dans le Cloud, le processeur peut être facilement adapté pour répondre aux besoins de votre équipe de développement au fur et à mesure de l'expansion de vos suites de tests. Toutefois, le processeur n'est pas illimité. Testez chaque aspect du code de façon complète mais pas redondante. En effet, les tests redondants gonflent la durée du build (et gaspillent le processeur). Plus vite les ingénieurs reçoivent le feu vert, plus vite ils peuvent passer à l'élément suivant dans le backlog.
Création de branches et intégration continue : une association de rêve !
Beaucoup d'équipes évitent la création de branches en raison des problèmes rencontrés lorsqu'elles doivent faire un merge. Les nouvelles technologies en matière de contrôle de versions, telles que Git, facilitent la création de branches et le merge. Pour préserver l'intégrité de la ligne de code principale (« branche principale » en jargon Git), exécutez le même niveau d'intégration continue sur l'ensemble des branches de versions stables et de développement. Lorsque le build arrive dans une branche, l'équipe est sûre de faire le merge de ce code en amont.
Avec la création de branches, l'intégration continue et l'automatisation des tests, les équipes peuvent être productives et innovantes tout en continuant à préserver la qualité du code. Si vous êtes prêt à passer aux étapes suivantes, consultez notre guide étape par étape pour commencer à utiliser l'intégration continue.
Le meilleur côté du développement Agile : livrer régulièrement des logiciels performants, avec une dette technique réduite au minimum et sans compromis en termes d'ingéniosité.