Aller au contenu

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 :

username,email
user1,user1@example.com
user2,user2@example.com
user3,user3@example.com


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 :

[
  {
    "id": 1,
    "name": "Laptop"
  },
  {
    "id": 2,
    "name": "Smartphone"
  },...
]


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 :

k6 run -e BASE_URL=https://staging.example.com -e API_KEY=secret123 script.js


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();
  }
}

☕️ Si tu souhaites soutenir mon travail, tu peux m'offrir un café ici.