Jenkins

Ce guide montre comment lancer un test JMeter LoadFocus depuis un pipeline Jenkins, attendre sa fin et faire échouer le build quand un seuil n'est pas respecté. Il utilise le LoadFocus API Client (loadfocus-api, installé depuis npm). Créez et enregistrez d'abord le test dans LoadFocus, voir Comment exécuter un nouveau test de charge Apache JMeter ; le pipeline lance ce test enregistré par son nom, donc --name doit être le nom exact de votre test enregistré.

run-test lance le test enregistré, attend sa fin et vérifie les seuils. Si un seuil n'est pas respecté, ou si l'exécution échoue, la commande se termine avec le code 1 et l'étape sh échoue. Les seuils sont vérifiés séparément pour chaque libellé de requête, et errors est un nombre de requêtes en échec, pas un pourcentage. Dans les exemples ci-dessous, remplacez My_JMeter_Test, API_Performance_Test et UI_Performance_Test par les noms exacts de vos tests enregistrés.

Le fichier de résultats commence par quelques lignes de progression avant l'objet JSON ; readJSON file: ne peut donc pas l'analyser tel quel. Les exemples qui lisent le fichier le lisent comme du texte et le coupent à la première ligne qui ne contient que {. L'étape readJSON provient du plugin Pipeline Utility Steps.

Étapes de configuration

1. Stocker les identifiants dans Jenkins

Tout d'abord, stockez vos identifiants API LoadFocus de manière sécurisée dans Jenkins :

  1. Accédez à Jenkins Dashboard > Manage Jenkins > Manage Credentials
  2. Sélectionnez le domaine d'identifiants approprié (par exemple, global)
  3. Cliquez sur "Add Credentials"
  4. Ajoutez les identifiants suivants :
    • Kind : Secret text
    • Scope : Global
    • Secret : Votre clé API LoadFocus
    • ID : loadfocus-api-key
    • Description : LoadFocus API Key
  5. Répétez l'opération pour votre ID d'équipe avec ID : loadfocus-team-id

2. Créer un pipeline Jenkins

Créez un Jenkinsfile dans votre dépôt :

pipeline {
agent {
docker {
image 'node:16-alpine'
}
}
environment {
LOADFOCUS_API_KEY = credentials('loadfocus-api-key')
LOADFOCUS_TEAM_ID = credentials('loadfocus-team-id')
}
stages {
stage('Build') {
steps {
// Vos etapes de build
sh 'npm install'
sh 'npm run build'
}
}
stage('Test') {
steps {
// Vos etapes de test
sh 'npm test'
}
}
stage('Performance Test') {
steps {
// Installer le client API JMeter de LoadFocus
sh 'npm install -g @loadfocus/loadfocus-api-client'
// Configurer le client API LoadFocus
sh 'loadfocus-api config set --apikey $LOADFOCUS_API_KEY --teamid $LOADFOCUS_TEAM_ID'
// Exécuter les tests de performance (--name est le nom exact d'un test enregistré dans LoadFocus)
sh '''
loadfocus-api jmeter run-test \
--name "My_JMeter_Test" \
--thresholds "avgresponse<=200,errors==0,p95<=250" \
--format json > performance_results.json
'''
// Archiver les resultats
archiveArtifacts artifacts: 'performance_results.json', fingerprint: true
}
}
stage('Deploy') {
when {
expression {
return currentBuild.resultIsBetterOrEqualTo('SUCCESS')
}
}
steps {
// Vos etapes de deploiement
echo 'Deploying...'
}
}
}
post {
always {
// Nettoyer l'espace de travail
cleanWs()
}
}
}

3. Configurer le job Jenkins

  1. Créez un nouveau job Pipeline dans Jenkins
  2. Configurez le Pipeline pour utiliser votre Jenkinsfile
  3. Configurez la gestion SCM appropriée pour récupérer votre dépôt

Configuration avancée

Pipeline déclaratif avec tests parallèles

Exécutez plusieurs tests de performance en parallèle. Votre forfait LoadFocus limite le nombre de tests pouvant s'exécuter simultanément ; au-delà, le client signale "Maximum number of parallel tests exceeded for your plan." :

pipeline {
agent any
environment {
LOADFOCUS_API_KEY = credentials('loadfocus-api-key')
LOADFOCUS_TEAM_ID = credentials('loadfocus-team-id')
}
stages {
// Etapes precedentes...
stage('Performance Tests') {
parallel {
stage('API Performance') {
agent {
docker {
image 'node:16-alpine'
}
}
steps {
sh 'npm install -g @loadfocus/loadfocus-api-client'
sh 'loadfocus-api config set --apikey $LOADFOCUS_API_KEY --teamid $LOADFOCUS_TEAM_ID'
sh '''
loadfocus-api jmeter run-test \
--name "API_Performance_Test" \
--thresholds "avgresponse<=150,errors==0" \
--format json > api_performance_results.json
'''
archiveArtifacts artifacts: 'api_performance_results.json', fingerprint: true
}
}
stage('UI Performance') {
agent {
docker {
image 'node:16-alpine'
}
}
steps {
sh 'npm install -g @loadfocus/loadfocus-api-client'
sh 'loadfocus-api config set --apikey $LOADFOCUS_API_KEY --teamid $LOADFOCUS_TEAM_ID'
sh '''
loadfocus-api jmeter run-test \
--name "UI_Performance_Test" \
--thresholds "avgresponse<=300,errors==0" \
--format json > ui_performance_results.json
'''
archiveArtifacts artifacts: 'ui_performance_results.json', fingerprint: true
}
}
}
}
// Etapes suivantes...
}
}

Pipeline scripté

Pour plus de flexibilité, utilisez un pipeline scripté. Comme sh échoue quand run-test se termine avec le code 1 (un seuil non respecté), le bloc catch ci-dessous s'exécute aussi bien pour un seuil non respecté que pour une erreur :

node {
def performanceTestPassed = false
stage('Checkout') {
checkout scm
}
stage('Build & Test') {
// Vos etapes de build et de test
}
stage('Performance Test') {
docker.image('node:16-alpine').inside {
withCredentials([
string(credentialsId: 'loadfocus-api-key', variable: 'LOADFOCUS_API_KEY'),
string(credentialsId: 'loadfocus-team-id', variable: 'LOADFOCUS_TEAM_ID')
]) {
sh 'npm install -g @loadfocus/loadfocus-api-client'
sh 'loadfocus-api config set --apikey $LOADFOCUS_API_KEY --teamid $LOADFOCUS_TEAM_ID'
try {
sh '''
loadfocus-api jmeter run-test \
--name "My_JMeter_Test" \
--thresholds "avgresponse<=200,errors==0,p95<=250" \
--format json > performance_results.json
'''
// Verifier si le test a reussi en examinant le JSON
def raw = readFile('performance_results.json')
def testResults = readJSON text: raw.substring(raw.indexOf('\n{') + 1)
if (testResults.overallResult == 'PASSED') {
performanceTestPassed = true
echo "Performance test passed!"
} else {
echo "Performance test failed to meet thresholds!"
// Optionnel : Faire echouer le build
// error "Performance test failed"
}
} catch (Exception e) {
echo "Error running performance test: ${e.message}"
}
archiveArtifacts artifacts: 'performance_results.json', fingerprint: true
}
}
}
stage('Deploy') {
if (performanceTestPassed) {
echo 'Deploying...'
// Vos etapes de deploiement
} else {
echo 'Skipping deployment due to performance test failure'
}
}
}

Bibliothèque partagée

Créez une bibliothèque partagée pour les tests de performance réutilisables :

// vars/performanceTest.groovy
def call(Map config = [:]) {
def testName = config.testName ?: "My_JMeter_Test"
def thresholds = config.thresholds ?: "avgresponse<=200,errors==0,p95<=250"
def waitTimeout = config.waitTimeout ?: 1800
def resultsFile = config.resultsFile ?: "performance_results.json"
docker.image('node:16-alpine').inside {
withCredentials([
string(credentialsId: 'loadfocus-api-key', variable: 'LOADFOCUS_API_KEY'),
string(credentialsId: 'loadfocus-team-id', variable: 'LOADFOCUS_TEAM_ID')
]) {
sh 'npm install -g @loadfocus/loadfocus-api-client'
sh 'loadfocus-api config set --apikey $LOADFOCUS_API_KEY --teamid $LOADFOCUS_TEAM_ID'
sh """
loadfocus-api jmeter run-test \\
--name "${testName}" \\
--thresholds "${thresholds}" \\
--wait-timeout ${waitTimeout} \\
--format json > ${resultsFile}
"""
archiveArtifacts artifacts: resultsFile, fingerprint: true
// Retourner les resultats du test
def raw = readFile(resultsFile)
def testResults = readJSON text: raw.substring(raw.indexOf('\n{') + 1)
return testResults
}
}
}

Puis dans votre Jenkinsfile :

@Library('my-shared-library') _
pipeline {
agent any
stages {
stage('Performance Test') {
steps {
script {
def results = performanceTest(
testName: "API_Performance_Test",
thresholds: "avgresponse<=150,errors==0"
)
if (results.overallResult != 'PASSED') {
error "Performance test failed"
}
}
}
}
}
}

Intégration avec les plugins Jenkins

Plugin Performance

Utilisez le plugin Performance de Jenkins pour visualiser les résultats des tests :

  1. Installez le plugin Performance dans Jenkins
  2. Convertissez les résultats LoadFocus dans un format supporté par le plugin (CSV JMeter ou XML JUnit)
  3. Configurez votre pipeline :
stage('Performance Test') {
steps {
// Executer le test LoadFocus
sh '''
loadfocus-api jmeter run-test \
--name "My_JMeter_Test" \
--thresholds "avgresponse<=200,errors==0,p95<=250" \
--format json > performance_results.json
# Convertir au format CSV JMeter (en utilisant un script personnalise)
node convert-to-jmeter.js performance_results.json performance_results.csv
'''
// Utiliser le plugin Performance
perfReport sourceDataFiles: 'performance_results.csv',
errorFailedThreshold: 0,
errorUnstableThreshold: 0,
errorUnstableResponseTimeThreshold: '200'
}
}

Notification par email

Envoyez des notifications par email avec les résultats des tests :

post {
always {
script {
if (fileExists('performance_results.json')) {
def raw = readFile('performance_results.json')
def results = readJSON text: raw.substring(raw.indexOf('\n{') + 1)
def resultStatus = results.overallResult == 'PASSED' ? 'SUCCESS' : 'FAILURE'
def subject = "Performance Test ${resultStatus}: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
// Creer le corps de l'email
def body = """
<h2>Resultats des tests de performance</h2>
<p><strong>Resultat global :</strong> ${results.overallResult}</p>
<h3>Resultats par label</h3>
<table border="1">
<tr><th>Label</th><th>Resultat</th><th>Temps de reponse moyen</th><th>Erreurs</th></tr>
"""
results.labels.each { label ->
body += """
<tr>
<td>${label.label}</td>
<td>${label.result}</td>
<td>${label.metrics.avgresponse}ms</td>
<td>${label.metrics.errors}</td>
</tr>
"""
}
body += "</table>"
emailext (
subject: subject,
body: body,
to: 'team@example.com',
attachmentsPattern: 'performance_results.json',
mimeType: 'text/html'
)
}
}
}
}

Conseils pour l'intégration Jenkins

  1. Gestion des délais : Définissez des délais pour les tests de performance de longue durée :

    stage('Performance Test') {
    options {
    timeout(time: 60, unit: 'MINUTES')
    }
    steps {
    // Etapes de test de performance
    }
    }
  2. Exécution conditionnelle : Exécutez les tests de performance uniquement sur des branches spécifiques :

    stage('Performance Test') {
    when {
    anyOf {
    branch 'main'
    branch 'develop'
    tag pattern: "v\\d+\\.\\d+\\.\\d+", comparator: "REGEXP"
    }
    }
    steps {
    // Etapes de test de performance
    }
    }
  3. Tests planifiés : Exécutez les tests de performance selon un planning :

    pipeline {
    agent any
    triggers {
    cron('0 0 * * *') // Executer a minuit chaque jour
    }
    stages {
    // Etapes du pipeline
    }
    }
  4. Tests paramétrés : Permettez la personnalisation des paramètres de test :

    pipeline {
    agent any
    parameters {
    string(name: 'TEST_NAME', defaultValue: 'API_Performance_Test', description: 'Name of the LoadFocus test to run')
    string(name: 'THRESHOLDS', defaultValue: 'avgresponse<=200,errors==0', description: 'Performance thresholds')
    string(name: 'WAIT_TIMEOUT', defaultValue: '1800', description: 'Maximum wait time in seconds')
    }
    stages {
    stage('Performance Test') {
    steps {
    // Executer le test avec les parametres
    sh """
    loadfocus-api jmeter run-test \\
    --name "${params.TEST_NAME}" \\
    --thresholds "${params.THRESHOLDS}" \\
    --wait-timeout ${params.WAIT_TIMEOUT} \\
    --format json > performance_results.json
    """
    }
    }
    }
    }

Pour plus d'informations, consultez la documentation Jenkins et la documentation du client API LoadFocus.