Lecture du debut d annee:
le devops ou la philosophie de la communication/outillage/monitoring pour pousser le concept de la gestion du cycle de vie du logiciel comme d un logiciel comme un autre...
et une relecture d un livre toujours d actualité sur l agilité et l importance de l humain dans le développement. Un livre donc que je conseille qui meme apres 13 ans de sa premiere lecture m apprend toujours des choses.
Differents mais complementaire allez y!
Affichage des articles dont le libellé est DevOps. Afficher tous les articles
Affichage des articles dont le libellé est DevOps. Afficher tous les articles
jeudi 31 janvier 2019
lundi 31 décembre 2018
Docker - Plugin Maven
Un petit écart dans la liste des articles qui devaient être publiés prochainement en abordant le sujet du packaging de nos builds maven dans des images Docker.
On parle d'écart mais en fait pas tant que ca car nous verrons que OSGI se prête bien à une intégration dans docker. Bref ca c’est une autre histoire.
Tout le monde connaît Docker, au moins de nom. Il s’agit d’une solution de conteneurisation [docker-pub], assimilable à de la “virtualisation allégé” (ok le raccourci est rapide) permettant de construire des architectures scalables [scala] de type [microservice] (nous en reparlerons).
L’approche classique pour construire une image docker et d’utiliser la commande “docker build”, si vous êtes un habitué de l’outil, sera de construire un Dockerfile. Je vous laisse pour cela aller consulter l’article [docker-base].
Cependant cette approche en ligne de commande, bien que pratique car universelle n’est pas forcément immédiate dans le cadre d’une industrialisation comme d’un build maven qui aurait pour résultat non pas un artifact java classique [integ-java] mais une image docker prête à l’emploi pour les tests ou la production (vous le voyez poindre le concept de Déploiement Continu?).
Heureusement pour répondre à ce problème il existe deux plugins maven [compar]:
A cela, il permet aussi de gérer le cycle de vie des conteneurs en activité (start/stop/kill etc...) ainsi que de publier les images sur un repository (comme le DockerHub [DocHub])
Le plus simple pour présenter le plugin est d’en faire la démonstration.
Ainsi considérons un projet java construit forcément avec un process maven. L’idée d’un build est de généralement construire jar. Dans une approche standard de packaging, le process maven appliquera une phase d’assemblage dans laquelle, le jar, sa conf et ses éventuellement dépendances seront mis dans un targz, un paquet debian où tout autre format de livraison.
Avec docker, le concept permettant d'exécuter un conteneur à partir d’une image quelque soit la plateforme permet d’imaginer une rationalisation du moyen de livraison et d'exécution.
Ainsi, parce que nous utilisons maven, nous allons enrichir un pom parent avec une configuration pluginManagement du plugin fabric8io. L’idée est alors de permettre à tout pom héritant de celui-ci de construire une image docker de packaging et d'exécution.
Ainsi la pré configuration maven du plugin permet de façon générale de donner un nom à l’image et spécifier ses informations générales (nom, mainteneur) dans la section “image”.
Ensuite dans une section build on va préciser le contenu de l’image en utilisant les mécanismes d’assembly maven que l’on devra préciser dans le fichier “assembly/assembly-docker.xml”
Enfin en coherence avec la logique des plugins maven se constituant d’une partie configuration et d’une partie exécution, dans cette dernière, on va préciser quelle commande docker nous allons appliquer.
Ici on notera qu’il y a deux profiles maven, l’un DOCKER de base qui apporte la configuration et la construction de l’image et un second PUSH dans lequel on appliquera la commande “push” de docker (cela nécessitera l’utilisation de la propriété docker.login précisant le compte du DockerHub associé et présent dans le nom de l’image)
L’utilisation de ce pom parent passe ensuite par la surcharge du profile DOCKER dans une section plugin (le profile PUSH étant directement hérité).
La surcharge est rapide bien qu’un peu verbeuse à cause du profile maven. (à noter que dans un process complet et générique on pourra in fine s’en passer)
Dans ce pom, il s’agira juste de completer les parties manquantes c’est à dire:
Ici nous utiliserons l’image openjdk:8-jre-alpine comme image source que nous allons configurer le port JMX de la JVM et que nous lancerons l’application via un script sh.
Pour ce qui concerne l’assembly, il s’agit à ce niveau d’une assembly standard utilisant des section “dependencySets” et “fileSets”. Je vous invite à consulter la documentation du plugin [plugass] et/ou de lire l’article [assem].
Voilà avec ce plugin, du coup il est possible de construire des images docker contenant directement notre build prêt à l’emploi nous facilitant d’une part la diffusion du livrable mais aussi l’exploitation dans des tests et surtout l’exploitation en production.
[docker-base] https://un-est-tout-et-tout-est-un.blogspot.com/2017/09/docker-construire-son-image.html
[scala] https://fr.wikipedia.org/wiki/Scalability
[integ-java] https://runnable.com/docker/java/dockerize-your-java-application
[microservice] https://fr.wikipedia.org/wiki/Microservices
[spotify] https://github.com/spotify/docker-maven-plugin
[spotify-2] https://github.com/spotify/dockerfile-maven
[fabric8io] https://github.com/fabric8io/docker-maven-plugin
[doc-fabric] http://dmp.fabric8.io/
[compar] https://dzone.com/articles/meet-the-docker-maven-plugin
[assembly-maven] http://maven.apache.org/plugins/maven-assembly-plugin/
[DocHub] https://hub.docker.com/
[assem] https://un-est-tout-et-tout-est-un.blogspot.com/2018/03/maven-assembly-targz-et-jdeb.html
[plugass] https://maven.apache.org/plugins/maven-assembly-plugin/single-mojo.html
On parle d'écart mais en fait pas tant que ca car nous verrons que OSGI se prête bien à une intégration dans docker. Bref ca c’est une autre histoire.
Tout le monde connaît Docker, au moins de nom. Il s’agit d’une solution de conteneurisation [docker-pub], assimilable à de la “virtualisation allégé” (ok le raccourci est rapide) permettant de construire des architectures scalables [scala] de type [microservice] (nous en reparlerons).
L’approche classique pour construire une image docker et d’utiliser la commande “docker build”, si vous êtes un habitué de l’outil, sera de construire un Dockerfile. Je vous laisse pour cela aller consulter l’article [docker-base].
Cependant cette approche en ligne de commande, bien que pratique car universelle n’est pas forcément immédiate dans le cadre d’une industrialisation comme d’un build maven qui aurait pour résultat non pas un artifact java classique [integ-java] mais une image docker prête à l’emploi pour les tests ou la production (vous le voyez poindre le concept de Déploiement Continu?).
Heureusement pour répondre à ce problème il existe deux plugins maven [compar]:
- spotify/maven-docker-plugin [spotify], et sa nouvelle version [spotify-2] spotify/dokerfile-maven-plugin
- fabric8io/maven-docker-plugin [fabric8io]
Spotify
Ce plugin maven est celui ci qui collera le plus avec la logique d’utilisation de docker.
En effet, ce plugin s’utilise de façon assez simple soit par configuration xml sur les éléments basiques qu’un dockerfile pourrait contenir où en spécifiant directement un répertoire où se trouvera un dockerfile.
Ainsi ce plugin va permettre de réaliser la phase de build de la commande docker mais aussi en complément la phase de push pour livrer l’image ainsi construite dans un repository comme le docker hub [DocHub].
On pourra regretter que ce plugin ne permet pas de lancer lui même des conteneurs, chose qui aurait pu être intéressant pour la réalisation de phase de tests.
Dans le cadre de cet article, comme dans celui de [compar], nous ne nous attarderons pas sur ce plugin qui finalement fait bien son taff mais ne fournira pas en dehors du cadre de l'intégration à maven beaucoup plus de fonctionnalité que de faire son Dockerfile nous même.
En effet, ce plugin s’utilise de façon assez simple soit par configuration xml sur les éléments basiques qu’un dockerfile pourrait contenir où en spécifiant directement un répertoire où se trouvera un dockerfile.
Ainsi ce plugin va permettre de réaliser la phase de build de la commande docker mais aussi en complément la phase de push pour livrer l’image ainsi construite dans un repository comme le docker hub [DocHub].
On pourra regretter que ce plugin ne permet pas de lancer lui même des conteneurs, chose qui aurait pu être intéressant pour la réalisation de phase de tests.
Dans le cadre de cet article, comme dans celui de [compar], nous ne nous attarderons pas sur ce plugin qui finalement fait bien son taff mais ne fournira pas en dehors du cadre de l'intégration à maven beaucoup plus de fonctionnalité que de faire son Dockerfile nous même.
Fabric8io
Le plugin fabric8io sort quand à lui plus des sentier battu en ne s’appuyant pas du tout sur un dockerfile mais sur une approche plus classique dans un environnement maven. En effet, ce plugin propose d’utiliser un descriptif xml du Dockerfile [doc-fabric] ainsi que le mécanisme des assembly [assembly-maven].A cela, il permet aussi de gérer le cycle de vie des conteneurs en activité (start/stop/kill etc...) ainsi que de publier les images sur un repository (comme le DockerHub [DocHub])
Le plus simple pour présenter le plugin est d’en faire la démonstration.
Ainsi considérons un projet java construit forcément avec un process maven. L’idée d’un build est de généralement construire jar. Dans une approche standard de packaging, le process maven appliquera une phase d’assemblage dans laquelle, le jar, sa conf et ses éventuellement dépendances seront mis dans un targz, un paquet debian où tout autre format de livraison.
Avec docker, le concept permettant d'exécuter un conteneur à partir d’une image quelque soit la plateforme permet d’imaginer une rationalisation du moyen de livraison et d'exécution.
Ainsi, parce que nous utilisons maven, nous allons enrichir un pom parent avec une configuration pluginManagement du plugin fabric8io. L’idée est alors de permettre à tout pom héritant de celui-ci de construire une image docker de packaging et d'exécution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <profiles> <profile> <id>DOCKER</id> <build> <pluginManagement> <plugins> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.27.2</version> <configuration> <images> <image> <name>${docker.login}/${project.artifactId}:%l</name> <alias>${project.artifactId}</alias> <build> <maintainer>Collonville Thomas collonville.thomas@gmail.com</maintainer> <!-- <dockerFile>Dockerfile</dockerFile> --> <assembly> <mode>dir</mode> <permissions>auto</permissions> <targetDir>/</targetDir> <descriptor>../assembly/assembly-docker.xml</descriptor> </assembly> </build> </image> </images> </configuration> <executions> <execution> <id>start</id> <phase>verify</phase> <goals> <goal>build</goal> </goals> </execution> </executions> </plugin> </plugins> </pluginManagement> </build> </profile> <profile> <id>PUSH</id> <build> <pluginManagement> <plugins> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.27.2</version> <executions> <execution> <id>start</id> <phase>verify</phase> <goals> <goal>build</goal> <goal>push</goal> </goals> </execution> </executions> </plugin> </plugins> </pluginManagement> </build> </profile> </profiles> |
Ainsi la pré configuration maven du plugin permet de façon générale de donner un nom à l’image et spécifier ses informations générales (nom, mainteneur) dans la section “image”.
Ensuite dans une section build on va préciser le contenu de l’image en utilisant les mécanismes d’assembly maven que l’on devra préciser dans le fichier “assembly/assembly-docker.xml”
Enfin en coherence avec la logique des plugins maven se constituant d’une partie configuration et d’une partie exécution, dans cette dernière, on va préciser quelle commande docker nous allons appliquer.
Ici on notera qu’il y a deux profiles maven, l’un DOCKER de base qui apporte la configuration et la construction de l’image et un second PUSH dans lequel on appliquera la commande “push” de docker (cela nécessitera l’utilisation de la propriété docker.login précisant le compte du DockerHub associé et présent dans le nom de l’image)
L’utilisation de ce pom parent passe ensuite par la surcharge du profile DOCKER dans une section plugin (le profile PUSH étant directement hérité).
La surcharge est rapide bien qu’un peu verbeuse à cause du profile maven. (à noter que dans un process complet et générique on pourra in fine s’en passer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <profiles> <profile> <id>DOCKER</id> <build> <plugins> <plugin> <groupId>io.fabric8</groupId> <artifactId>docker-maven-plugin</artifactId> <configuration> <images> <image> <build> <from>openjdk:8-jre-alpine</from> <cmd>/opt/equinox-loader/docker.sh</cmd> <ports> <port>${jmx.port}</port> </ports> </build> </image> </images> </configuration> </plugin> </plugins> </build> </profile> </profiles> |
Dans ce pom, il s’agira juste de completer les parties manquantes c’est à dire:
- l’image source utilisé
- une commande de lancement
- les ports et les volumes à déclarer
- pour finir le contenu de l’assembly, faisant office de commande ADD et COPY d’un Dockerfile
Ici nous utiliserons l’image openjdk:8-jre-alpine comme image source que nous allons configurer le port JMX de la JVM et que nous lancerons l’application via un script sh.
Pour ce qui concerne l’assembly, il s’agit à ce niveau d’une assembly standard utilisant des section “dependencySets” et “fileSets”. Je vous invite à consulter la documentation du plugin [plugass] et/ou de lire l’article [assem].
Voilà avec ce plugin, du coup il est possible de construire des images docker contenant directement notre build prêt à l’emploi nous facilitant d’une part la diffusion du livrable mais aussi l’exploitation dans des tests et surtout l’exploitation en production.
Références
[docker-pub] https://un-est-tout-et-tout-est-un.blogspot.com/2017/10/docker-publier.html[docker-base] https://un-est-tout-et-tout-est-un.blogspot.com/2017/09/docker-construire-son-image.html
[scala] https://fr.wikipedia.org/wiki/Scalability
[integ-java] https://runnable.com/docker/java/dockerize-your-java-application
[microservice] https://fr.wikipedia.org/wiki/Microservices
[spotify] https://github.com/spotify/docker-maven-plugin
[spotify-2] https://github.com/spotify/dockerfile-maven
[fabric8io] https://github.com/fabric8io/docker-maven-plugin
[doc-fabric] http://dmp.fabric8.io/
[compar] https://dzone.com/articles/meet-the-docker-maven-plugin
[assembly-maven] http://maven.apache.org/plugins/maven-assembly-plugin/
[DocHub] https://hub.docker.com/
[assem] https://un-est-tout-et-tout-est-un.blogspot.com/2018/03/maven-assembly-targz-et-jdeb.html
[plugass] https://maven.apache.org/plugins/maven-assembly-plugin/single-mojo.html
dimanche 1 juillet 2018
Alors Cochon ou Poulet?
Encore un sujet de réflexion ce matin sur l’allégorie du restaurant du poulet et du cochon portée par l'approche agile Scrum.
En effet dans Scrum [1], on utilise souvent cet exemple pour mettre en avant l'importance des rôles des uns et des autres dans une équipe agile et surtout leur niveau de responsabilité et d'implication.
L'exemple est simple:
Un poulet propose a un cochon d'ouvrir un restaurant: il propose comme deal de participer au restaurant en donnant ses œufs, et de son coté le cochon lui devra donner son lard. Le cochon refuse en expliquant que le degré d’implication de l'un et de l'autre ne sont pas les même. En effet, le poulet, en donnant ses œufs, ne fait que participer, alors que le cochon, en donnant une part de lui même, est bien plus impliqué.
Cet exemple est frappant car il met en évidence une problématique proprement humaine et relationnelle : Au sein d'une équipe, comment positionner le degré de responsabilité d'un individu et le degré de pertinence a accorder a ses propos ?
L'exemple du Poulet et du Cochon, nous donne quelques réponses en identifiant au sein du projet quels sont les cochons et les poulets, ceux qui s'engagent personnellement et matériellement (comme le Product Owner, le Scrum master qui eux portent l'engagement) et ceux qui "ne font" que participer au processus (les développeurs par exemple dont l'engagement se limite au périmètre du sprint).
L'article [2] pousse le raisonnement en identifiant d'autres profils d'acteurs gravitant autour de l’équipe ou même présent en son sein. On notera le profil Mouette qui est l'individu se mêlant de ce qui ne le concerne pas et fini par perturber l’équipe par des protestations et conseils mal avisé.
Personnellement je considère que cet exemple est même généralisable a des spectres d'applications bien plus large que simplement le cadre d'une équipe agile et dans toutes activités, il convient d'identifier les cochons, les poulets et les mouettes afin de donner a chacun le degré de responsabilité, son poids dans la prise de décision et son degré de crédibilité (dans un approche qui pourrait être bayésienne)
Ainsi par exemple prenons le contexte DevOps [3], cette approche cherche a impliquer plus fortement les développeur dans les besoins de l'exploitation mais ne sommes nous pas justement dans un paradoxe puisque dans cette démarche, les développeurs, ne sont que des poulets face aux exploitants qui eux sont les cochons?
Alors vous lecteurs, vous êtes quoi? Poulet? Cochon? ou je l’espère pas Mouette?
Références
[1] https://un-est-tout-et-tout-est-un.blogspot.com/search?q=Scrum
[2] https://thescrumcoach.wordpress.com/2013/03/02/poulet-ou-cochon-scrum-animal-farm/
[3] https://blog.clever-age.com/fr/2012/04/17/le-mouvement-devops/
En effet dans Scrum [1], on utilise souvent cet exemple pour mettre en avant l'importance des rôles des uns et des autres dans une équipe agile et surtout leur niveau de responsabilité et d'implication.
L'exemple est simple:
Un poulet propose a un cochon d'ouvrir un restaurant: il propose comme deal de participer au restaurant en donnant ses œufs, et de son coté le cochon lui devra donner son lard. Le cochon refuse en expliquant que le degré d’implication de l'un et de l'autre ne sont pas les même. En effet, le poulet, en donnant ses œufs, ne fait que participer, alors que le cochon, en donnant une part de lui même, est bien plus impliqué.
Cet exemple est frappant car il met en évidence une problématique proprement humaine et relationnelle : Au sein d'une équipe, comment positionner le degré de responsabilité d'un individu et le degré de pertinence a accorder a ses propos ?
L'exemple du Poulet et du Cochon, nous donne quelques réponses en identifiant au sein du projet quels sont les cochons et les poulets, ceux qui s'engagent personnellement et matériellement (comme le Product Owner, le Scrum master qui eux portent l'engagement) et ceux qui "ne font" que participer au processus (les développeurs par exemple dont l'engagement se limite au périmètre du sprint).
L'article [2] pousse le raisonnement en identifiant d'autres profils d'acteurs gravitant autour de l’équipe ou même présent en son sein. On notera le profil Mouette qui est l'individu se mêlant de ce qui ne le concerne pas et fini par perturber l’équipe par des protestations et conseils mal avisé.
Personnellement je considère que cet exemple est même généralisable a des spectres d'applications bien plus large que simplement le cadre d'une équipe agile et dans toutes activités, il convient d'identifier les cochons, les poulets et les mouettes afin de donner a chacun le degré de responsabilité, son poids dans la prise de décision et son degré de crédibilité (dans un approche qui pourrait être bayésienne)
Ainsi par exemple prenons le contexte DevOps [3], cette approche cherche a impliquer plus fortement les développeur dans les besoins de l'exploitation mais ne sommes nous pas justement dans un paradoxe puisque dans cette démarche, les développeurs, ne sont que des poulets face aux exploitants qui eux sont les cochons?
Alors vous lecteurs, vous êtes quoi? Poulet? Cochon? ou je l’espère pas Mouette?
Références
[1] https://un-est-tout-et-tout-est-un.blogspot.com/search?q=Scrum
[2] https://thescrumcoach.wordpress.com/2013/03/02/poulet-ou-cochon-scrum-animal-farm/
[3] https://blog.clever-age.com/fr/2012/04/17/le-mouvement-devops/
Libellés :
Agile,
bayesianisme,
DevOps,
Scrum
lundi 16 avril 2018
Les tests logiciels
Problématique
Dans le développement logiciel, la plus grande des préoccupations est que ce qui est attendu par le client soit effectivement ce qui sera livré. Pour répondre à cette problématique, le client mettra probablement en place des moyens permettant de faire la recette du logiciel livré et vérifier que les fonctionnalités attendues sont bien présentes. Attendre cette étape du processus serait un grave erreur. Ainsi, il importe de faire ces vérifications avant cette étape et afin de garantir le moins de mauvaises surprises possibles.Contexte
Pour faire ces vérifications, l’approche classique consiste à définir un plan de stratégie de test (STP). A ce stade j’en imagine déjà certains en train de dire, pfff, des tests, de la doc, tout ca c’est ca a rien à voir avec le développement logiciel! Et bien ils se trompent car définir une stratégie de test est tout aussi important que d’avoir formalisé les besoins (auxquels les tests vont données des moyens de validation), d’avoir défini une architecture (qui sera aussi validé par les tests) où d’avoir un processus de développement (qui pourra s’appuyer sur les tests pour qualifier le logiciel et permettre son déroulement).Ainsi le test est partout, dans tous les processus, à toutes les étapes, à tous les niveaux d’abstractions et il permet même de faciliter le développement en guidant le développeur en adoptant la démarche TDD (test driven development).
Dans cet article je vous propose dans un premier temps de revenir sur la définition d’un test puis de regarder les éléments faisant partie du plan de stratégie et d’identifier l’ensemble des types de tests qui peuvent être réalisés, leur objectifs et l’outillage éventuellement nécessaire pour les mettre en oeuvre.
Définition du test
Un test est une procédure permettant pour une assertion données de déclarer si celle ci est vrai ou fausse. Cette assertion est généralement la confrontation du résultat d’un calcul où d’une procédure comparé avec un résultat attendu.La procédure permettant la mise en oeuvre d’un test consiste généralement à considérer l'élément à tester comme une noire de façon à ne pas préjuger de son implémentation et de ne se fier qu'à ses contrats d’interfaces (Par exemple pour une méthode, ce sont ses paramètres et retour, pour un composant, ce sont ses interfaces, pour un web service, le wsdl).
Enfin il reste à définir des scénarios d'exécution à l’aide de jeux de données d’entrées et de données attendues. A noter que si le composant a tester nécessite des dépendances, alors il convient de les déboucher avec des artefacts simulant le fonctionnement de celles-ci.
L'exécution des tests se doit alors de couvrir l’ensemble des fonctions attendues du composant,reproductible et constante dans le temps. Test de recette
Tout d’abord et nous venons d’en parler, il a le test de recette. Ce test est un test permettant au client de valider la livraison sur un certain périmètre fonctionnel plus où moins grand selon les modifications apportées au logiciel dans la version.
C’est en toute logique l'équipe en charge du développement qui va proposer le protocole et le contenu du test de recette afin d’une part de permettre au client de le valider en amont de la livraison et également faciliter la reproductibilité de celui-ci. Ainsi sur des livraisons mineures et si la confiance est suffisante, ces tests pourront même être joué par l'équipe sur la base du protocole validé. Un compte rendu des tests sera ensuite livrés en même temps que le produit afin d’en attester des fonctionnalités. Le client aura alors toute la latitude de rejouer où non la version et les tests afin d’en vérifier les résultats prétendu obtenu par l'équipe.
Dans le plan de stratégie de test, le test de recette est évidemment indispensable et forcément majeur. Cependant, il n’est pas réaliste de croire que d’une part faire des tests pour la livraison est faisable surtout après plusieurs semaines de développement, et d’autre part que le client va s’en satisfaire.
Test du développement et de l’intégration continue
Pour répondre a ces problèmes, généralement, il est proposé de réaliser des tests en différents point du processus de développement et d’intégration du logiciel et ce de façon régulière (de préférence journalière). Cette approche qui nécessite souvent d'être automatisé (on peut même affirmer que c’est incontournable) permet l’identification au plus tôt des régressions éventuellement. Nous avions vu le principe de l'intégration continu dans l’article [1], il s’agit ici textuellement de la mise en oeuvre de cette partie du processus.Différents types de tests pourront être distingué :
- Les tests unitaires
- Les test technique
- Les test d’interface
- Les test integration
- Les test de Base de données
- Les test d’IHM
- Les test fonctionnel
- Les test bout en bout
- Les test de qualimétrie
L’outil classique et le plus polyvalent pour répondre à la grande partie des mises en oeuvre des tests est indéniablement Robotframework [12]. Dédié le plus souvent aux tests fonctionnels, il permet de construire des DSL modélisant l’environnement des tests à réaliser permettant de l’adapter à tout type de test, que ce soit technique que fonctionnel. Tests unitaires
En entré du processus d’IC, viennent les branches de développement. Ces branches sont issues du travaille des développeurs qui auront, selon les aspects techniques et les éléments fonctionnels impactés, ajoutés ou mis à jours les tests unitaires.
Les test unitaires sont des tests locaux sur les éléments du développement en cours dont le périmètre doit se restreindre au maximum aux briques essentielles de ce développement. Généralement les tests se limitent à la granularité minimal du code, en proposant un cadre exhaustif d'utilisation d’une méthode où plus largement d’une classe. Pour cela, de nombreux frameworks sont disponibles fournissant des primitives de tests facilitant la vérification de résultats attendus (le plus connu étant JUnit [2]) où fournissant des moyens de simplifications pour la mise en oeuvre des tests en facilitant soit la construction de jeux de données ou le bouchonnage de dépendances par la construction de Mock (soutenu par le framework Mockito [3] par exemple).
Les démarches de construction des tests unitaires sont variables. La pratique courante et que le développeur en charge de la réalisation d’une évolution se charge également de la réalisation du test. Ceci est considéré comme une mauvaise pratique pour deux raisons:
Tout d’abord, un test a pour but de démontrer une erreur dans la réalisation d’une fonction or généralement, les gens sont plutôt d’accord avec eux même. Il est vrai que parfois en écrivant le test, on se rend compte d’oubli mais le test n’est pas initialement le moment de comprendre le besoin, il ne sert qu'à démontrer le bon fonctionnement. On préconise donc que le test soit écrit par un autre développeur sachant que cela nécessite alors que les deux développeurs se mettent d’accord avec les interfaces du composant à tester/réaliser.
Second point, on préconise également pour faciliter la mise en oeuvre de la fonction que les tests soient défini préalablement afin de faciliter la compréhension de la fonction, la validation de celle-ci et d’avoir une mesure plus évidente de l’avancement. On appelle cette démarche le TDD (Test Driven Development)
De façon générale, les tests unitaires sont joués par le développeur lors du développement mais aussi lors de corrections dans l’objectif de contrôler la non régression technique où fonctionnel car même si les TU doivent être développé indépendamment, le code l’est rarement et parfois, avec des mocks, modifier une fonction et son test ne suffit pas pour garantir que tous les tests continueront à être valide. Ainsi de façon a ce que l'exécution des tests ne soient pas trop long il est indispensable de les faire simple et concis. Car il est évident que si l'exécution des tests prennent plus de 30 min à être exécuté par le développeur, ils auront à terme plus de chance de ne plus être exécuté….
Test technique
Le test technique est un test de haut niveau dont la portée n’est pas de garantir un besoin client mais la validation de où d’une partie de la solution technique. Ainsi un test technique ne cherche pas à garantir le but mais le moyen. Par exemple, on peut considérer que les TU sont une sorte de test technique, tout comme les tests sur des web services, d'intégration, de charge, de robustesse, de base de données d’IHM où encore de qualimétrie, etc…Généralement si le processus de développement définit convenablement son référentiel documentaire et que celui ci s’appuie sur des exigences, alors le test technique permet la validation des exigences du cahier de conception (où d’architecture)
Test intégration
Les tests d'intégration sont des tests techniques primordiaux dans la vie de systèmes logiciels. On peut les considérer de deux sortes:des tests d'intégration horizontaux qui traitent généralement des problématiques d'intégration propre aux choix d’architectures telles que les architectures modulaires et/ou réparti
des test verticaux traitant de la capacité de compatibilité des logiciels entre eux (par exemple, la capacité d’installation, configuration, désinstallation, mise a jours sur une où plusieurs type d’OS où dans des conteneurs d’applications différents)
Ces test sont souvent complexe à mener car difficile à automatiser et nécessitant une expertise transverse à l’ensemble des composants. De plus, les outils utilisables restent très spécifiques à chaque type d’interface à intégrer ainsi, il sera nécessaire de constituer des équipes conséquentes pour gérer une trop forte hétérogénéité surtout dans le cas de systèmes logiciels conséquent qui nécessitent souvent des plateformes d'intégrations dédiés
Test de Base de données
L’utilisation de base de données est incontournable dans les systèmes logiciels actuel. Il s’agit généralement d’un composant critique du système contenant toutes les informations relatives à l’exploitation du métier du client.La vérification de base de données consiste généralement en la vérification des accès aux données, à la coherence d’insertion respectant les contraintes d'intégrités et que la suppression de données permet de conserver une base de données également intégrée et cohérente.
Pour faire ce genre de test, on pourra employer des outils facilitant la création, suppression et modification des données tels que Liquibase [4], dbdeploy [5] où JHipster [6].
Test d’IHM
Souvent considérés à tort comme des tests fonctionnels, les tests d’IHM sont en fait des tests techniques dont l’objet est la vérification d’ergonomie de l’application (qu’elle soit web où stand alone) et la présence effective des informations et contrôleurs permettant les interactions du client.La confusion entre test fonctionnel et test ihm est simple, elle provient de la simplification de la stratégie de vérification en proposant dans une plateforme d'intégration (donc relativement complète techniquement) des procédures déroulant les cas d’utilisation du client. Ces procédures (généralement réalisées manuellement et considérées comme des tests fonctionnels) sont en fait des tests de recette permettant une couverture non-exhaustive des fonctionnalités. S'ils permettent d’avoir un bon apriori sur le périmètre fonctionnel viable il n’en donne pas une information réelle. De même nous verrons dans un chapitre suivant qu'à l’inverse un test fonctionnel n’est pas forcément un test d’IHM.
La mise en oeuvre de test d’IHM est complexe car la boite noire a tester est l’IHM dans son environnement d'exécution. Ainsi le point d’entrée d’une IHM est généralement un écran, un clavier et une souris et donc s’assimile souvent à des images corrélées à des événements claviers/souris ainsi que la position de cette dernière.
Pour répondre à ce genre de problématiques, il existe deux approches: La première consiste a considérer l'écran tel quel le voit l’utilisateur et d’enregistrer les actions utilisateurs et déplacement souris. Ainsi, suite a l’enregistrement il sera possible de rejouer le test. Cette approche est proposé par des outils comme Selenium [7] et Sikuli [8]. Bien que peu robuste aux modifications même infime d’IHM, ces approches sont difficiles à maintenir. La seconde approche consiste à utiliser des outils d’introspection capable d’identifier les composants de l’IHM pendant leur exécution et de simuler les actions d’un utilisateur. Dans cette approche, l’avantage est clairement la simplification des tests qui alors devient des tests classiques presque unitaire. Cependant, tous les framework d’IHM ne permettent cette approche car si en Java Swing, il sera facile d’utiliser Fest [9], dès que l’on utilisera une IHM Web, il sera nécessaire de se rabattre sur des tests utilisant l’approche précédente.
Test de qualimétrie
Les tests de qualimétrie sont des tests technique portant sur la qualité du logiciel en terme de vulnérabilité, maintenabilité, bug potentiel, couverture de test et duplication de code. Ces informations sont élaborées par des outils exploitant les phases de compilations, de test unitaire où de tests spécifiques. Ainsi dans ce contexte le plus connu est probablement aujourd’hui Sonar [10] qui permet la consolidation de ces différents critères.A noter quand dans la pratique, ces informations sont trop souvent négligé à tort car les configurations par défaut s'appuient sur les recommandations construites par les communautés et fournissent un cadre formatif très poussé pour comprendre beaucoup de subtilités des langages traités
Test de charge
Les tests de charges sont des tests techniques où l’application est mise en situation de fonctionnement nominal avec des fluctuations sur les débits des flux entrant.Le but de ce type de test est de visualiser le comportement du système dans les cas normaux et également aux limites, lorsque celui-ci est sollicité de façon exagérée. On procédera souvent a des mesure de temps de traversé des données et des temps de réponse du composant pour la prise en compte des sollicitations.
Ces tests ne sont pas souvent mise en oeuvre car étant coûteux à mettre en oeuvre même si des outils existent comme JMeter [11]
Test de robustesse
Le test de robustesse, comme le test de charge est un type de test technique où le but est la mise en situation critique du logiciel soit sur des cas d’utilisation non prévu, soit dans les cas de défaillances pendant lesquels, le logiciel doit être en mesure soit de continuer à assurer le service soit au mieux permettre aux services parallèles de continuer à fonctionner. Les tests de robustesses sont à définir sur de nombreux plans, des TU aux tests d’IHM, aux tests de base de données où même de charge.Le cas typique du test de robustesse est la résistance à des données d’entrée corrompu susceptible de corrompre le fonctionnement.
Test fonctionnel
Souvent confondu avec les tests d’IHM comme nous en avons parlé précédemment, les tests fonctionnels sont défini sur la base de la définition du besoin du client. Ils permettent de vérifier la faisabilité et la cohérence fonctionnelle du besoin en formalisant et scénarisant son utilisation. Ainsi le test fonctionnel (et ses UC) sert de référentiel pour la couverture complète du besoin et est généralement la base pour la constitution des tests de recettes qui en forme souvent un sous ensemble lorsque ces derniers traitent des IHM.Test bout en bout
Lest test bout en bout regroupent l’ensemble des tests permettant la traversé complète du système logiciel, du point d’entré jusqu’aux bases de données en incluant les retours de données éventuels. Selon le test, cela ne signifie pas forcément la même chose, il est évident que toutes les fonctions ne réalisent pas les mêmes trajets, mais c’est l'intérêt de ces tests finalement: fournir une couverture exhaustive de l’ensemble des traversés possibles du système.Dans ce genre de test, l’utilisation d’outils comme Robotframework est indispensable en permettant de construire des DSL spécifique a chaque type de test bout en bout rencontré. Cela nécessitera cependant la création de bouchons afin donner l’impression que les systèmes externes sont opérant.
Conclusion
Voilà nous arrivons au bout de ce long article sur les tests. Ils sont souvent complexe à réaliser et s’appliquent sur divers aspects du système logiciel, a tous les niveaux d’abstraction et selon des méthodes et des approches variés. Pourtant même les tests ne sont pas forcément à la hauteur du système logiciel qu’ils doivent validé, Ils sont indispensables à la qualité du produit et à la confiance que le client pourra donner au système logiciel. Ainsi, il n’est jamais bon de négliger les testsRéférences
[1] http://un-est-tout-et-tout-est-un.blogspot.fr/2018/02/integration-continue.html[2] https://junit.org/junit5/
[3] http://site.mockito.org/
[4] https://www.liquibase.org/
[5] http://dbdeploy.com/
[6] https://www.jhipster.tech/
[7] https://www.seleniumhq.org/
[8] http://www.sikuli.org/
[9] https://un-est-tout-et-tout-est-un.blogspot.fr/2018/01/test-dihm-fest-util.html
[10] https://about.sonarcloud.io/
[11] https://jmeter.apache.org/
[12] http://robotframework.org/
Libellés :
Agile,
architecture,
boite noire,
Bout en bout,
build,
DevOps,
Fest,
IHM,
Intégration continue,
qualimetrie,
robotframework,
selenium,
sikuli,
Sonar,
test,
test fonctionnel,
TU
samedi 24 février 2018
Agilité: Combinatoire d'activité
Dans un article précédent [1] nous avons vu un modèle de processus de développement dans lequel je faisais intervenir 5 acteurs clefs responsables des axes majeurs intervenant dans le développement logiciel:

Je suis bien sûr très intéressé par votre opinion concernant mon avis sur le sujet. Alors n’hésitez pas à mettre des commentaires.
[1] http://un-est-tout-et-tout-est-un.blogspot.fr/2018/02/integration-continue.html
- axe fonctionnel : le PO
- axe technique : l’architecte
- axe process : le scrum master
- axe IVQ : le responsable IVQ (Intégration Validation Qualification)
- axe savoir faire : le développeur

Je suis bien sûr très intéressé par votre opinion concernant mon avis sur le sujet. Alors n’hésitez pas à mettre des commentaires.
Références:
[1] http://un-est-tout-et-tout-est-un.blogspot.fr/2018/02/integration-continue.html
Libellés :
Agile,
Conception,
DevOps,
IC IntegrationContinu,
processus de développement,
Scrum
mercredi 21 février 2018
Intégration continue
Petit aparté pour parler un peu de l'intégration continu. Nous avions évoqué un peu le sujet dans l’article précédent [1] sur Gradle qui en est tout comme Maven [2] un élément et outil central à la construction d’un composant logiciel. Cependant, si nous avions décrit son rôle dans le processus de développement, nous n'avons pas décrit qu’elles sont les autres outils qui peuvent nous aider a automatiser l’ensemble du processus, nous aider à mener à bien l’entreprise de production logiciel complet, de A a Z.

Sans forcément faire un long discours explicatif des différents éléments de ce schéma (qui n’est qu’un modèle parmi d’autres possibles), nous pouvons décrire ce processus comme suit:
Différents acteurs cités ici ont des rôles spécialisés selon les différents axes majeurs du développement logiciels :
Nous avons déjà parler de l’approche agile mais nous pouvons constater ici qu’une phase importante du processus concerne la sortie de la partie cyclique. Cette phase peut être appeler livraison car elle correspond à la finalisation du ou des développements, et correspond au final à la livraison d’un nouvel incrément fonctionnel par l’ajout de nouveaux morceaux de code. Il faut comprendre que cette phase n’est pas terminale mais itérative comme l’est le développement et consiste à soutenir le développement en permettant la validation/livraison a chaque itération.

Ceci n’est cependant clairement pas suffisant car si un ajout de code peut être correct sur le poste du développeur et même en considérant que ce poste est conforme à un standard commun à toute l'équipe, il persistera toujours des différences sans compter les différences évidentes entre le poste de dev et la configuration d’un serveur cible.
Dans les faits, les sources sont récupérées par un outil d'orchestration tel que Jenkins [7] ou Travis [8] qui par configuration va appliquer un certain nombre de processus via un outil de build comme maven ou gradle ou directement sur la branche contenant les sources.
Procéduralement l’outil d’orchestration va devoir:
Ces nouvelles approches permettent au développeur de disposer d’un environnement de test ( voir de développement) local beaucoup plus proche et conforme à ce que sera la cible chez le client. Ces approches portées par des logiciels comme Docker fournissent des moyens beaucoup plus simple et élémentaires de validation et d'intégration en rapprochant le développeur de la plateforme cible cependant, elle nécessite l’utilisation par le client d’architecture spécifique basé sur ce type de conteneur.
Facilitant d’un coté la maintenance, ces solutions doivent malgré tout, “en solution de virtualisation”, fournir des moyens de sécurisation et d’optimisation des performances au moins équivalentes aux solutions conventionnelles.
Il n’en reste pas moins que l'intégration continu est un environnement fortement outillé. Certains de ces outils, comme Maven, Gradle ou même la production documentaire, ont été évoqué dans différents articles. Pour les prochains articles, afin d’affiner notre vision des possibilités de l'intégration continu et des architectures possible la guidant, nous tacherons de rentrer un peu plus dans le détails de ces autres outils
[2] http://un-est-tout-et-tout-est-un.blogspot.com/2017/12/maven-introduction.html
[3] http://un-est-tout-et-tout-est-un.blogspot.com/2017/12/les-processus-de-developpement-ou.html
[4] https://git-scm.com/
[5] https://subversion.apache.org/
[6] https://www.mercurial-scm.org/
[7] https://jenkins.io/
[8] https://travis-ci.org/
[9] https://maven.apache.org/
[10] https://gradle.org/
[11] https://jfrog.com/artifactory/
[12] https://www.sonatype.com/nexus-repository-sonatype
[13] http://robotframework.org/
[14] http://www.sikuli.org/
[15] https://www.sonarqube.org/
[16] https://maven.apache.org/plugins/maven-site-plugin/
[17] https://maven.apache.org/plugins/maven-javadoc-plugin/
Contextualisation
Repartons d’un processus de développement de base. Nous en avions vu quelques un dans l’article [3]. En voici un, sûrement perfectible, dans lequel nous utilisons une approche agile au sein de laquelle vont intervenir nos outils d'intégration continue.
Sans forcément faire un long discours explicatif des différents éléments de ce schéma (qui n’est qu’un modèle parmi d’autres possibles), nous pouvons décrire ce processus comme suit:
A partir de l’idée du client, sont définies un certain nombre de spécifications fonctionnelles plus ou moins raffinées. Ces spécification sont injectées, une fois suffisamment mature et dont la valeur ajoutée est considérée comme suffisamment significative, dans un certain nombre de Sprint sous la forme de Stories fonctionnelles et ou techniques. Le but final de l’approche étant de produire un certain nombre d'artefacts évoluant au fil d’un certain nombre de versions
Différents acteurs cités ici ont des rôles spécialisés selon les différents axes majeurs du développement logiciels :
- axe fonctionnel : le PO
- axe technique : l’architecte
- axe process : le scrum master
- axe IVQ : le responsable IVQ (Intégration Validation Qualification)
- axe savoir faire : le développeur
Nous avons déjà parler de l’approche agile mais nous pouvons constater ici qu’une phase importante du processus concerne la sortie de la partie cyclique. Cette phase peut être appeler livraison car elle correspond à la finalisation du ou des développements, et correspond au final à la livraison d’un nouvel incrément fonctionnel par l’ajout de nouveaux morceaux de code. Il faut comprendre que cette phase n’est pas terminale mais itérative comme l’est le développement et consiste à soutenir le développement en permettant la validation/livraison a chaque itération.
L'integration Continue
Cette phase est en fait appeler la phase d’intégration continue. Elle provient du besoin de tester systématiquement le code source et les nouvelles fonctionnalités apportées tout en garantissant la non régression des fonctionnalités déjà développées précédemment.
Mot d'ordre : automatisation
Dans ce schéma, le processus d'intégration continu fait intervenir un ensemble de composants en interaction et répondant à différents besoins. En entrée de l'intégration continu nous avons l’outil de gestion des sources (tel que Git [4], SVN [5] ou Mercurial [6]) dans lequel les développeurs déposeront le code produit et tester localement unitairement.Ceci n’est cependant clairement pas suffisant car si un ajout de code peut être correct sur le poste du développeur et même en considérant que ce poste est conforme à un standard commun à toute l'équipe, il persistera toujours des différences sans compter les différences évidentes entre le poste de dev et la configuration d’un serveur cible.
Feed-back
Pour résoudre ces problèmes, intervient alors la phase d'intégration continu. Elle va permettre de procéder à une construction complète, automatisé et régulière de l’ensemble du composant logiciel soit de façon journalière, soit a chaque modification du référentiel de code, voir les deux. En procédant ainsi, l'intégration continu permettra la validation dans des plateforme de référence, de l’ensemble de fonctionnalités en déroulant l’ensemble des tests prévus (à noter que ces tests sont définis selon des niveaux différents, N1: tests unitaires, N2 tests d'intégrations, N3 : tests fonctionnels; les niveaux N2 et N3 sont souvent fusionnés). Les tests une fois validés, les développement réalisés par les développeurs sont alors intégré ensemble au sein d’une même branche ou de nouvelles validations sont déroulées (voila le coté intégration en continu).Dans les faits, les sources sont récupérées par un outil d'orchestration tel que Jenkins [7] ou Travis [8] qui par configuration va appliquer un certain nombre de processus via un outil de build comme maven ou gradle ou directement sur la branche contenant les sources.
Procéduralement l’outil d’orchestration va devoir:
- construire le composant (via maven [9] ou gradle [10]) en s’appuyant sur un entrepôt de composant (artifactory [11] ou nexus [12])
- utiliser les éléments produit pour effectuer des tests unitaires
- utiliser les éléments produit pour effectuer des tests fonctionnels dans un plateforme cible (virtuelle VM/docker ou non) avec des outils tels que robotframework [13] , sikuli [14]
- effectuer de l’analyse de code à l’aide d’un outil comme sonar [15]
- produire de la documentation à l’aide d’outils comme maven site [16] ou java doc [17]
Vers le continuous delivery et le DevOps
En parallèle de cette approche ou le but est de vérifier au plus tôt l’absence de défauts mais aussi de problème d'intégration, il est considéré aujourd’hui de nouvelles approches par l’utilisation de conteneur versionable et livrable directement au client.Ces nouvelles approches permettent au développeur de disposer d’un environnement de test ( voir de développement) local beaucoup plus proche et conforme à ce que sera la cible chez le client. Ces approches portées par des logiciels comme Docker fournissent des moyens beaucoup plus simple et élémentaires de validation et d'intégration en rapprochant le développeur de la plateforme cible cependant, elle nécessite l’utilisation par le client d’architecture spécifique basé sur ce type de conteneur.
Facilitant d’un coté la maintenance, ces solutions doivent malgré tout, “en solution de virtualisation”, fournir des moyens de sécurisation et d’optimisation des performances au moins équivalentes aux solutions conventionnelles.
Conclusion
Dans ce blog, nous avons déjà traité des sujets tels que Docker. Il ne fait aucun doute que ce type de technologies ont leur adepte, et à juste titre. Cependant, même si ces approches ont leur avantages, il me semble que les approches conventionnelles (parce que omniprésente) gardent elles aussi leur points forts et que les solutions de productions logicielles futurs devront surtout composer avec des approches mixtes.Il n’en reste pas moins que l'intégration continu est un environnement fortement outillé. Certains de ces outils, comme Maven, Gradle ou même la production documentaire, ont été évoqué dans différents articles. Pour les prochains articles, afin d’affiner notre vision des possibilités de l'intégration continu et des architectures possible la guidant, nous tacherons de rentrer un peu plus dans le détails de ces autres outils
References
[1] http://un-est-tout-et-tout-est-un.blogspot.com/2018/01/gradle.html[2] http://un-est-tout-et-tout-est-un.blogspot.com/2017/12/maven-introduction.html
[3] http://un-est-tout-et-tout-est-un.blogspot.com/2017/12/les-processus-de-developpement-ou.html
[4] https://git-scm.com/
[5] https://subversion.apache.org/
[6] https://www.mercurial-scm.org/
[7] https://jenkins.io/
[8] https://travis-ci.org/
[9] https://maven.apache.org/
[10] https://gradle.org/
[11] https://jfrog.com/artifactory/
[12] https://www.sonatype.com/nexus-repository-sonatype
[13] http://robotframework.org/
[14] http://www.sikuli.org/
[15] https://www.sonarqube.org/
[16] https://maven.apache.org/plugins/maven-site-plugin/
[17] https://maven.apache.org/plugins/maven-javadoc-plugin/
Libellés :
Agile,
analyse,
architecture,
Artifactory,
Conception,
construction,
DevOps,
Docker,
Gradle,
IC IntegrationContinu,
Jenkins,
Maven,
processus de développement,
Scrum,
Travis
Inscription à :
Articles (Atom)