Logomotion: Qualification
This commit is contained in:
parent
68a2e82bf2
commit
675ad0fb70
|
@ -1,4 +1,4 @@
|
||||||
<style>pre, table { font-size: 0.6em !important; }</style>
|
<style>pre, table { font-size: 0.5em !important; }</style>
|
||||||
|
|
||||||
# Qualification et intégration continue
|
# Qualification et intégration continue
|
||||||
|
|
||||||
|
@ -17,7 +17,9 @@ William Petit - S.C.O.P. Cadoles
|
||||||
|
|
||||||
## Les tests applicatifs
|
## Les tests applicatifs
|
||||||
|
|
||||||
Les tests applicatifs ont pour objectif de valider le bon fonctionnement de l'application d'un point de vue métier, c'est à dire de vérifier que celle ci répond aux attentes et aux contraintes du client d'un point de vue fonctionnel.
|
Les tests applicatifs ont pour objectif de valider le bon fonctionnement de l'application d'un point de vue métier, c'est à dire de vérifier que celle ci répond aux attentes et aux contraintes du client d'un point de vue fonctionnel.
|
||||||
|
|
||||||
|
Ils permettent également et surtout aux développeurs de **détecter les régressions** dans le cycle de développement.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -35,6 +37,8 @@ Les tests applicatifs ont pour objectif de valider le bon fonctionnement de l'ap
|
||||||
|
|
||||||
Tester le bon fonctionnement des plus petites unités logiques/fonctionnelles de l'application: les fonctions/méthodes d'objets.
|
Tester le bon fonctionnement des plus petites unités logiques/fonctionnelles de l'application: les fonctions/méthodes d'objets.
|
||||||
|
|
||||||
|
**Exemple** Vérifier qu'une méthode de calcul du prix taxé d'un produit retourne la valeur attendue en fonction des paramètres passés.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Cycle de vie
|
## Cycle de vie
|
||||||
|
@ -49,7 +53,7 @@ Tester le bon fonctionnement des plus petites unités logiques/fonctionnelles de
|
||||||
## Caractéristiques clés
|
## Caractéristiques clés
|
||||||
|
|
||||||
- Ils sont nombreux.
|
- Ils sont nombreux.
|
||||||
- Ils sont mis en place dès le début de l'implémentation, voir avant.
|
- Ils sont mis en place dès le début de l'implémentation, voir avant (voir "Test Driven Development").
|
||||||
- Ils sont rapides à exécuter.
|
- Ils sont rapides à exécuter.
|
||||||
- Ils permettent de détecter rapidement les régressions.
|
- Ils permettent de détecter rapidement les régressions.
|
||||||
- Ils permettent de rassurer le développeur qui doit apporter des évolutions à une base de code existante.
|
- Ils permettent de rassurer le développeur qui doit apporter des évolutions à une base de code existante.
|
||||||
|
@ -60,13 +64,42 @@ Tester le bon fonctionnement des plus petites unités logiques/fonctionnelles de
|
||||||
|
|
||||||
## Exemple: Tests unitaires en Javascript (Mocha)
|
## Exemple: Tests unitaires en Javascript (Mocha)
|
||||||
|
|
||||||
TODO
|
```javascript
|
||||||
|
// Fichier test/my-test-suite.js
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
// Déclaration de la suite de tests
|
||||||
|
describe('My suite', function() {
|
||||||
|
|
||||||
|
// Test synchrone
|
||||||
|
it('should not fail', function() {
|
||||||
|
assert.equal(true, 1); // true == 1 en javascript
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test asynchrone
|
||||||
|
it('should do something async', function() {
|
||||||
|
|
||||||
|
return doSomethingAsync()
|
||||||
|
.then(result => {
|
||||||
|
assert.ok(result); // On vérifie que le résultat n'est pas null
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
assert.ifError(err); // On vérifie qu'aucune erreur n'est remontée
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Exemple: Tests unitaires en PHP (Symfony3)
|
## Et le style dans tout ça ?
|
||||||
|
|
||||||
TODO
|
- Javascript: https://eslint.org/
|
||||||
|
- PHP: https://github.com/phpro/grumphp
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -76,9 +109,10 @@ Soit un numéro de carte bancaire donné, implémenter un test pour la fonction
|
||||||
|
|
||||||
**Ressources**
|
**Ressources**
|
||||||
|
|
||||||
|
- [Mocha - Librairie de test](https://mochajs.org/)
|
||||||
|
- [Module `assert`](https://nodejs.org/api/assert.html)
|
||||||
- [La formule de Luhn](https://fr.wikipedia.org/wiki/Formule_de_Luhn)
|
- [La formule de Luhn](https://fr.wikipedia.org/wiki/Formule_de_Luhn)
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Tests d'intégration
|
## Tests d'intégration
|
||||||
|
@ -87,7 +121,9 @@ Soit un numéro de carte bancaire donné, implémenter un test pour la fonction
|
||||||
|
|
||||||
## Objectifs
|
## Objectifs
|
||||||
|
|
||||||
Tester la bonne communication des différents "modules" composant une application.
|
Tester la bonne communication et interaction des différents "modules" composant une application.
|
||||||
|
|
||||||
|
**Exemple** Vérifier que qu'une transaction est correctement enregistrée dans la base de données lorsque le module de paiement est utilisé.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -113,9 +149,18 @@ Les tests d'intégration peuvent être un bon témoin/validateur de l'état de r
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Exemple: Test de la soumission d'un formulaire (Symfony3)
|
## Exemple: Test d'une API REST avec Symfony3
|
||||||
|
|
||||||
TODO
|
1. Implémenter une API JSON/REST basique avec Symfony3 permettant d'enregistrer/lister dans une base de données (sqlite3) une "annonce" avec les propriétés suivantes:
|
||||||
|
- Titre
|
||||||
|
- Description
|
||||||
|
- Type
|
||||||
|
- Prix
|
||||||
|
2. Implémenter avec la librairie standard de Symfony3 les tests suivants:
|
||||||
|
- Ajout d'une nouvelle annonce et vérification du bon enregistrement de la nouvelle annonce via un appel sur l'URL d'affichage des annonces
|
||||||
|
|
||||||
|
**Ressources**
|
||||||
|
- [Symfony3 - Working with the Test client](http://symfony.com/doc/current/testing.html#working-with-the-test-client)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -142,7 +187,7 @@ Tester le bon fonctionnement de l'application d'un point de vue utilisateur.
|
||||||
|
|
||||||
## Cycle de vie
|
## Cycle de vie
|
||||||
|
|
||||||
Les tests fonctionnels devraient être implémentés une fois que l'itération a été validée par le client.
|
Les tests fonctionnels devraient être implémentés une fois que l'itération a atteint une certaine stabilité en terme d'interface utilisateur.
|
||||||
|
|
||||||
Ils ne devraient être modifiés que lorsque le client demande une évolution de l'interface utilisateur et/ou des cinématiques d'action.
|
Ils ne devraient être modifiés que lorsque le client demande une évolution de l'interface utilisateur et/ou des cinématiques d'action.
|
||||||
|
|
||||||
|
@ -150,13 +195,13 @@ Ils ne devraient être modifiés que lorsque le client demande une évolution de
|
||||||
|
|
||||||
## Exemple: Tests fonctionnels Web avec NightmareJS
|
## Exemple: Tests fonctionnels Web avec NightmareJS
|
||||||
|
|
||||||
TODO
|
Voir l'exemple `tests-fonctionnels`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Exercice: Tester une procédure d'authentification d'un utilisateur
|
## Exercice: Simuler un utilisateur avec le client web KiwiIRC
|
||||||
|
|
||||||
TODO
|
Via NightmareJS et avec le client [KiwiIRC](https://kiwiirc.com/nextclient/), se connecter au serveur `irc.freenode.net`, rejoindre le canal `#cadoles` en tapant la commande `/join <canal>` puis envoyer un message sur le canal nouvellement rejoint.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -194,7 +239,9 @@ Les tests de charge devraient être exécutés régulièrement afin de vérifier
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Exemple: Utilisation d'Apache Benchmark pour vérifier le temps de réponse d'une application Web
|
## Exemple: Utilisation de Siege pour vérifier les temps de réponse d'une application Web
|
||||||
|
|
||||||
|
https://www.joedog.org/siege-home/
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -229,21 +276,30 @@ Ils doivent être réactualisés lors de tout changement d'infrastructure et de
|
||||||
|
|
||||||
## Exemple: Vérification de sécurité pour les dépendances PHP
|
## Exemple: Vérification de sécurité pour les dépendances PHP
|
||||||
|
|
||||||
TODO https://github.com/sensiolabs/security-checker
|
https://github.com/sensiolabs/security-checker
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Exemple: Tests d'attaques automatisées sur les applications Web avec w3af
|
## Exemple: Audit automatisé sur les applications Web avec w3af
|
||||||
|
|
||||||
TODO https://tools.kali.org/web-applications/w3af
|
https://github.com/andresriancho/w3af/
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Les serveurs d'intégration continue
|
## Le cycle (simplifié) d'intégration continue
|
||||||
|
|
||||||
|
![center 60%](./img/cycle_dintgration_continue.png?1)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Technologies de conteneurisation
|
## Automatisation, virtualisation et conteneurisation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principes généraux sur les conteneurs
|
||||||
|
|
||||||
|
- Les conteneurs sont un mécanisme de virtualisation basée sur l'isolation des processus au niveau du système d'exploitation.
|
||||||
|
- Ils bénéficient d'une très faible perte de performances brutes par rapport à de la virtualisation classique utilisation des mécanismes d'émulation.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -251,12 +307,151 @@ TODO https://tools.kali.org/web-applications/w3af
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Manipuler des images de conteneur
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exécuter un conteneur
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gérer les conteneurs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Partager des répertoires
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configurer le réseau d'un conteneur
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Construire une image
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Publier une image sur le Hub
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Utiliser `docker-compose`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Le fichier `docker-compose.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2' # Version du fichier docker-compose
|
||||||
|
services: # Déclaration des services
|
||||||
|
faketools: # Service 'faketools'
|
||||||
|
build: # Création de l'image du conteneur depuis un dossier du projet
|
||||||
|
context: .
|
||||||
|
dockerfile: containers/faketools/Dockerfile
|
||||||
|
args: # Déclaration d'arguments de construction de l'image
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY}
|
||||||
|
http_proxy: ${http_proxy}
|
||||||
|
https_proxy: ${https_proxy}
|
||||||
|
ports: # Déclaration des ports à exposer sur la machine hôte
|
||||||
|
- "8080:8080"
|
||||||
|
- "8081:8081"
|
||||||
|
- "2525:2525"
|
||||||
|
- "3389:3389"
|
||||||
|
- "8443:8443"
|
||||||
|
- "2222:22"
|
||||||
|
volumes: # Déclaration des montages de volumes
|
||||||
|
- ./data:/faketools/data
|
||||||
|
environment: # Déclaration de variables d'environnement
|
||||||
|
HTTP_PROXY: ${HTTP_PROXY}
|
||||||
|
HTTPS_PROXY: ${HTTPS_PROXY}
|
||||||
|
http_proxy: ${http_proxy}
|
||||||
|
https_proxy: ${https_proxy}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercice
|
||||||
|
|
||||||
|
Créer un environnement de développement `docker-compose` à partir de l'image `ubuntu:xenial` pour une application Symfony3 et une base de données MySQL avec l'image `mysql:latest`.
|
||||||
|
|
||||||
|
Le répertoire des sources locales devra être partagé avec le conteneur d'application et le port du conteneur exposé sur la machine hôte.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Les serveurs d'intégration continue
|
||||||
|
|
||||||
|
https://docs.gitlab.com/ce/ci/
|
||||||
|
https://jenkins.io/
|
||||||
|
https://drone.io/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Exemple: Gitlab et Gitlab Runner
|
## Exemple: Gitlab et Gitlab Runner
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Le fichier `.gitlab-ci.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Déclaration de variables utilisables dans le fichier
|
||||||
|
variables:
|
||||||
|
MY_VAR: Hello World
|
||||||
|
|
||||||
|
# Nom de l'image Docker à utiliser pour les différentes phases du pipeline
|
||||||
|
image: <image_docker>
|
||||||
|
|
||||||
|
# Listes de commandes à exécuter dans le conteneur
|
||||||
|
# avant le lancement des différents jobs
|
||||||
|
before_script:
|
||||||
|
- echo ${MY_VAR}
|
||||||
|
|
||||||
|
# Déclaration des phases du pipeline
|
||||||
|
stages:
|
||||||
|
- test
|
||||||
|
- dist
|
||||||
|
|
||||||
|
# Déclaration d'un job
|
||||||
|
unit-tests:
|
||||||
|
stage: test # Ce job est attaché à la phase "test"
|
||||||
|
script: # Commandes à exécuter dans le conteneur
|
||||||
|
- ./script/test
|
||||||
|
|
||||||
|
# Déclaration d'un autre job
|
||||||
|
dist:
|
||||||
|
stage: dist # Ce job est attaché à la phase "dist"
|
||||||
|
only: # Ce job ne doit s'exécuter que lorsque la branche est "master"
|
||||||
|
refs:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- ./script/dist
|
||||||
|
artifacts: # Artefacts à conserver à l'issue de la phase
|
||||||
|
paths:
|
||||||
|
- dist/*.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exécuter un pipeline en local
|
||||||
|
|
||||||
|
<pre style="font-size:0.8em!important">
|
||||||
|
gitlab-runner exec docker [job]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
> La fonctionnalité est dépréciée depuis la version 10.0. Voir la discussion https://gitlab.com/gitlab-org/gitlab-runner/issues/2797 pour le futur remplacement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Exercice: Mise en application générale
|
## Exercice: Mise en application générale
|
||||||
|
|
||||||
|
Sélectionner une application existante (ou laissez le formateur vous proposer un sujet) et:
|
||||||
|
|
||||||
|
1. Mettre en place l'exécution des tests unitaires sur le projet et écrire une première suite de tests.
|
||||||
|
2. Mettre en place les tests d'intégration sur le projet et écrire une première suite de tests.
|
||||||
|
3. Mettre en place les tests fonctionnels et écrire une première suite de tests.
|
||||||
|
4. Concevoir un "pipeline" d'intégration continue avec Gitlab et Gitlab Runner et tester une activation complète du pipeline.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Licence
|
# Licence
|
||||||
|
|
Loading…
Reference in New Issue