Quality gate
La quality gate est l'un des composants de Squash. Elle peut être utilisée pour affiner les conditions de l'échec ou du succès d'un pipeline comprenant l'étape de l'exécution des tests. La quality gate permet de définir des règles d'évaluation qui précisent le seuil de succès attendu et qui filtrent les tests à évaluer. Ainsi, on peut choisir de faire échouer un pipeline à l'étape des tests dans le cas où moins de 90% des tests d'importance très haute sont en succès. Pour cela, un fichier de définition doit être fourni à la quality gate.
Fichier de définition de la quality gate
Ce fichier doit être au format YAML (.yaml
ou .yml
) et définir au moins une quality
gate qui comporte au moins une règle. Voici l'exemple d'une définition basique :
qualitygates:
- name: my.quality.gate
rules:
- name: JUnit tests
rule:
scope: (test.technology=='junit') && (test.importance=='VERY_HIGH')
threshold: 95%
failure-status: [failure]
Une seule quality gate, my.quality.gate
, est définie dans ce fichier. Elle contient une
règle, JUnit tests
, qui s'applique à des tests JUnit d'importance très haute.
La quality gate sera en succès si au moins 95% des tests sont évalués comme en succès.
Parmi les paramètres, .rules.name
et .rule.failure-status
sont
facultatifs. Si une règle n'a pas de nom, elle se verra attribuer un UUID à la place ;
si failure-status
est omis, sa valeur par défaut sera ['failure', 'error', 'blocked']
.
Un fichier de définition peut définir plusieurs quality gates, et une quality gate peut comporter autant de règles que nécessaire.
Définition du seuil et du filtre
Le seuil (threshold
) d'une règle est un pourcentage compris entre 0% et 100%.
Le filtre (scope
) d'une règle utilise les fonctions et les expressions
qui sont décrites dans la documentation d'OpenTestFactory.
La quality gate utilise le contexte test
de l'orchestrateur, dont les properties sont détaillées
dans le tableau ci-dessous. Depuis ce contexte, on peut également faire appel aux propriétés du plan de test
(itération ou suite de tests) en utilisant test.collection
et aux datasets ou CUF en recourant
à test.data
.
Anciennes versions de Squash TM
️L'ensemble de ces priorités est disponible pour Squash TM 6.0 ou postérieure.
Pour les versions plus anciennes, seules test.technology
, test.uses
, test.runs-on
et test.job
sont utilisables.
Légende
️💎 indique un composant ou une fonctionnalité Ultimate. Une vue d'ensemble des fonctionnalités Premium et Ultimate est disponible ici. Pour en bénéficier ou demander plus d'informations, consulter notre site ou nous contacter.
Propriété | Type | Description | Valeur | test |
---|---|---|---|
test.technology |
string | Technologie du test. |
cucumber, cucumber5, cypress, junit, playwright, postman, robotframework, skf, soapui, agilitest💎, katalon💎, ranorex💎, uft💎
|
test.uses |
string | Action utilisée pour exécuter le test. | Voir les actions des providers dans la documentation d'OpenTestFactory. |
test.runs-on |
object | Tags de l'environnement d'exécution | Utiliser la fonction contains() pour filtrer. |
test.managed |
boolean | Indicateur de test géré par un référentiel de test | true si et seulement si le test est géré par Squash TM (c'est-à-dire qu'il est lancé lors de l'exécution d'un cas de test Squash TM auquel il est lié). |
test.job |
string | Nom du job exécutant le test. | |
test.name |
string | Nom du cas de test dans Squash TM. | Voir le champ respectif dans l'espace "Cas de test". |
test.technology-name |
string | Nom de la technologie du test automatisé affiché dans Squash TM. | Voir la liste déroulante "Technologie du test auto." du bloc "Automatisation" du cas de test. |
test.reference |
string | Référence du cas de test dans Squash TM. | Voir le champ "Référence du test auto." du bloc "Automatisation" du cas de test. |
test.importance |
string | Importance du cas de test dans Squash TM. | VERY_HIGH, HIGH, MEDIUM, LOW |
test.nature |
string | Nature du cas de test dans Squash TM. | NAT_UNDEFINED, NAT_FUNCTIONAL_TESTING, NAT_BUSINESS_TESTING, NAT_USER_TESTING,
NAT_NON_FUNCTIONAL_TESTING, NAT_PERFORMANCE_TESTING, NAT_SECURITY_TESTING, NAT_ATDD |
test.type |
string | Type du cas de test dans Squash TM. | TYP_UNDEFINED, TYP_COMPLIANCE_TESTING, TYP_CORRECTION_TESTING, TYP_REGRESSION_TESTING, TYP_EVOLUTION_TESTING,
TYP_END_TO_END_TESTING, TYP_PARTNER_TESTING |
test.path |
object | Chemin du cas de test dans Squash TM (espace "Cas de test"). | Utiliser la fonction contains() pour filtrer. |
test.collection |
test.collection.path |
object | Chemin du plan de test (itération ou suite) dans Squash TM (espace "Campagnes"). | Utiliser la fonction contains() pour filtrer. |
test.collection.type |
string | Type du plan de test (itération ou suite) dans Squash TM. | iteration , test suite |
test.collection.uuid |
string | UUID du plan de test dans Squash TM. | Voir le champ "UUID" du bloc "Informations" de l'itération ou de la suite de tests. | test.data |
test.data.DSNAME |
string | Nom du jeu de données dans Squash TM. | Voir le champ "NOM" du bloc "Paramètres et jeux de données" du cas de test. |
test.data.DS_{param_name} |
string | Nom du paramètre dans Squash TM. | Tel que défini dans le bloc "Paramètres et jeux de données" du cas de test. |
test.data.TC_EXECUTION_ID 💎 |
string | ID d'exécution dans Squash TM. Disponible uniquement avec Squash TM 8.0 ou une version ultérieure. |
|
test.data.TC_REFERENCE |
string | Référence du test dans Squash TM. | Voir le champ "Référence du cas de test" au-dessus du bloc "Informations" du cas de test. |
test.data.TC_UUID |
string | UUID du cas de test. | |
test.data.TC_CUF_{CUF_CODE} |
string | Champ personnalisé du cas de test dans Squash TM. | |
test.data.TS_CUF_{CUF_CODE} 💎 |
string | Champ personnalisé de la suite de tests dans Squash TM. | |
test.data.IT_CUF_{CUF_CODE} 💎 |
string | Champ personnalisé de l'itération dans Squash TM. | |
test.data.CPG_CUF_{CUF_CODE} 💎 |
string | Champ personnalisé de la campagne dans Squash TM. |
Appliquer la quality gate à un workflow
Transmettre le fichier de définition au service
Pour appliquer une quality gate à un workflow, il faut d'abord transmettre le fichier de définition au service. Il existe deux possibilités pour le faire :
1) Charger le fichier au lancement de l'orchestrateur. Il suffit alors d'ajouter deux paramètres dans la commande de démarrage :
- le point de montage du fichier de définition (en local) sur l'image de l'orchestrateur ;
- la variable d'environnement
QUALITYGATE_DEFINITIONS
qui prendra pour valeur le chemin d'accès du fichier sur l'image.
docker run ... \
-v /path/to/qg_def/my_qualitygate.yaml:/app/qualitygate/my_qualitygate.yaml \
-e QUALITYGATE_DEFINITIONS=/app/qualitygate/my_qualitygate.yaml \
...
docker run ... ^
-v d:\path\to\qg_def\my_qualitygate.yaml:/app/qualitygate/my_qualitygate.yaml ^
-e QUALITYGATE_DEFINITIONS=/app/qualitygate/my_qualitygate.yaml ^
...
docker run ... `
-v d:\path\to\qg_def\my_qualitygate.yaml:/app/qualitygate/my_qualitygate.yaml `
-e QUALITYGATE_DEFINITIONS=/app/qualitygate/my_qualitygate.yaml `
...
Deux quality gates sont toujours chargées au lancement du service : strict
, qui
évalue tous les tests exécutés en utilisant un seuil de 100% et les failure-status
par
défaut, et passing
, dont le seuil de succès est de 0% et qui retournera un résultat
passant quels que soient les résultats de l'exécution.
2) Spécifier le fichier via l'option --using
de la commande opentf-ctl get qualitygate
(détaillée ci-dessous).
Warning
Si le fichier de définition est transmis au service par la commande get qualitygate
,
seules les quality gates définies dans ce fichier peuvent être utilisées. Les quality
gates au niveau du service deviennent inaccessibles.
Évaluer le résultat d'exécution
Pour évaluer le résultat d'exécution des tests d'un workflow, on se servira de la commande
opentf-ctl get qualitygate
, disponible au sein des outils de l'orchestrateur.
La commande opentf-ctl get qualitygate {workflow_id} {options}
évalue un workflow en utilisant
l'ensemble des règles de la quality gate spécifiée par l'utilisateur. Elle retourne le résultat
d'évaluation pour chaque règle ainsi que le résultat d'évaluation général :
opentf-ctl get qualitygate a13f0572-b23b-40bc-a6eb-a12429f0143c --mode my.quality.gate
RULE,RESULT,TESTS_IN_SCOPE,TESTS_FAILED,TESTS_PASSED,SUCCESS_RATIO
JUnit tests,FAILURE,50,10,40,80.0%
Workflow a13f0572-b23b-40bc-a6eb-a12429f0143c failed the quality gate using mode my.quality.gate.
Le paramètre obligatoire de la commande est {workflow_id}
, l'UUID du workflow à évaluer.
Les options sont les suivantes :
--mode
ou-m
. Le nom (name
) de la quality gate.--using
ou-u
. Le chemin du fichier de définition de l'utilisateur.--output wide
ou-o wide
. Ajoute dans le retour de la commande deux colonnes :THRESHOLD
etSCOPE
.
Info
On peut également utiliser l'option --output custom-columns
pour spécifier les colonnes que l'on veut obtenir : voir la documentation d'OpenTestFactory.
L'option --mode
devient obligatoire si le fichier de définition est transmis via l'option
--using
. Si ce dernier a été chargé au niveau de service, la quality
gate strict
sera utilisée si --mode
n'est pas spécifiée.
Chaque règle retourne FAILURE
, SUCCESS
, ou NOTEST
(si aucun test correspondant au filtre
n'a été trouvé). Le résultat général est FAILURE
("workflow failed the quality gate")
si au moins une règle est en échec et SUCCESS
("worklow passed the quality gate") si toutes
les règles sont en succès. Si toutes les règles retournent NOTEST
, le résultat général est
également NOTEST
("workflow contains no test matching quality gate scopes").
Les codes retour de la commande get qualitygate
sont :
0
si le workflow a passé la quality gate avec succès ou si le résultat général estNOTEST
;101
si le workflow est toujours en cours d'exécution ;102
si la quality gate est en échec pour le workflow.
Exemples
Application d'une quality gate définie par l'utilisateur
Prenons un pipeline qui exécute des tests Selenium et des tests Robot Framework au sein d'une même itération Squash TM. On veut que le pipeline passe si :
- au moins 90% de tests avec le tag
Selenium
d'importance haute et très haute sont en succès ; - au moins 75% de tests Robot Framework qui n'utilisent pas le jeu de données
API tests
sont en succès.
Supposons qu'une telle quality gate n'existe pas dans le fichier de définition chargé au niveau de l'orchestrateur.
Dans ce cas, l'utilisateur doit d'abord créer son propre fichier de définition :
qualitygates:
- name: custom.quality.gate
rules:
- name: Selenium tests
rule:
scope: (test.data.TC_CUF_TAG=='Selenium') && ((test.importance=='VERY_HIGH') || (test.importance=='HIGH'))
threshold: 90%
failure-status: [failure]
- name: RobotFramework
rule:
scope: (test.technology=='robotframework') && (test.data.DSNAME!='API tests')
threshold: 75%
failure-status: [failure]
Information
Au lieu de la condition ((test.importance=='VERY_HIGH') || (test.importance=='HIGH'))
, on peut
aussi utiliser contains(fromJSON('["HIGH", "VERY_HIGH"]'), test.importance)
.
Ensuite, s'il sauvegarde le fichier comme custom_quality_gate.yaml
, il doit passer son chemin
à la commande opentf-ctl get qualitygate
:
opentf-ctl get qualitygate {workflow_id} --mode custom.quality.gate --using /home/user/custom_quality_gate.yaml --output wide
Dans cet exemple, l'option --output wide
est utilisée et le retour de la commande contient,
en plus des informations sur l'exécution, le seuil et le filtre définis par l'utilisateur :
RULE,RESULT,TESTS_IN_SCOPE,TESTS_FAILED,TESTS_PASSED,SUCCESS_RATIO,THRESHOLD,SCOPE
Selenium tests,SUCCESS,20,2,18,90.0%,90%,(test.data.TC_CUF_TAG=='Selenium') && ((test.importance=='VERY_HIGH') || (test.importance=='HIGH'))
RobotFramework,SUCCESS,40,5,35,87.5%,75%,(test.technology=='robotframework') && (test.data.DSNAME!='API tests')
Workflow {workflow_id} passed the quality gate using mode custom.quality.gate.
Application d'une règle à l'ensemble des tests du workflow
Si l'on veut appliquer une règle à l'ensemble des tests exécutés au sein
d'un workflow, il suffit de passer au paramètre scope
la valeur true
:
qualitygates:
- name: my.quality.gate
rules:
- name: All tests
rule:
scope: 'true'
threshold: 85%
Filtrage sur les paths
La quality gate permet d'ajouter des filtres sur les chemins des cas de test et/ou
des itérations et des suites de test dans Squash TM. Pour ce faire, il faut
utiliser la fonction contains(search, item)
en indiquant l'élément du chemin (nom
du dossier) sur lequel on veut filtrer.
Ainsi, cette règle évalue les cas de test qui se trouvent dans les dossiers
TNR_main
et TNR_smoketest
du projet WebApp
dans l'espace "Cas de test" de Squash TM:
qualitygates:
- name: my.quality.gate
rules:
- name: TNR
rule:
scope: (contains(test.path, 'TNR_main') || contains(test.path, 'TNR_smoketest')) && contains(test.path('WebApp'))
threshold: 95%
De même, pour ajouter des filtres sur les chemins des itérations et/ou des suites de test,
on utilisera la fonction contains()
avec la property test.collection.path
. Par exemple,
la règle suivante s'applique aux cas de test de l'itération Dropdowns
:
qualitygates:
- name: my.quality.gate
rules:
- name: Dropdowns
rule:
scope: (test.collection.type=='iteration') && contains(test.collection.path, 'Dropdowns')
threshold: 100%
Utilisation de la quality gate dans un pipeline Jenkins
Il est possible d'appliquer la quality gate au sein d'un pipeline Jenkins en
utilisant la commande opentf-ctl get qualitygate
. L'utilisateur doit disposer
d'une instance Jenkins reliée à l'orchestrateur à l'aide du plugin
Jenkins et s'assurer que les outils de l'orchestrateur
(opentf-tools
) sont disponibles dans l'environnement d'exécution Jenkins.
Info
On se reportera aux parties respectives de la présente documentation pour l'installation du plugin, la configuration du plugin et les appels à l'orchestrateur depuis Jenkins.
Une fois la communication entre Jenkins et l'orchestrateur établie, il suffit d'ajouter un appel à la quality gate au sein du pipeline en lui passant l'UUID du workflow exécuté.
Voici l'exemple d'un pipeline qui lance le workflow squash_sample_tests.yaml
et
applique la quality gate sample.quality.gate
(chargée au niveau de l'orchestrateur)
au workflow exécuté :
pipeline {
agent any
environment {
WORKFLOW_ID = ''
}
stages {
stage('Run OTF workflow'){
steps {
script {
WORKFLOW_ID = runOTFWorkflow(
workflowPathName: 'squash_sample_tests.yaml',
workflowTimeout: '300S',
serverName:'Orchestrator',
jobDepth: 2,
stepDepth: 3,
dumpOnError: true
)
}
}
}
stage('Apply quality gate'){
steps {
script {
def qg_command = "opentf-ctl get qualitygate $WORKFLOW_ID --mode sample.quality.gate"
def qg_result = sh(returnStdout: true, script: qg_command)
echo "$qg_result"
}
}
}
}
}
Ce pipeline utilise la variable d'environnement WORKFLOW_ID
qui peut être passée d'une étape
à l'autre. Sa valeur (UUID du workflow exécuté) est récupérée depuis la fonction runOTFWorkflow()
et transmise à la commande get qualitygate
. Le résultat d'exécution de celle-ci est également
récupérée dans une variable et affichée dans la console.
Si la quality gate est en échec, elle retourne le code d'erreur 102
et fait échouer le pipeline.
Si la quality gate est en succès ou ne trouve aucun test à évaluer, elle retourne le code 0
et
le pipeline se termine en succès (ou continue s'il y a d'autres étapes qui suivent).
On peut choisir de ne pas arrêter le pipeline même si le workflow ne passe pas la quality gate.
Dans ce cas, le script shell doit être exécuté avec l'option returnStatus: true
au lieu
de returnStdout: true
. Le step retournera alors le code retour du script, qui
pourra être traité dans les étapes ultérieures.
Utilisation de la quality gate dans un pipeline GitLab
Il est également possible (et même conseillé) d'appliquer la quality gate à un workflow exécuté au sein d'un pipeline GitLab. Un guide détaillé sur l'intégration de Squash Orchestrator avec GitLab CI est disponible dans la documentation d'OpenTestFactory.
Voici l'exemple d'un fichier .gitlab-ci.yml
qui exécute le workflow my_workflow.yaml
et applique
la quality gate, définie dans un fichier utilisateur au sein du projet, chaque fois que
le projet est modifié :
default:
image: python:3.12
stages:
- test
opentf-workflow:
stage: test
script:
- pip install opentf-tools
- RESULT=$(opentf-ctl run workflow .opentf/workflows/my_workflow.yaml --watch)
- WORKFLOW_ID=$(echo $RESULT | head -n 1 |awk -F ' ' '{print $2}')
- opentf-ctl get qualitygate $WORKFLOW_ID --mode sample.quality.gate --using .opentf/qualitygates/my_quality_gate.yaml
La commande pip install
vérifie que la version la plus récente des outils de
l'orchestrateur est disponible sur le runner, et la commande opentf-ctl run...
exécute le workflow avec l'option --watch
pour suivre l'exécution. L'UUID du
workflow est ensuite récupéré dans la variable WORKFLOW_ID
depuis le retour
de la commande.
Enfin, la quality gate sample.quality.gate
, définie dans le fichier my_quality_gate.yaml
,
est appliquée au workflow et son retour est affiché. Si le workflow ne passe pas
la quality gate, le code d'erreur 102
sera retourné et le pipeline sera en échec.
Sans la quality gate, le pipeline sera toujours en succès, quels que soient les résultats des tests.
Publication des résultats de la quality gate dans une merge request
Les résultats de la quality gate peuvent être publiés dans une merge request de
GitLab : il suffit de compléter la commande get qualitygate
en lui passant
les paramètres --plugin gitlab:...
demandés. Le pipeline concerné doit être un merge request pipeline.
Voici l'exemple d'un fichier .gitlab-ci.yml
qui exécute le workflow my_workflow.yaml
et applique la quality gate définie au niveau du service chaque fois qu'un commit
est poussé sur la branche de la merge request. Les résultats de la quality gate sont ensuite
publiés dans cette merge request sous forme d'une note :
default:
image: python:3.12
stages:
- test
opentf-workflow:
stage: test
script:
- pip install opentf-tools
- RESULT=$(opentf-ctl run workflow .opentf/workflows/my_workflow.yaml --watch)
- WORKFLOW_ID=$(echo $RESULT | head -n 1 |awk -F ' ' '{print $2}')
- opentf-ctl get qualitygate $WORKFLOW_ID --mode sample.quality.gate \
--plugin gitlab:keep-history=true \
--plugin gitlab:token={authentication token} \
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
--plugin gitlab:keep-history
est l'unique paramètre obligatoire. S'il vaut true
,
l'historique des résultats de la quality gate définie par --mode
sera gardé dans les notes
de la merge request. S'il vaut false
, une seule note sera ajoutée à la merge request
et sera mise à jour chaque fois que la quality gate est évaluée.
Le paramètre --plugin gitlab:token
permet de définir le token d'accès au projet
si c'est nécessaire.
L'instance de GitLab, le projet et la merge request sont récupérés par défaut
depuis les variables d'environnement prédéfinies de GitLab (à savoir
CI_SERVER_URL
, CI_MERGE_REQUEST_PROJECT_ID
et CI_MERGE_REQUEST_IID
). Il est
toutefois possible de définir sa propre instance GitLab, l'ID du projet et l'IID
de la merge request en utilisant les paramètres gitlab:server
, gitlab:project
et gitlab:mr
.
On peut aussi ajouter à la merge request un label qui affiche le statut de la quality gate.
Il faut d'abord créer, au niveau du projet GitLab, trois labels correspondant aux statuts
possibles de la quality gate : {prefix}::Passed
, {prefix}::Failed
et {prefix}::No test
.
C'est à l'utilisateur de choisir le préfixe. Ensuite, il faut ajouter à la commande
get qualitygate
le paramètre --plugin gitlab:label={prefix}
.
Il est également possible de publier les résultats de la quality gate dans l'issue liée
à la merge request. Voici l'exemple d'un pipeline qui exécute le workflow my_workflow.yaml
,
applique la quality gate à ce workflow et envoie les résultats vers l'issue correspondante.
L'IID de l'issue est récupéré depuis la description de la merge request, qui doit le contenir
par défaut :
default:
image: python:3.12
stages:
- test
opentf-workflow:
stage: test
script:
- pip install opentf-tools
- RESULT=$(opentf-ctl run workflow .opentf/workflows/my_workflow.yaml --watch)
- WORKFLOW_ID=$(echo $RESULT | head -n 1 |awk -F ' ' '{print $2}')
- MR_DATA="$(curl --header "PRIVATE-TOKEN:{authentication token}" \ "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID" | sed 's/\\"//g')"
- ISSUE_IID=$(python -c "import json; data = json.loads('$MR_DATA'); print(data.get('description'))" | head -1 | sed 's/.*#//')
- opentf-ctl get qualitygate $WORKFLOW_ID --mode sample.quality.gate \
--plugin gitlab:keep-history=false \
--plugin gitlab:issue=$ISSUE_IID
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
La liste complète des options GitLab de la commande opentf-ctl get
qualitygate
est disponible dans la documentation d'OpenTestFactory.