Fondamentaux et Scripting¶
Module 4 : Paramètres et Dynamisme¶
4.1 Outils Divers¶
Récupérer des informations contenue dans une requête
import http from 'k6/http';
import { check } from 'k6';
export default function () {
// Extraction depuis JSON
const res = http.get('https://httpbin.org/json');
const data = res.json();
const slideshow = data.slideshow.author;
console.log(`Auteur: ${slideshow}`);
// Extraction depuis headers
const locationHeader = res.headers['Location'];
// Extraction avec regex
const body = res.body;
const tokenMatch = body.match(/token":"([^"]+)"/);
if (tokenMatch) {
const token = tokenMatch[1];
console.log(`Token extrait: ${token}`);
}
}
4.1 Outils Divers¶
Chaînage de requêtes
export default function () {
// 1. Créer une ressource
const createRes = http.post('https://httpbin.org/post',
JSON.stringify({ name: 'Test' })
);
const createdId = createRes.json().id;
// 2. Récupérer la ressource créée
const getRes = http.get(`https://httpbin.org/get?id=${createdId}`);
// 3. Mettre à jour
http.put(`https://httpbin.org/put?id=${createdId}`,
JSON.stringify({ name: 'Updated' })
);
}
4.2 Données Externes¶
xk6 Faker
- Générer facilement des données réalistes : noms, emails, adresses, numéros, UUID, etc.
- Éviter les données statiques ou répétitives dans les tests de charge
- Simuler des comportements utilisateurs variés et crédibles
import faker from "k6/x/faker";
import http from "k6/http";
export default function () {
const user = {
name: faker.person.firstName(),
};
// Encodage du JSON pour l’URL (request data ici)
const requestData = encodeURIComponent(JSON.stringify(user));
const url = `http://localhost/anything/${requestData}`;
const res = http.post(url, JSON.stringify(user), {
headers: { "Content-Type": "application/json" },
});
}
4.2 Données Externes¶
Utilisation de fichiers CSV
import http from 'k6/http';
import * as CSV from "k6/x/csv";
import { SharedArray } from 'k6/data';
// Lecture et parsing du fichier CSV
const csvData = new SharedArray('users', () => {
return CSV.parse(open('./resources/users.csv')); // Retourne un tableau d'objets
});
export default function () {
const user = csvData[Math.floor(Math.random() * csvData.length)];
//{"username":"user1","email":"user1@example.com"}
const payload = JSON.stringify({
username: user.username,
email: user.email,
});
const resp = http.post('http://localhost/anything', payload, {
headers: { 'Content-Type': 'application/json' },
});
}
Fichier users.csv :
4.2 Données Externes¶
Utilisation de fichiers JSON
import http from "k6/http";
import { SharedArray } from "k6/data";
// Chargement du fichier JSON une seule fois
const jsonData = new SharedArray("users", () => {
return JSON.parse(open("./resources/products.json"));
});
export default function () {
const user = jsonData[Math.floor(Math.random() * jsonData.length)];
// {"id":"1","name":"Laptop"}
http.post("http://localhost/anything", JSON.stringify(user), {
headers: { "Content-Type": "application/json" },
});
}
Fichier products.json :
4.2 Données Externes¶
Le SharedArray dans k6 est une structure de données spéciale qui permet de partager des données en lecture seule entre tous les VUs (Virtual Users) de manière mémoire-efficiente.
- Le fichier JSON n'est lu et parsé qu'une seule fois au début du test (read-only)
- Les données sont stockées dans une zone mémoire partagée (évite la duplication des données en mémoire)
- Tous les VUs accèdent aux mêmes données sans duplication
const data = new SharedArray('products', function () {
return JSON.parse(open('./products.json'));
});
Exemple concret
Avec 100 VUs et un fichier de 1 000 produits :
- Sans SharedArray : 100 copies × 1 000 produits = 100 000 objets en mémoire
- Avec SharedArray : 1 copie × 1 000 produits = 1 000 objets en mémoire
4.2 Données Externes¶
Variables d'environnement
import http from 'k6/http';
const BASE_URL = __ENV.BASE_URL || 'https://example.com';
const API_KEY = __ENV.API_KEY || 'default-key';
export default function () {
http.get(`${BASE_URL}/api`, {
headers: { 'X-API-Key': API_KEY },
});
}
Exécution :
4.2 Données Externes¶
Exercice pratique
Objectif : Créer un test avec données dynamiques
- Créer un fichier CSV avec des utilisateurs de test
- Implémenter un script qui utilise ces données
- Extraire un token de la réponse de login
- Utiliser ce token pour des requêtes suivantes
4.3 Théorie et Introduction : K6 Browser¶
K6 browser est une extension de Grafana k6 qui permet de réaliser des tests de charge basés sur un navigateur réel, en simulant le comportement d’un utilisateur humain dans un vrai navigateur Chromium embarqué
C’est une évolution majeure par rapport au k6 "classique", qui ne teste que la charge HTTP au niveau protocolaire (sans navigateur, donc sans rendu DOM, JS, CSS, etc.)
Cas d'usage
- Basé sur Playwright/Chromium
- Tester des flux utilisateurs complets
- Applications Single Page (React, Vue, Angular)
- Tests de bout en bout avec charge
- Complément aux tests API
4.3 Théorie et Introduction : K6 Browser¶
| Caractéristique | k6 “classique” | k6 browser |
|---|---|---|
| Type de test | Backend / API | Frontend (navigateur) |
| Niveau de test | Protocolaire HTTP | Réel (navigateur complet) |
| Rendu graphique | ❌ Non | ✅ Oui (Chromium embarqué) |
| Scénarios possibles | Appels API, endpoints REST, GraphQL | Navigation web, clics, formulaires, interactions DOM |
| Mesures collectées | Latence, taux d’erreur, throughput | Browser metrics |
4.3 Théorie et Introduction : K6 Browser¶
Script de base K6 Browser
import { browser } from 'k6/browser';
import { check } from 'k6';
export const options = {
scenarios: {
browser: {
executor: 'constant-vus',
vus: 1,
duration: '30s',
options: {
browser: {
type: 'chromium',
},
},
},
},
};
export default async function () {
const page = browser.newPage();
try {
await page.goto('https://example.com');
await page.locator('input[name="login"]').type('admin');
await page.locator('input[name="password"]').type('123');
await Promise.all([
page.waitForNavigation(),
page.locator('button[type="submit"]').click(),
]);
check(page, {
'header': page.locator('h2').textContent() == 'Welcome, admin!',
});
} finally {
page.close();
}
}