<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:media="http://search.yahoo.com/mrss/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ouidou</title>
	<atom:link href="https://ouidou.fr/feed/" rel="self" type="application/rss+xml" />
	<link>https://ouidou.fr/</link>
	<description>Conseil et expertise en technologies</description>
	<lastBuildDate>Wed, 08 Apr 2026 16:55:11 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.8</generator>
	<item>
		<title>Ouidou et Scaleway : un partenariat stratégique pour accélérer le cloud souverain en Europe</title>
		<link>https://ouidou.fr/2026/04/08/ouidou-et-scaleway-un-partenariat-strategique-pour-accelerer-le-cloud-souverain-en-europe/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Wed, 08 Apr 2026 16:55:09 +0000</pubDate>
				<category><![CDATA[Tous les articles]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=18209</guid>

					<description><![CDATA[<p>L’article <a href="https://ouidou.fr/2026/04/08/ouidou-et-scaleway-un-partenariat-strategique-pour-accelerer-le-cloud-souverain-en-europe/">Ouidou et Scaleway : un partenariat stratégique pour accélérer le cloud souverain en Europe</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>L’article <a href="https://ouidou.fr/2026/04/08/ouidou-et-scaleway-un-partenariat-strategique-pour-accelerer-le-cloud-souverain-en-europe/">Ouidou et Scaleway : un partenariat stratégique pour accélérer le cloud souverain en Europe</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2026/04/Scaleway.png" medium="image"></media:content>
				</item>
		<item>
		<title>JTE : un moteur de templates moderne, rapide et sécurisé pour Java</title>
		<link>https://ouidou.fr/2026/03/09/jte-java-template-engine/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Mon, 09 Mar 2026 09:34:01 +0000</pubDate>
				<category><![CDATA[Technique]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=18057</guid>

					<description><![CDATA[<p>Écrit par Thusitha T. Introduction Les moteurs de templates occupent une place clé dans la création de vues côté serveur, l&#8217;envoi d&#8217;emails personnalisés ou encore la<span class="excerpt-hellip"> […]</span></p>
<p>L’article <a href="https://ouidou.fr/2026/03/09/jte-java-template-engine/">JTE : un moteur de templates moderne, rapide et sécurisé pour Java</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Écrit par Thusitha T.</em></p>



<h2 class="wp-block-heading" id="Introduction"><strong>Introduction</strong></h2>



<p>Les moteurs de templates occupent une place clé dans la création de vues côté serveur, l&#8217;envoi d&#8217;emails personnalisés ou encore la génération de fichiers HTML à partir de données Java. Bien que des outils tels que <strong>Thymeleaf</strong>, <strong>FreeMarker</strong> ou <strong>Velocity</strong> soient populaires, un nouvel acteur a réussi à se démarquer grâce à sa performance et sa facilité d&#8217;utilisation : <strong>JTE</strong> (<strong>J</strong>ava <strong>T</strong>emplate <strong>E</strong>ngine).<br>Cet article vous propose une introduction à JTE, incluant ses principes opérationnels et ses bénéfices techniques, tout en fournissant un aperçu de son intégration au sein d&#8217;un projet Java modern.</p>



<h2 class="wp-block-heading" id="Qu’est-ce-que-JTE-?"><strong>Qu’est-ce que JTE ?</strong></h2>



<p><strong><a href="https://jte.gg/">JTE</a> </strong>(<strong>J</strong>ava<strong> T</strong>emplate<strong> E</strong>ngine) est un moteur de templates <strong>compilé</strong>, créé en 2020, qui vise à offrir une alternative plus <strong>rapide</strong>, <strong>sécurisée</strong> et <strong>typée</strong> aux moteurs de templates traditionnels utilisés dans les applications Java.<br>Contrairement à des solutions interprétées comme <strong>Thymeleaf</strong> ou <strong>FreeMarker</strong>, JTE <strong>compile les templates en classes Java</strong> au moment du build. Cela lui permet d’obtenir des performances proches de celles du code natif, tout en garantissant la détection d’erreurs à la compilation.</p>



<h3 class="wp-block-heading" id="Objectif-principal"><strong>Objectif principal</strong></h3>



<p><strong>JTE</strong> vise à fournir un moteur de templates modern pour Java, approprié aux contextes de haute performance (API, microservices, applications server-side rendering, etc.), tout en maintenant une simplicité d&#8217;apprentissage.</p>



<h2 class="wp-block-heading" id="Les-atouts-majeurs"><strong>Les atouts majeurs</strong></h2>



<h3 class="wp-block-heading" id="&#x1f680;Haute-Performance"><strong>Haute Performance</strong></h3>



<p>L’un des atouts les plus marquants de JTE est dans sa rapidité d’exécution.</p>



<p>En effet, JTE supprime la phase d’interprétation. Les fichiers <strong>.jte</strong> sont transformés en classes Java lors de la compilation. Ainsi, les modèles sont donc directement exécutés comme du code Java optimisé par la JVM.</p>



<p>Des comparaisons indépendantes ont démontré que JTE peut être plus rapide que <strong>Thymeleaf</strong> ou <strong>FreeMarker</strong> dans différents scénarios.</p>



<h3 class="wp-block-heading" id="&#x1f6e1;Sécurité-renforcée"><strong>Sécurité renforcée</strong></h3>



<p>En appliquant une <strong>échappement automatique du HTML</strong> et des autres formats (XML, JSON, etc.), JTE réduit drastiquement les risques d’<strong>injections XSS</strong> (Cross-Site Scripting).<br>De plus, comme les templates sont compilés, il n’y a <strong>aucune exécution dynamique de code</strong>, contrairement à d’autres moteurs plus permissifs.</p>



<h3 class="wp-block-heading" id="&#x1f9e9;Typage-fort-et-vérification-à-la-compilation"><strong>Typage fort et vérification à la compilation</strong></h3>



<p>Etant donné que les templates JTE sont <strong>vérifiés à la compilation</strong>, si un champ ou une méthode n’existe plus dans un objet passé au template, l’erreur est détectée <strong>avant le déploiement</strong>, et non à l’exécution.</p>



<h3 class="wp-block-heading" id="&#x1f517;Intégration-fluide"><strong>Intégration fluide</strong></h3>



<p>JTE ne nécessite pas de configuration complexe.<br>Un simple ajout de dépendance Maven ou Gradle suffit pour l’utiliser dans un projet Java.<br>Il s’intègre facilement avec des frameworks comme <strong>Spring Boot</strong>.</p>



<h2 class="wp-block-heading" id="Installation"><strong>Installation</strong></h2>



<pre class="wp-block-code"><code class="">&lt;dependency&gt;
    &lt;groupId&gt;gg.jte&lt;/groupId&gt;
    &lt;artifactId&gt;jte-spring-boot-starter-3&lt;/artifactId&gt;
    &lt;version&gt;3.2.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;gg.jte&lt;/groupId&gt;
    &lt;artifactId&gt;jte&lt;/artifactId&gt;
    &lt;version&gt;3.2.1&lt;/version&gt;
&lt;/dependency&gt;</code></pre>



<p>Les fichiers <code>.jte</code> placés dans <code>src/main/resources/templates</code> seront automatiquement détectés et rendus via les contrôleurs Spring (<code>@Controller</code> + <code>ModelAndView</code>).</p>



<h3 class="wp-block-heading" id="Structure-de-base"><strong>Structure de base</strong></h3>



<pre class="wp-block-code"><code class="">src/
 ├─ main/
 │   ├─ java/
 │   ├─ resources/
 │   │   └─ templates/
 │   │       └─ hello.jte</code></pre>



<h3 class="wp-block-heading" id="Structure-de-base"><strong>Exemple de template <code>hello.jte</code></strong></h3>



<pre class="wp-block-code"><code class="">@import java.time.LocalDateTime
&lt;html&gt;
  &lt;body&gt;
    &lt;h1&gt;Hello ${name}!&lt;/h1&gt;
    &lt;p&gt;Nous sommes le ${LocalDateTime.now()}.&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>



<h3 class="wp-block-heading" id="Structure-de-base"><strong>Contrôleur </strong></h3>



<pre class="wp-block-code"><code class="">import org.springframework.web.servlet.ModelAndView;
@GetMapping("/hello")
public ModelAndView hello() {
  return new ModelAndView("hello", Map.of("name", "Jean"))
}</code></pre>



<h3 class="wp-block-heading" id="Structure-de-base"><strong>Classe Java générée du template </strong></h3>



<pre class="wp-block-code"><code class="">package jte;
import gg.jte.TemplateOutput;
import gg.jte.html.HtmlTemplateOutput;
import gg.jte.runtime.Template;
import java.time.LocalDateTime;
import java.util.Map;
public final class JtehelloGenerated implements Template {
  @Override
  public void render(Map&lt;String, Object&gt; params, TemplateOutput output) {
    String name = (String) params.get("name");
    output.writeContent("&lt;html&gt;\n  &lt;body&gt;\n    &lt;h1&gt;Hello ");
    output.writeUserContent(name);
    output.writeContent("!&lt;/h1&gt;\n    &lt;p&gt;Nous sommes le ");
    output.writeUserContent(LocalDateTime.now());
    output.writeContent(".&lt;/p&gt;\n  &lt;/body&gt;\n&lt;/html&gt;");
  }
  @Override
  public static void render(Map&lt;String, Object&gt; params, HtmlTemplateOutput output) {
    new JtehelloGenerated().render(params, output);
  }
}</code></pre>



<h4 class="wp-block-heading" id="Explications"><strong>Explications</strong></h4>



<p>Le fichier <code>.jte</code> est <strong>transformé en une classe Java</strong> qui implémente l’interface <code>gg.jte.runtime.Template</code> et tout le contenu statique HTML est injecté via <code>output.writeContent(...)</code>.</p>



<p>Les variables quant à elles (<code>${name}</code>, <code>${LocalDateTime.now()}</code>) deviennent des appels Java typés et sûrs.</p>



<p>La méthode <code>render</code> est appelée par le moteur JTE lors de l’exécution.</p>



<h3 class="wp-block-heading" id="Explications"><strong>Résultat affiché</strong></h3>



<pre class="wp-block-code"><code class="">&lt;html&gt;
  &lt;body&gt;
    &lt;h1&gt;Hello Jean!&lt;/h1&gt;
    &lt;p&gt;Nous sommes le 2025-10-23T14:35:10.123.&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>



<h2 class="wp-block-heading" id="Exemples-d’utilisation-de-JTE"><strong>Exemples d’utilisation de JTE</strong></h2>



<h3 class="wp-block-heading" id="Affichage-conditionnel"><strong>Affichage conditionnel</strong></h3>



<pre class="wp-block-code"><code class="">@if(isAdmin)
  &lt;p&gt;Bienvenue, administrateur ${userName}.&lt;/p&gt;
@else if(isGuest)
  &lt;p&gt;Bienvenue, invité.&lt;/p&gt;
@else
  &lt;p&gt;Bienvenue, utilisateur.&lt;/p&gt;
@end</code></pre>



<p>Etant donné que le template est compilé en <code>if / else</code> Java, aucune erreur n’est possible à l’exécution.</p>



<h3 class="wp-block-heading" id="Affichage-conditionnel"><strong>Boucle <code>for</code> (<code>foreach</code>)</strong></h3>



<pre class="wp-block-code"><code class="">&lt;ul&gt;
@for(Product product : products)
  &lt;li&gt;${product.getName()} — ${product.getPrice()} €&lt;/li&gt;
@end
&lt;/ul&gt;</code></pre>



<h3 class="wp-block-heading" id="Affichage-conditionnel"><strong>Fragment réutilisable</strong></h3>



<p>Supposons que nous avons le fragment <code>fragments/header.jte</code> :</p>



<pre class="wp-block-code"><code class="">@param String title
&lt;header&gt;
  &lt;h1&gt;${title}&lt;/h1&gt;
&lt;/header&gt;</code></pre>



<p>En appelant ce dernier dans le template suivant :</p>



<pre class="wp-block-code"><code class="">@template.views.fragments.header(
  title = "Accueil"
)
&lt;main&gt;
  &lt;p&gt;Bienvenue sur notre site !&lt;/p&gt;
&lt;/main&gt;</code></pre>



<p>Nous aurons le résultat suivant :</p>



<pre class="wp-block-code"><code class="">&lt;header&gt;
  &lt;h1&gt;Accueil&lt;/h1&gt;
&lt;/header&gt;
&lt;main&gt;
  &lt;p&gt;Bienvenue sur notre site !&lt;/p&gt;
&lt;/main&gt;</code></pre>



<h2 class="wp-block-heading" id="Limites-et-points-de-vigilance-avec-JTE"><strong>Limites et points de vigilance avec JTE</strong></h2>



<p>Même si <strong>JTE</strong> se distingue par ses performances et sa sécurité, il est important de connaitre ses limites avant de l’adopter dans un projet.</p>



<h3 class="wp-block-heading" id="&#x1f501;Recompilation-après-chaque-modification"><strong>Recompilation après chaque modification</strong></h3>



<p>Vu que JTE travaille avec des templates compilés, lorsqu’on modifie un <code>.jte</code>, les modifications seront prises en compte seulement après <strong>recompilation</strong>.</p>



<h3 class="wp-block-heading" id="&#x1f331;Communauté-encore-jeune"><strong>Communauté encore jeune</strong></h3>



<p>Comparé à <strong>Thymeleaf</strong> ou <strong>FreeMarker</strong>, JTE dispose d’une <strong>communauté plus restreinte</strong>.<br>La documentation officielle est claire mais <strong>moins riche en exemples</strong> et <strong>moins d’intégrations tierces</strong> existent pour l’instant (tags Spring Security, intégrations JSP, etc.).</p>



<h3 class="wp-block-heading" id="&#x1f335;Moins-d’écosystème-autour-des-extensions"><strong>Moins d’écosystème autour des extensions</strong></h3>



<p>En misant sur la simplicité et la performance, JTE a un écosystème plus fermé que par exemple Thymeleaf qui propose des dialectes et des extensions personnalisables. Autrement dit, si le projet a besoin de tags ou de macros complexes, JTE sera moins adapté.</p>



<h3 class="wp-block-heading" id="&#x1f9e9;&#x2757;Extensions-et-plugins-JTE-encore-limités"><strong>Extensions et plugins JTE encore limités</strong></h3>



<p>JTE propose plusieurs <strong>plugins officiels</strong> pour l’intégration dans les outils de build, mais ils restent <strong>moins matures</strong> que ceux des moteurs plus anciens :</p>



<figure class="wp-block-table"><table><tbody><tr><th>Plugin</th><th>Description</th><th>Limitation actuelle</th></tr><tr><td><strong>jte-maven-plugin</strong></td><td>Compile les templates <code>.jte</code> lors du <code>mvn compile</code></td><td>Peu documenté, nécessite une configuration manuelle des chemins</td></tr><tr><td><strong>jte-gradle-plugin</strong></td><td>Compilation automatique dans Gradle</td><td>Incompatible avec certains environnements Gradle anciens (&lt; 7)</td></tr><tr><td><strong>jte-intellij-plugin</strong></td><td>Coloration syntaxique et autocomplétion</td><td>Support partiel, pas encore complet sur les <code>@include</code> et <code>@param</code></td></tr><tr><td><strong>jte-spring-boot-starter</strong></td><td>Intégration MVC avec Spring Boot</td><td>Fonctionne bien mais peu d’exemples complexes dans la doc</td></tr></tbody></table></figure>



<p>Il n’y a exemple aucun plugin sur Eclipse ou VS Code permettant d’avoir la coloration syntaxique et l’autocomplétion.</p>



<h3 class="wp-block-heading" id="&#x1f6ab;&#x269b;Pas-de-Virtual-DOM-ni-de-rendu-réactif"><strong>Pas de Virtual DOM ni de rendu réactif</strong></h3>



<p>JTE est un <strong>moteur de rendu côté serveur pur</strong> :<br>il ne propose <strong>aucun Virtual DOM</strong>, ni <strong>mécanisme de réconciliation</strong> des changements de données comme le font des bibliothèques front-end (React, Vue, Svelte…).</p>



<p>Chaque rendu JTE <strong>recrée le HTML complet</strong> à partir du serveur, sans mise à jour partielle du DOM côté client.</p>



<p>Cela signifie que toute modification d’état nécessite un <strong>nouvel appel serveur et un rechargement complet de la vue</strong>.</p>



<h2 class="wp-block-heading" id="Conclusion"><strong>Conclusion</strong></h2>



<p><strong>JTE</strong> s’impose aujourd’hui comme une alternative aux moteurs historiques de templates Java.<br>Son approche <strong>compilée</strong>, son <strong>typage fort</strong> et sa <strong>sécurité intégrée</strong> en font un choix pertinent pour les développeurs cherchant à <strong>améliorer les performances</strong> et la <strong>fiabilité</strong> de leurs applications Java.</p>



<p>Autrement dit, il peut être l’idéal pour les applications où le contenu est statique au build (templates de mails, vues serveur, génération de rapports HTML). Par contre, s’il s’agit d’un projet avec des templates très dynamique, très intéractifs ou orientés utilisateur, un framework front moderne reste plus adapté.</p>



<h2 class="wp-block-heading" id="Liens-utiles"><strong>Liens utiles</strong></h2>



<ul>
<li>Documentation officielle : <a href="https://jte.gg/">jte: Java Template Engine &#8211; jte</a></li>



<li>Repo GitHub : <a href="https://github.com/casid/jte">GitHub &#8211; casid/jte: Secure and speedy templates for Java and Kotlin.</a></li>



<li>Intégration avec Spring Boot : <a href="https://jte.gg/spring-boot-starter-3/">jte Spring Boot 3 Starter &#8211; jte</a></li>
</ul>
<p>L’article <a href="https://ouidou.fr/2026/03/09/jte-java-template-engine/">JTE : un moteur de templates moderne, rapide et sécurisé pour Java</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2026/03/JTE-un-moteur-de-templates-moderne-rapide-et-securise-pour-Java.png" medium="image"></media:content>
				</item>
		<item>
		<title>La Sobriété Numérique, de la quantification des émissions carbone des applications à la mise en œuvre des corrections</title>
		<link>https://ouidou.fr/2026/02/16/la-sobriete-numerique/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Mon, 16 Feb 2026 08:58:11 +0000</pubDate>
				<category><![CDATA[Technique]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17878</guid>

					<description><![CDATA[<p>Écrit par Hudson T. Qu’est que c’est La Sobriété Numérique Selon l&#8217;ADEME, dans une étude réalisée en 2020, 2,5 % de l&#8217;empreinte carbone de la France<span class="excerpt-hellip"> […]</span></p>
<p>L’article <a href="https://ouidou.fr/2026/02/16/la-sobriete-numerique/">La Sobriété Numérique, de la quantification des émissions carbone des applications à la mise en œuvre des corrections</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Écrit par Hudson T.</em></p>



<h2 class="wp-block-heading" id="1.-Qu’est-que-c’est-La-Sobriété-Numérique"><strong>Qu’est que c’est La Sobriété Numérique</strong></h2>



<p>Selon l&#8217;<strong>ADEME</strong>, dans une étude réalisée en <strong>2020</strong>, <strong>2,5 %</strong> de l&#8217;<strong>empreinte carbone</strong> de la France est liée au <strong>numérique</strong>, avec <strong>10 %</strong> de la <strong>consommation annuelle d&#8217;énergie</strong> attribuée aux <strong>services numériques</strong>. Pour atteindre la <strong>transition écologique</strong> définie par la France, la mesure des <strong>émissions de carbone</strong> et la mise en œuvre de <strong>mesures d&#8217;atténuation des risques</strong> sont essentielles pour un <strong>avenir durable</strong>.</p>



<p>Dans cette perspective, nous appliquons les principes de la <strong>sobriété numérique</strong>, qui consistent à concevoir des <strong>services numériques plus économes</strong>, afin de réduire les <strong>impacts environnementaux</strong> et la <strong>consommation d&#8217;énergie</strong> des <strong>technologies</strong>, par exemple lors de la <strong>navigation sur internet</strong> et de l&#8217;utilisation d&#8217;<strong>applications web</strong> sur les <strong>ordinateurs</strong> et les <strong>téléphones portables</strong>.</p>



<h2 class="wp-block-heading" id="2.-La-Sobriété-Numérique-dès-la-conception-de-l'application"><strong>La Sobriété Numérique dès la conception de l&#8217;application</strong></h2>



<p>La <strong>conception d&#8217;une application web</strong> implique plusieurs facteurs importants, en particulier si l&#8217;on considère l&#8217;<strong>empreinte carbone</strong> associée à l&#8217;utilisation de ces applications. Pour réduire la <strong>consommation d&#8217;énergie</strong>, il est nécessaire d&#8217;analyser des aspects tels que :</p>



<ul>
<li><strong>Cible</strong> : évaluer la <strong>taille</strong> et les <strong>habitudes du public</strong> qui utilisera la plateforme et sa <strong>fréquence d&#8217;utilisation</strong>, car le <strong>nombre d&#8217;accès</strong> est directement lié aux <strong>émissions générées</strong>.</li>



<li><strong>Technologies utilisées</strong> : choisissez des <strong>technologies web modernes</strong> mais moins gourmandes en énergie, qui évitent le <strong>chargement continu des pages web</strong> et la répétition des <strong>requêtes et des connexions</strong>.</li>



<li><strong>Requêtes HTTP</strong> : réduire le <strong>nombre de requêtes</strong> effectuées lors de l&#8217;utilisation de l&#8217;application, en minimisant les <strong>appels redondants</strong>.</li>



<li><strong>Taille des fichiers</strong> : optez pour des <strong>fichiers plus petits et optimisés</strong>, tels que des <strong>images compressées</strong>, du <strong>HTML</strong>, <strong>CSS</strong> et <strong>JavaScript minifiés</strong>.</li>



<li><strong>Infrastructure d&#8217;hébergement</strong> : vérifiez la <strong>répartition géographique des serveurs</strong> afin de réduire la <strong>latence</strong> et d&#8217;améliorer le <strong>chargement</strong>. Privilégiez les <strong>hébergeurs qui utilisent des énergies renouvelables</strong>.</li>
</ul>



<p>De nombreuses pratiques d&#8217;<strong>éco-conception</strong> sont également directement liées à l&#8217;<strong>expérience utilisateur (UX)</strong> et à l&#8217;<strong>interface (UI)</strong>. Au cours du processus de conception, il est essentiel de réduire le <strong>nombre d&#8217;actions nécessaires</strong> à l&#8217;utilisateur pour atteindre ses objectifs, en optimisant les <strong>flux et les interfaces</strong>. Une <strong>conception simple et fonctionnelle</strong> permet non seulement de minimiser l&#8217;<strong>impact sur l&#8217;environnement</strong>, mais aussi de créer des <strong>applications plus agréables à utiliser</strong>.</p>



<h2 class="wp-block-heading" id="3.-Comment-mesurer-l'empreinte-carbone-des-applications-web"><strong>Comment mesurer l&#8217;empreinte carbone des applications web</strong></h2>



<p>Globalement, la <strong>navigation sur Internet</strong> est directement liée à la <strong>consommation d&#8217;énergie</strong> des <strong>applications</strong>. Il est donc possible de mesurer l&#8217;<strong>impact carbone</strong> des applications en prenant en compte l&#8217;<strong>énergie consommée</strong> lors de leur utilisation.</p>



<p>Pour ce faire, il existe des <strong>outils</strong> qui permettent de calculer l&#8217;<strong>empreinte carbone</strong> en tenant compte de la <strong>matrice énergétique du pays</strong>, du <strong>pourcentage d&#8217;énergies renouvelables</strong> utilisées et de l&#8217;<strong>empreinte carbone moyenne</strong> des sites de la région. Une solution existante est le site <strong><a href="https://www.ecoindex.fr/" target="_blank" rel="noreferrer noopener">Ecoindex</a></strong> et l’extension <a href="https://chromewebstore.google.com/detail/greenit-analysis/mofbfhffeklkbebfclfaiifefjflcpad?hl=fr" target="_blank" rel="noreferrer noopener"><strong>GreenIt &#8211; Analyses</strong> </a>qui fournissent un <strong>rapport</strong> sur la <strong>quantité de code inutilisé</strong> sur la page, le <strong>nombre d&#8217;images plus grandes que nécessaire</strong> et indiquent même les <strong>formats d&#8217;image</strong> qui pourraient être modifiés pour réduire la <strong>consommation d&#8217;énergie</strong> et les <strong>émissions de CO₂</strong> lors du téléchargement. Ils vérifient également si l&#8217;<strong>hébergeur du site</strong> utilise de l&#8217;<strong>énergie renouvelable</strong> sur ses <strong>serveurs</strong>, en utilisant l&#8217;outil de <a href="https://www.thegreenwebfoundation.org/" target="_blank" rel="noreferrer noopener"><strong>The Green Web Foundation</strong>.</a></p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img fetchpriority="high" decoding="async" width="1024" height="454" src="https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-1024x454.png" alt="" class="wp-image-17880" style="width:547px;height:auto" srcset="https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-1024x454.png 1024w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-300x133.png 300w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-768x341.png 768w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-150x67.png 150w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-380x168.png 380w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250919-145138-1-480x213.png 480w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></figure></div>


<p class="has-text-align-center"><em><strong>Figure 1 : Exemple d&#8217;évaluation de l&#8217;EcoIndex par l&#8217;extension GreenIt.</strong></em></p>



<h2 class="wp-block-heading" id="4.-Comment-mettre-en-œuvre-L'Eco-conception-lors-de-la-rédaction-du-code"><strong>Comment mettre en œuvre L&#8217;Eco-conception lors de la rédaction du code</strong></h2>



<p>Les <strong>stratégies</strong> à utiliser pour chaque projet doivent être adaptées à ses <strong>caractéristiques spécifiques</strong>. Nous vous présentons quelques <strong>exemples concrets de bonnes pratiques</strong> illustrant comment certaines <strong>décisions techniques</strong> peuvent influencer directement la <strong>performance</strong> et la <strong>maintenabilité</strong> d’une <strong>application</strong>.</p>



<p><strong>Dans les applications React</strong></p>



<p>Il est important d’éviter les <strong>re-rendus inutiles</strong>. Cela peut se faire en utilisant <strong>React.memo</strong> pour prioriser les <strong>rendus uniques</strong>. Il faut également être attentif à l’utilisation des <strong>hooks</strong> : par exemple, privilégier <strong>useMemo</strong> pour les <strong>variables</strong> qui ne changent pas entre les rendus ou pour les <strong>opérations simples</strong>, plutôt que de recourir à <strong>useState</strong> lorsqu’il n’est pas nécessaire. Une autre bonne pratique consiste à <strong>mettre en cache</strong> les informations afin de réduire les <strong>appels HTTP redondants et inutiles</strong>.</p>



<p><strong>Dans les applications Java</strong></p>



<p>Il est recommandé d’envisager l’utilisation de <strong>Hibernate</strong> pour <strong>abstraire la base de données</strong>. Afin d’optimiser les <strong>performances</strong>, il est aussi possible de tirer parti du <strong>cache de second niveau</strong> proposé par Hibernate, qui diminue significativement le <strong>nombre d’accès à la base de données</strong>.</p>



<p>Dans toutes les applications, il est tout aussi important de s’assurer que les <strong>changements souhaités</strong> sont effectivement observés dans le <strong>code</strong>, et de vérifier les <strong>points définis</strong> au cours du développement. Il est essentiel que notre <strong>CD/CI</strong> soit adaptée à cet effet. Il existe différents <strong>modèles</strong> qui contrôlent les <strong>applications</strong> et leurs <strong>résultats</strong> en fonction de l&#8217;évolution du code, comme le <strong>Template </strong><a href="https://github.com/green-coding-solutions/eco-ci-energy-estimation?tab=readme-ov-file" target="_blank" rel="noreferrer noopener"><strong>Eco-CI</strong> </a>fourni par <strong>Green Coding</strong>.</p>



<p>Une autre solution simple consiste à utiliser le <strong>plugin <a href="https://github.com/green-code-initiative/creedengo-rules-specifications" target="_blank" rel="noreferrer noopener">creedengo</a></strong> dans le logiciel <strong>SonarQube</strong>, le logiciel d&#8217;<strong>analyse statique de code</strong> utilisé dans la plupart des <strong>CI existantes</strong>. Le plugin permet d&#8217;ajouter des <strong>règles d&#8217;analyse</strong> au champ d&#8217;application du logiciel, visant à identifier les <strong>problèmes d&#8217;éco-conception</strong>, permettant de les corriger au fur et à mesure de l&#8217;écriture du code, dans de nombreux <strong>langages</strong> tels que <strong>Java, JavaScript, PHP, Python et C#</strong>. Bien que très récent et en cours de développement, l&#8217;outil est déjà disponible pour la <strong>version 9.4.+</strong> de SonarQube. Le plugin vous permet d&#8217;ajouter de <strong>nouvelles règles</strong> à marquer avec la <strong>balise creedengo</strong> comme indiqué ci-dessous.</p>



<p>Ci-dessous, nous présentons un <strong>exemple d’identification</strong> d’un <strong>problème d’éco-conception</strong> dans un <strong>code Java</strong>, signalé par <strong>SonarQube</strong> avec le <strong>plugin installé</strong>. Comme on peut le constater, notre <strong>code</strong> présente un <strong>problème de performance</strong> marqué avec le <strong>tag creedengo</strong>, qui indique une <strong>inefficacité</strong> liée à l’<strong>appel de la fonction size</strong> à l’intérieur d’une <strong>boucle</strong>.</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/a4d167ba-4a13-41a6-900d-f64210f6a6e0/variants/518967c8-4cfe-4d10-931d-3f3c9abb6009/src" alt="Utilisation de Creedengo dans SonarQube" style="width:522px;height:auto"/></figure></div>


<p class="has-text-align-center"><em><strong>Figure 2 : Exemple d&#8217;analyse SonarQube avec des erreurs de performance remontées par creedengo.</strong></em></p>



<p>Ce <strong>comportement</strong> est <strong>problématique</strong> car la fonction <strong>size</strong> est évaluée à chaque <strong>itération</strong>, entraînant une <strong>consommation inutile</strong> de <strong>cycles CPU</strong> et, par conséquent, une <strong>augmentation de la consommation énergétique</strong>.</p>



<p><strong>SonarQube</strong> propose une <strong>solution</strong> : <strong>stocker</strong> la <strong>valeur retournée</strong> par la fonction <strong>size</strong> dans une <strong>variable</strong> avant la <strong>boucle</strong>. Cela permet d’éviter de <strong>recalculer</strong> la <strong>taille</strong> de la <strong>collection</strong> à chaque itération, <strong>améliorant</strong> ainsi l’<strong>efficacité du code</strong> tout en <strong>réduisant son impact énergétique</strong>.</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/53f7e348-acda-435a-a310-9694cc813005/variants/e52275dd-ddf8-49cb-88b4-bf27ce8e5bb5/src" alt="Exemple d'analyse de code Java" style="width:522px;height:auto"/></figure></div>


<p class="has-text-align-center"><em><strong>Figure 3 : Exemple de proposition SonarQube avec creedengo pour améliorer l’efficacité.</strong></em></p>



<h2 class="wp-block-heading" id="5.-Conclusion"><strong>Conclusion</strong></h2>



<p>La <strong>sobriété numérique</strong> est <strong>cruciale</strong> pour réduire l&#8217;<strong>impact environnemental</strong> des <strong>services numériques</strong>. En adoptant des pratiques d&#8217;<strong>éco-conception</strong>, en <strong>optimisant le code</strong> et en <strong>mesurant les émissions de carbone</strong>, il est possible de <strong>réduire la consommation énergétique</strong> tout en <strong>améliorant l&#8217;expérience utilisateur</strong>. Cela soutient la <strong>transition écologique</strong> et permet aux <strong>entreprises</strong> de répondre aux <strong>attentes croissantes</strong> des <strong>consommateurs</strong> et des <strong>régulateurs</strong> en matière de <strong>durabilité</strong>. Cela renforce également leur <strong>image de marque</strong> et leur <strong>engagement envers l&#8217;environnement</strong>.</p>



<h2 class="wp-block-heading" id="6.-Sources"><strong>Sources</strong></h2>



<ul>
<li><a href="https://www.w3.org/blog/2023/introducing-web-sustainability-guidelines/">Article du W3C présentant les directives pour un web plus durable, avec des recommandations pour concevoir des sites web écologiques</a></li>



<li><a href="https://librairie.ademe.fr/consommer-autrement/5226-evaluation-de-l-impact-environnemental-du-numerique-en-france-et-analyse-prospective.html">Rapport de l&#8217;ADEME évaluant l&#8217;impact environnemental du numérique en France et proposant des scénarios prospectifs</a></li>



<li><a href="https://sustainablewebdesign.org/">Plateforme dédiée à la conception web durable, offrant des outils, des conseils et des bonnes pratiques pour réduire l&#8217;empreinte écologique des sites web</a></li>
</ul>



<h3 class="wp-block-heading" id="Outils-de-mesure-mentionnés"><strong>Outils de mesure mentionnés</strong></h3>



<ul>
<li><a href="https://chromewebstore.google.com/detail/greenit-analysis/mofbfhffeklkbebfclfaiifefjflcpad?hl=fr">Extension Chrome permettant d&#8217;analyser l&#8217;impact environnemental des sites web</a></li>



<li><a href="https://markdowntohtml.com/www.thegreenwebfoundation.org/">Outil pour vérifier si un hébergement utilise de l&#8217;énergie renouvelable</a></li>



<li><a href="https://github.com/green-coding-solutions/eco-ci-energy-estimation?tab=readme-ov-file">Template pour estimer la consommation énergétique des pipelines CI/CD</a></li>



<li><a href="https://ecoresponsable.numerique.gouv.fr/publications/boite-outils/fiches/ecocode/">Guide pratique pour intégrer des principes d&#8217;éco-conception dans les projets numériques</a></li>



<li><a href="https://ecoresponsable.numerique.gouv.fr/publications/boite-outils">Sélection d&#8217;outils recommandés par la direction interministérielle du numérique et le ministère de la Transition écologique pour un numérique durable</a></li>
</ul>



<h3 class="wp-block-heading" id="Quelques-ressources-pour-aller-plus-loin…"><strong>Quelques ressources pour aller plus loin…</strong></h3>



<ul>
<li><a href="https://www.greenit.fr/etude-empreinte-environnementale-du-numerique-mondial/#recommandations">Rapport détaillant les impacts environnementaux du numérique à l&#8217;échelle mondiale et proposant des recommandations pour les réduire</a></li>



<li><a href="https://alexsoyes.com/eco-conception-web/">Blog détaillant des pratiques pour une éco-conception web efficace et durable</a></li>
</ul>
<p>L’article <a href="https://ouidou.fr/2026/02/16/la-sobriete-numerique/">La Sobriété Numérique, de la quantification des émissions carbone des applications à la mise en œuvre des corrections</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2026/02/La-Sobriete-Numerique.png" medium="image"></media:content>
				</item>
		<item>
		<title>Introduction pratique au Q-learning avec Gymnasium Taxi-v3</title>
		<link>https://ouidou.fr/2026/01/06/introduction-pratique-au-q-learning-avec-gymnasium-taxi-v3/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Tue, 06 Jan 2026 10:12:18 +0000</pubDate>
				<category><![CDATA[Technique]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17885</guid>

					<description><![CDATA[<p>Écrit par Kévin A. Introduction L&#8217;apprentissage par renforcement (Reinforcement Learning, ou RL) est une branche de l&#8217;intelligence artificielle dans laquelle un agent IA apprend à prendre<span class="excerpt-hellip"> […]</span></p>
<p>L’article <a href="https://ouidou.fr/2026/01/06/introduction-pratique-au-q-learning-avec-gymnasium-taxi-v3/">Introduction pratique au Q-learning avec Gymnasium Taxi-v3</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Écrit par Kévin A.</em></p>



<h2 class="wp-block-heading"><strong>Introduction</strong></h2>



<p>L&#8217;apprentissage par <strong>renforcement</strong> (<strong>Reinforcement Learning</strong>, ou <strong>RL</strong>) est une branche de l&#8217;<strong>intelligence artificielle</strong> dans laquelle un <strong>agent IA</strong> apprend à prendre des décisions par <strong>essai-erreur</strong>. Contrairement à l&#8217;<strong>apprentissage supervisé</strong>, il n&#8217;existe pas de réponses toutes faites : l&#8217;<strong>agent</strong> explore son <strong>environnement</strong> et améliore ses choix grâce aux <strong>récompenses</strong> reçues.</p>



<p>Aujourd’hui nous allons découvrir <strong><a href="https://gymnasium.farama.org/environments/toy_text/taxi/" target="_blank" rel="noreferrer noopener">Gymnasium</a></strong>, une <strong>bibliothèque open source</strong> proposant de nombreux <strong>environnements simulés</strong>. Dans cet article, nous allons explorer l&#8217;environnement <strong>Taxi-v3</strong>. Dans cet <strong>environnement</strong>, le but est simple : déplacer le <strong>taxi</strong> pour récupérer un <strong>passager</strong> et le déposer à sa <strong>destination</strong> le plus efficacement possible.</p>



<p>Nous allons découvrir comment entraîner notre <strong>agent</strong> à accomplir cette <strong>tâche</strong> en utilisant le <strong>Q-Learning</strong>, un <strong>algorithme</strong> à la fois simple et particulièrement efficace.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img decoding="async" width="551" height="349" src="https://ouidou.fr/wp-content/uploads/2025/11/plateau-1.png" alt="" class="wp-image-17887" style="width:291px;height:auto" srcset="https://ouidou.fr/wp-content/uploads/2025/11/plateau-1.png 551w, https://ouidou.fr/wp-content/uploads/2025/11/plateau-1-300x190.png 300w, https://ouidou.fr/wp-content/uploads/2025/11/plateau-1-118x75.png 118w, https://ouidou.fr/wp-content/uploads/2025/11/plateau-1-306x194.png 306w, https://ouidou.fr/wp-content/uploads/2025/11/plateau-1-480x304.png 480w" sizes="(max-width:767px) 480px, 551px" /></figure></div>


<h2 class="wp-block-heading" id="Comprendre-le-Q-Learning-et-la-Q-Table"><strong>Comprendre le Q-Learning et la Q-Table</strong></h2>



<h3 class="wp-block-heading" id="La-Q-Table"><strong>La Q-Table</strong></h3>



<p>Le <strong>Q-Learning</strong> est un <strong>algorithme</strong> basé sur une <strong>Q-Table</strong>, une <strong>matrice</strong> où chaque <strong>ligne</strong> correspond à un <strong>état possible</strong>, et chaque <strong>colonne</strong> à une <strong>action</strong>. La valeur dans la case <strong>Q(s,a)</strong> indique la &#8220;<strong>qualité</strong>&#8221; de choisir l&#8217;<strong>action a</strong> dans l&#8217;<strong>état s</strong>.</p>



<p>Au départ, la <strong>Q-Table</strong> est remplie de <strong>zéros</strong>. L&#8217;<strong>agent IA</strong> apprend progressivement à <strong>mettre à jour</strong> cette <strong>table</strong> en <strong>interagissant</strong> avec l&#8217;<strong>environnement</strong>.</p>



<h3 class="wp-block-heading" id="La-formule-de-mise-à-jour"><strong>La formule de mise à jour</strong></h3>



<p>Chaque fois que le taxi prend une action et reçoit une récompense, la Q-Table est mise à jour selon :</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="402" height="47" src="https://ouidou.fr/wp-content/uploads/2025/11/image-20250915-085752.png" alt="" class="wp-image-17888" srcset="https://ouidou.fr/wp-content/uploads/2025/11/image-20250915-085752.png 402w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250915-085752-300x35.png 300w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250915-085752-150x18.png 150w, https://ouidou.fr/wp-content/uploads/2025/11/image-20250915-085752-380x44.png 380w" sizes="(max-width:767px) 402px, 402px" /></figure></div>


<ul>
<li><em>α</em> (alpha): taux d&#8217;apprentissage (généralement entre 0 et 1, mais peut être supérieur dans certains cas spéciaux), correspond au paramètre <strong>lr</strong> dans notre fonction.</li>



<li><em>γ</em> (gamma): facteur d&#8217;actualisation qui valorise les récompenses futures, correspond au paramètre <strong>gamma</strong> dans notre fonction.</li>



<li><em>r</em> : récompense immédiate.</li>



<li><em>s</em>,<em>a</em> : état et action actuels.</li>



<li><em>s</em>′ : nouvel état après action.</li>
</ul>



<p>Dans notre implémentation, cette formule est appliquée avec les valeurs par défaut de <strong>lr = 0.1</strong> et <strong>gamma = 0.99</strong>, ce qui signifie que l&#8217;agent apprend modérément vite et accorde une grande importance aux récompenses futures.</p>



<h3 class="wp-block-heading" id="Stratégie-d'exploration"><strong>Stratégie d&#8217;exploration</strong></h3>



<p>Pour éviter que l&#8217;<strong>agent</strong> ne se contente d&#8217;une <strong>stratégie sous-optimale</strong>, on utilise une approche <strong>ε-greedy</strong> :</p>



<p>L&#8217;approche <strong>ε-greedy</strong> équilibre <strong>exploration</strong> et <strong>exploitation</strong> en <strong>Q-learning</strong> : l&#8217;<strong>agent</strong> explore <strong>aléatoirement</strong> avec une probabilité <strong>ε</strong>, sinon il choisit la <strong>meilleure action connue</strong>. Un <strong>ε élevé</strong> favorise l&#8217;<strong>exploration</strong> (utile au début), tandis qu&#8217;un <strong>ε faible</strong> privilégie l&#8217;<strong>exploitation</strong> des <strong>connaissances acquises</strong>.</p>



<p>Le <strong>epsilon decay</strong> consiste à <strong>réduire progressivement</strong> la valeur de <strong>ε</strong> au cours de l&#8217;<strong>entraînement</strong>. Cette <strong>diminution graduelle</strong> permet de commencer par une <strong>exploration intensive</strong> pour découvrir l&#8217;<strong>environnement</strong>, puis de converger vers une <strong>stratégie stable</strong> en privilégiant l&#8217;<strong>exploitation des connaissances</strong>.</p>



<p>Plusieurs <strong>approches</strong> existent pour implémenter cette <strong>décroissance</strong> :</p>



<ul>
<li>La <strong>décroissance exponentielle</strong> utilise la formule <strong>ε = ε_initial × decay_rate^épisode</strong> et offre une <strong>réduction rapide</strong> au début qui <strong>ralentit progressivement</strong>.</li>



<li>La <strong>décroissance linéaire</strong> applique une <strong>réduction constante</strong> à chaque épisode avec <strong>ε = ε_initial &#8211; (decay_step × épisode)</strong>.</li>



<li>Une approche particulièrement populaire est la <strong>décroissance avec plancher</strong>, qui suit <strong>ε = max(ε_min, ε × decay_rate)</strong> et maintient un <strong>niveau minimal d&#8217;exploration permanent</strong>, évitant que l&#8217;<strong>agent</strong> devienne trop <strong>rigide</strong>.</li>



<li>Enfin, la <strong>décroissance inverse</strong> propose une formule <strong>ε = ε_initial / (1 + decay_rate × épisode)</strong> pour une <strong>décroissance douce et continue</strong>.</li>
</ul>



<p>Chaque <strong>approche</strong> offre un <strong>compromis</strong> différent entre <strong>vitesse de convergence</strong> et <strong>maintien de l&#8217;exploration</strong>, le choix dépendant de la <strong>complexité de l&#8217;environnement</strong> et des <strong>objectifs d&#8217;apprentissage</strong>.</p>



<h3 class="wp-block-heading" id="Description-du-problème"><strong>Description du problème</strong></h3>



<p>Dans <em>Taxi-v3</em>, le joueur (notre agent IA) contrôle un taxi dans une grille de <strong>5&#215;5 cases</strong>. Sa mission est simple : récupérer un passager à un point donné et le déposer à la bonne destination.</p>



<p>L&#8217;environnement nous met à disposition tous les éléments nécessaires pour définir le problème d&#8217;apprentissage par renforcement de manière claire et structurée.</p>



<ul>
<li><strong>États</strong> : position du taxi, position du passager (4 emplacements possibles ou &#8220;dans le taxi&#8221;), et destination (4 emplacements possibles). Cela donne <strong>500 états possibles</strong>.</li>



<li><strong>Actions</strong> : 6 choix sont disponibles – se déplacer au nord, sud, est, ouest, prendre un passager, déposer un passager.</li>



<li><strong>Récompenses</strong> :
<ul>
<li>+20 si le passager est déposé au bon endroit.</li>



<li>-10 si le taxi tente une mauvaise action (par exemple déposer sans passager).</li>



<li>-1 pour chaque pas, afin d&#8217;encourager une solution rapide.</li>
</ul>
</li>
</ul>



<h2 class="wp-block-heading" id="Implémentation-en-Python"><strong>Implémentation en Python</strong></h2>



<p>Voici une version simplifiée de l&#8217;entraînement avec Q-Learning :</p>



<pre class="wp-block-code"><code class="">import gymnasium as gym
import numpy as np
# Création de l'environnement Taxi
env = gym.make("Taxi-v3")
# Initialisation de la Q-Table
state_space = env.observation_space.n
action_space = env.action_space.n
Q = np.zeros((state_space, action_space))
# Hyperparamètres
alpha = 0.1     # taux d'apprentissage
gamma = 0.6     # facteur d'actualisation
epsilon = 0.1   # exploration
episodes = 10000
# Entraînement
for episode in range(episodes):
    state, _ = env.reset()
    done = False
    while not done:
        if np.random.uniform(0,1) &lt; epsilon:
            action = env.action_space.sample()  # exploration
        else:
            action = np.argmax(Q[state])        # exploitation
        next_state, reward, done, truncated, info = env.step(action)
        # Mise à jour de la Q-Table
        best_next_action = np.argmax(Q[next_state])
        Q[state, action] = Q[state, action] + alpha * (
            reward + gamma * Q[next_state, best_next_action] - Q[state, action]
        )
        state = next_state</code></pre>



<p>Après un entraînement de 10000 épisodes comme dans notre exemple (quelques minutes) le taxi apprend à résoudre efficacement sa mission.</p>



<h2 class="wp-block-heading" id="Résultats-et-analyse"><strong>Résultats et analyse</strong></h2>



<h3 class="wp-block-heading" id="Évaluation-de-l'agent"><strong>Évaluation de l&#8217;agent</strong></h3>



<p>Une fois entraîné, l&#8217;agent peut être évalué sur plusieurs parties de test. Les métriques typiques sont :</p>



<ul>
<li><strong>score moyen</strong> par épisode,</li>



<li><strong>nombre moyen d&#8217;étapes</strong> nécessaires pour déposer le passager.</li>
</ul>



<p>En général, après un bon entraînement, l&#8217;agent réussit sa mission en <strong>moins de 20 étapes</strong>.</p>



<h3 class="wp-block-heading" id="Visualisation-des-performances"><strong>Visualisation des performances</strong></h3>



<p>On peut tracer la progression du score moyen :</p>



<pre class="wp-block-code"><code class="">import matplotlib.pyplot as plt
# Liste des récompenses obtenues à chaque épisode d'entraînement
plt.plot(rewards_per_episode) 
# Axe horizontal : numéro de l'épisode (de 0 à nombre total d'épisodes)
plt.xlabel("Épisodes") 
# Axe vertical : récompense cumulée par épisode
plt.ylabel("Score moyen") 
# Titre du graphique montrant l'évolution des performances
plt.title("Progression du taxi avec Q-Learning") 
# Affiche le graphique pour visualiser l'apprentissage de l'agent
plt.show() </code></pre>



<p>Voici par exemple un des graphiques de l&#8217;entraînement de notre <strong>agent</strong>. Ce graphique montre comment notre <strong>taxi</strong> apprend au fil du temps grâce au <strong>Q-Learning</strong>.</p>



<h3 class="wp-block-heading" id="Plusieurs-choses-sont-affiché-sur-ce-graphique.">Plusieurs choses sont affiché sur ce graphique.</h3>



<p><strong>l&#8217;axe horizontal</strong>, chaque point correspond à un <strong>épisode d&#8217;entraînement</strong>, c&#8217;est-à-dire une partie que joue notre taxi. Plus on avance vers la droite, plus l&#8217;agent a eu d&#8217;occasions d&#8217;apprendre.</p>



<p><strong>l&#8217;axe vertical</strong>, on y voit deux choses : En <strong>orange</strong>, on voit le <strong>nombre d&#8217;étapes</strong> que l&#8217;agent met pour terminer une partie. Au départ, ce nombre est très élevé (l&#8217;agent échoue souvent et atteint la limite de <strong>200 actions</strong>), puis il diminue progressivement à mesure que le taxi apprend à être plus <strong>efficace</strong>.</p>



<p>En <strong>vert</strong>, les <strong>récompenses</strong> obtenues par l&#8217;agent, elles vont très loin dans le <strong>négatif</strong> au départ, puis augmentent et se <strong>stabilisent</strong> quand le taxi apprend à bien jouer.</p>



<p>La ligne <strong>rouge</strong>, elle représente l&#8217;<strong>exploration</strong>. Au début, le taxi teste un peu tout au hasard (l&#8217;<strong>epsilon</strong> est élevé). Au fur et à mesure, il explore moins et applique ce qu&#8217;il a appris (l&#8217;<strong>epsilon diminue</strong> jusqu&#8217;à <strong>0</strong>).</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" width="1024" height="478" src="https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-1024x478.png" alt="" class="wp-image-17889" style="width:406px;height:auto" srcset="https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-1024x478.png 1024w, https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-300x140.png 300w, https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-768x358.png 768w, https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-150x70.png 150w, https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-380x177.png 380w, https://ouidou.fr/wp-content/uploads/2025/11/QLearning_graph-480x224.png 480w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></figure></div>


<p>Notre graphique illustre l&#8217;évolution des récompenses et du nombre de pas, où l&#8217;on observe une stabilisation progressive (convergence) des performances lorsque l&#8217;agent apprend une stratégie optimale, tandis que l&#8217;epsilon décroît vers zéro.</p>



<h2 class="wp-block-heading" id="Optimiser-les-performances-de-l'algorithme-Q-Learning"><strong>Optimiser les performances de l&#8217;algorithme Q-Learning</strong></h2>



<p>Une fois l&#8217;algorithme fonctionnel, il est intéressant de chercher à <strong>accélérer l&#8217;apprentissage</strong> et <strong>les performances finales de notre agent</strong>. Cela passe par l&#8217;optimisation des hyperparamètres.</p>



<h3 class="wp-block-heading" id="Le-taux-d'apprentissage-(lr)"><strong>Le taux d&#8217;apprentissage (lr)</strong></h3>



<p>Le <strong>taux d&#8217;apprentissage</strong> détermine l&#8217;<strong>importance</strong> accordée aux <strong>nouvelles informations</strong> par rapport aux <strong>connaissances déjà acquises</strong> dans la <strong>Q-Table</strong>. Dans notre approche, la <strong>valeur par défaut</strong> est fixée à <strong>0.1</strong> (sur une échelle de 0 à 1). Un <strong>taux trop faible</strong> entraîne un <strong>apprentissage très lent</strong> car l&#8217;<strong>agent</strong> intègre difficilement les <strong>nouvelles expériences</strong>, tandis qu&#8217;un <strong>taux trop élevé</strong> provoque des <strong>changements trop brutaux</strong> qui effacent les <strong>apprentissages précédents</strong>.</p>



<h3 class="wp-block-heading" id="Le-facteur-de-discount-(gamma)"><strong>Le facteur de discount (gamma)</strong></h3>



<p>Le <strong>facteur de discount</strong> détermine quelle <strong>importance</strong> l&#8217;<strong>agent</strong> accorde aux <strong>récompenses futures</strong> par rapport à celles qu&#8217;il peut obtenir <strong>immédiatement</strong>. Notre <strong>implémentation</strong> utilise une <strong>valeur par défaut</strong> de <strong>0.99</strong> (sur une échelle de 0 à 1). Un <strong>gamma faible</strong> incite l&#8217;<strong>agent</strong> à rechercher des <strong>gains immédiats</strong> sans se soucier des <strong>conséquences</strong>, alors qu&#8217;un <strong>gamma élevé</strong> le pousse à prendre des <strong>décisions</strong> qui peuvent être moins <strong>avantageuses maintenant</strong> mais plus <strong>bénéfiques à long terme</strong>.</p>



<h3 class="wp-block-heading" id="La-probabilité-d'exploration-(epsilon)"><strong>La probabilité d&#8217;exploration (epsilon)</strong></h3>



<p>La <strong>probabilité d&#8217;exploration</strong> équilibre entre l&#8217;<strong>exploration aléatoire</strong> de nouvelles <strong>actions</strong> et l&#8217;<strong>exploitation</strong> des <strong>meilleures actions connues</strong>. Notre approche utilise un <strong>decay exponentiel</strong> avec la formule : <strong>epsilon = min_epsilon + (max_epsilon &#8211; min_epsilon) * exp(-epsilon_decay * episode)</strong>.</p>



<p>Nos <strong>paramètres</strong> sont configurés avec :</p>



<ul>
<li>un <strong>epsilon initial</strong> de <strong>0.3</strong> pour une <strong>exploration modérée</strong> au début,</li>



<li>un <strong>max_epsilon</strong> de <strong>1.0</strong> permettant une <strong>exploration maximale</strong> si nécessaire,</li>



<li>un <strong>min_epsilon</strong> de <strong>0.001</strong> pour une <strong>exploitation quasi-totale</strong> en fin d&#8217;<strong>entraînement</strong>,</li>



<li>et un <strong>epsilon_decay</strong> de <strong>0.1</strong> pour une <strong>décroissance progressive</strong>.</li>
</ul>



<p>Cette <strong>configuration</strong> permet une <strong>transition fluide</strong> de l&#8217;<strong>exploration</strong> vers l&#8217;<strong>exploitation</strong>, avec un suivi de l&#8217;<strong>évolution d&#8217;epsilon</strong> via <strong>epsilon_vec</strong> pour analyser le <strong>comportement de l&#8217;agent</strong>.</p>



<pre class="wp-block-code"><code class="">epsilon = 1.0
epsilon_min = 0.01
epsilon_decay = 0.995
for episode in range(episodes):
    ...
    epsilon = max(epsilon_min, epsilon * epsilon_decay) #  Décroissance avec plancher </code></pre>



<h3 class="wp-block-heading" id="Le-nombre-d'épisodes"><strong>Le nombre d&#8217;épisodes</strong></h3>



<ul>
<li>Plus il y a d&#8217;épisodes, plus l&#8217;agent a de chances de converger.</li>



<li>Comme nous pouvons le voir sur le graphique d&#8217;entraînement, nous atteignons un point de convergence autour de <strong>20 000 épisodes</strong></li>
</ul>



<h3 class="wp-block-heading" id="Comparer-les-résultats"><strong>Comparer les résultats</strong></h3>



<p>La meilleure façon de trouver les bons réglages est de tester plusieurs combinaisons et de comparer les courbes de performance. Une approche simple est la recherche par grille (<em><strong>grid search</strong></em>) : tester différentes valeurs de α, γ, ε et observer la <strong>convergence</strong>.</p>



<pre class="wp-block-code"><code class="">def grid_search():
    learning_rates = [0.001, 0.01, 0.1]
    gammas = [0.9, 0.95, 0.99]
    epsilons = [0.1, 0.2, 0.3]
    epsilon_decays = [0.001, 0.01, 0.1]
    best_params = None
    best_reward = float('-inf')
    for lr, gamma, epsilon, epsilon_decay in itertools.product(learning_rates, gammas, epsilons, epsilon_decays):
        print(f"Training with lr={lr}, gamma={gamma}, epsilon={epsilon}, epsilon_decay={epsilon_decay}")
        _, mean_reward = train(env=gym.make("Taxi-v3"),
                               episodes=1000,
                               lr=lr,
                               gamma=gamma,
                               epsilon=epsilon,
                               epsilon_decay=epsilon_decay)
        if mean_reward &gt; best_reward:
            best_reward = mean_reward
            best_params = (lr, gamma, epsilon, epsilon_decay)
    print(f"Best parameters: lr={best_params[0]}, gamma={best_params[1]}, epsilon={best_params[2]}, epsilon_decay={best_params[3]}")
    print(f"Best mean reward: {best_reward}")
grid_search()</code></pre>



<p>Cette méthode peut être améliorée en élargissant la plage de valeurs testées pour chaque paramètre et en augmentant la granularité de la recherche.<br></p>



<h2 class="wp-block-heading" id="Limites-du-Q-Learning"><strong>Limites du Q-Learning</strong></h2>



<p>Même si le <strong>Q-Learning</strong> fonctionne très bien pour un <strong>petit environnement</strong> comme <strong>Taxi</strong>, il présente des <strong>limites importantes</strong>. La <strong>scalabilité</strong> constitue un <strong>problème majeur</strong> car la <strong>Q-Table</strong> grandit de manière <strong>exponentielle</strong> quand l&#8217;<strong>espace d&#8217;états</strong> devient énorme, rendant <strong>impossible son stockage</strong> en <strong>mémoire vive (RAM)</strong> pour des <strong>environnements complexes</strong>.</p>



<p>De plus, l&#8217;<strong>algorithme</strong> souffre d&#8217;un <strong>manque de généralisation</strong> puisqu&#8217;il ne peut pas <strong>apprendre</strong> sur des <strong>états</strong> qu&#8217;il n&#8217;a jamais <strong>rencontrés</strong> auparavant. Enfin, l&#8217;<strong>exploration ε-greedy</strong> reste une <strong>approche basique</strong>, alors que d&#8217;autres méthodes comme l&#8217;<strong>exploration de Boltzmann</strong> ou <strong>UCB (Upper Confidence Bound)</strong> offrent des <strong>stratégies plus intelligentes</strong>.</p>



<p>Pour dépasser ces <strong>limites</strong>, on peut utiliser des <strong>réseaux de neurones</strong> pour <strong>approximer la fonction Q</strong>. C&#8217;est le principe des <strong>Deep Q-Networks (DQN)</strong>, utilisés dans des <strong>environnements beaucoup plus complexes</strong> comme les <strong>jeux vidéos</strong>, la <strong>robotique</strong> ou d&#8217;autres <strong>domaines nécessitant une représentation continue des états</strong>.</p>



<h2 class="wp-block-heading" id="Visualisation-de-l'agent"><strong>Visualisation de l&#8217;agent</strong></h2>



<p>Gymnasium permet de visualiser le plateau de jeu avec :</p>



<pre class="wp-block-code"><code class="">import gymnasium as gym
env = gym.make("Taxi-v3", render_mode="human")
print(env.render())</code></pre>



<p>Nous avons accès à plusieurs valeurs possibles pour le paramètre render_mode. (ansi, rgb_array, rgb_array_list, human).</p>



<p>Pour cet article nous utiliserons le render_mode &#8220;human&#8221; qui offre la meilleure visualisation graphique interactive en temps réel.</p>



<p>Et voilà notre agent à l&#8217;œuvre !</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex"><div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" width="550" height="350" data-id="17894" src="https://ouidou.fr/wp-content/uploads/2025/11/taxi_game.gif" alt="" class="wp-image-17894"/></figure></div></figure>



<h2 class="wp-block-heading" id="Conclusion"><strong>Conclusion</strong></h2>



<p>J&#8217;espère vous avoir fait découvrir un sujet intéressant à travers cet article. L&#8217;environnement Taxi-v3 est un excellent point d&#8217;entrée dans l&#8217;IA. Il offre une complexité suffisante pour comprendre les mécanismes fondamentaux tout en restant accessible.</p>



<p>Cet exemple pratique nous a donné un aperçu complet de l&#8217;apprentissage par renforcement. Nous avons vu la construction de la Q-Table et l&#8217;optimisation des <strong>hyperparamètres</strong>. Nous avons observé comment un agent développe une stratégie optimale par l&#8217;expérience seule, sans supervision directe.</p>



<p>Le Q-Learning s&#8217;applique concrètement dans plusieurs domaines. Par exemple, l&#8217;optimisation de systèmes de recommandation où l&#8217;agent apprend à proposer le contenu le plus pertinent. Ou encore la gestion automatique des ressources serveur pour optimiser les performances. Il peut aussi développer des chatbots qui s&#8217;améliorent grâce aux retours utilisateurs. Ces applications montrent qu&#8217;un algorithme simple peut résoudre des problèmes complexes du monde réel.</p>



<p>Pour approfondir vos connaissances, plusieurs pistes s&#8217;offrent à vous. Explorez d&#8217;autres environnements Gymnasium plus complexes. Expérimentez avec des variantes comme <strong>SARSA</strong>. Ou orientez-vous vers le <strong>Deep Reinforcement Learning</strong> avec les DQN pour des problèmes nécessitant une représentation continue des états.</p>



<h2 class="wp-block-heading" id="liens-utiles"><strong>liens utiles</strong></h2>



<p><strong>Le projet</strong> :<br><a href="https://gitlab.tech.ouidou.fr/kevin.aubel/q-learning">https://gitlab.tech.ouidou.fr/kevin.aubel/q-learning</a></p>



<h3 class="wp-block-heading" id="Articles-similaire:"><strong>Articles similaire:</strong></h3>



<p><a href="https://www.geeksforgeeks.org/machine-learning/q-learning-in-python/">Q-Learning in Reinforcement Learning &#8211; GeeksforGeeks</a></p>



<p><a href="https://medium.com/@goldengrisha/a-beginners-guide-to-q-learning-understanding-with-a-simple-gridworld-example-2b6736e7e2c9">A Beginner’s Guide to Q-Learning: Understanding with a Simple Gridworld Example</a></p>



<p><a href="https://medium.com/analytics-vidhya/reinforcement-learning-101-bf42523fd6ad">Reinforcement Learning 101</a></p>



<h3 class="wp-block-heading" id="Site-avec-implementation-de-Q-learning:--[inlineCard]"><strong>Site avec implementation de Q-learning:<br></strong><a href="https://www.kaggle.com/search?q=taxi-v3">Search | Kaggle</a></h3>



<p><a href="https://huggingface.co/simonescaccia/dqn-Taxi-v3">simonescaccia/dqn-Taxi-v3 · Hugging Face</a></p>



<p><a href="https://huggingface.co/winkin119/q-Taxi-v3">winkin119/q-Taxi-v3 · Hugging Face</a></p>
<p>L’article <a href="https://ouidou.fr/2026/01/06/introduction-pratique-au-q-learning-avec-gymnasium-taxi-v3/">Introduction pratique au Q-learning avec Gymnasium Taxi-v3</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/Introduction-pratique-au-Q-learning-avec-Gymnasium-Taxi-v3-1.png" medium="image"></media:content>
				</item>
		<item>
		<title>Introduction à K6</title>
		<link>https://ouidou.fr/2025/12/09/introduction-a-k6/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Tue, 09 Dec 2025 13:14:00 +0000</pubDate>
				<category><![CDATA[Technique]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17873</guid>

					<description><![CDATA[<p>Écrit par Mouloud H. Définitions des types de tests Avant de plonger dans l&#8217;utilisation de K6, il est important de comprendre les différents types de tests<span class="excerpt-hellip"> […]</span></p>
<p>L’article <a href="https://ouidou.fr/2025/12/09/introduction-a-k6/">Introduction à K6</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Écrit par Mouloud H.</em></p>



<h2 class="wp-block-heading" id="Définitions-des-types-de-tests"><strong>Définitions des types de tests</strong></h2>



<p>Avant de plonger dans l&#8217;utilisation de K6, il est important de comprendre les différents types de tests qu&#8217;il permet de réaliser :</p>



<ul>
<li><strong>Smoke testing</strong> : Un test rapide visant à valider que le système ou le script fonctionne correctement sous une charge minimale. Souvent appelé &#8220;test de santé&#8221;, il s&#8217;agit d&#8217;une méthode préliminaire pour vérifier que les fonctionnalités essentielles de l&#8217;application fonctionnent correctement avant de procéder à des tests plus approfondis. Cela permet de s&#8217;assurer qu&#8217;il n&#8217;y a pas de problèmes critiques, comme des erreurs empêchant l&#8217;application de démarrer ou de répondre correctement à des requêtes simples.</li>



<li><strong>Load testing</strong> : Ce type de test mesure les performances du système sous une charge normale ou attendue. L&#8217;objectif est de vérifier comment le système se comporte dans des conditions standard d&#8217;utilisation.</li>



<li><strong>Stress testing</strong> : Ici, le test pousse le système au-delà de ses limites normales pour évaluer sa stabilité et sa résilience sous une charge extrême.</li>



<li><strong>Soak testing</strong> : Aussi appelé test d&#8217;endurance, il évalue les performances et la fiabilité du système sur une période prolongée, permettant d&#8217;identifier les éventuelles fuites de mémoire ou autres problèmes de stabilité à long terme.</li>
</ul>



<h2 class="wp-block-heading" id="Qu'est-ce-que-K6-?"><strong>Qu&#8217;est-ce que K6 ?</strong></h2>



<p><a href="https://k6.io/" target="_blank" rel="noreferrer noopener">K6</a> est un outil de test de charge open source, conçu pour les développeurs et les équipes DevOps. Il permet de simuler des charges réalistes sur des applications web et des API, afin de tester leurs performances et leur évolutivité. Développé en Go et racheté par Grafana Labs en 2021, K6 offre une solution complète pour détecter les régressions de performance et construire des systèmes robustes.</p>



<h2 class="wp-block-heading" id="Pourquoi-utiliser-K6-?"><strong>Pourquoi utiliser K6 ?</strong></h2>



<ul>
<li><strong>Simplicité d&#8217;utilisation</strong> : Facile à installer et à utiliser, avec une prise en main rapide grâce à JavaScript pour la rédaction des scripts.</li>



<li><strong>Haute performance</strong> : Consomme moins de ressources que les outils basés sur la JVM comme Gatling ou JMeter.</li>



<li><strong>Polyvalence</strong> : Convient pour différents types de tests, comme le smoke testing, le load testing, le stress testing ou encore le soak testing.</li>



<li><strong>Visualisation des données</strong> : Compatible avec des outils comme Grafana et Datadog pour des tableaux de bord interactifs et un suivi en temps réel.</li>



<li><strong>Open source et gratuit</strong> : Accessible à tous sans frais, avec une documentation complète.</li>
</ul>



<h2 class="wp-block-heading" id="Fonctionnalités-principales"><strong>Fonctionnalités principales</strong></h2>



<p>K6 se distingue par plusieurs fonctionnalités majeures, qui en font un outil très polyvalent et puissant pour les tests de performance :</p>



<ul>
<li><strong>Tests de charge</strong> : Cette fonctionnalité permet de simuler des milliers d&#8217;utilisateurs simultanés pour évaluer la résilience de vos applications. Par exemple, vous pouvez identifier comment votre serveur répond lorsqu&#8217;un grand nombre d&#8217;utilisateurs accèdent simultanément à une API ou à un site web. C&#8217;est essentiel pour anticiper les comportements lors de pics d&#8217;activité ou lors d&#8217;événements promotionnels importants.</li>



<li><strong>Tests de performance</strong> : Avec K6, vous pouvez analyser les goulets d&#8217;étranglement dans vos systèmes. Cela inclut la détection de lenteurs dans les bases de données, les appels réseau ou encore les API tierces. Grâce à des métriques détaillées, comme le temps moyen de réponse ou les percentiles, vous obtenez une vue complète des performances de votre application sous diverses charges.</li>



<li><strong>Tests fonctionnels</strong> : Validez les comportements attendus de vos API même sous des charges importantes. Par exemple, vous pouvez vous assurer que les réponses aux requêtes respectent bien les spécifications (codes HTTP, contenu attendu, etc.), garantissant ainsi une qualité de service optimale.</li>



<li><strong>Métriques personnalisées</strong> : K6 permet de définir vos propres métriques en fonction de vos besoins spécifiques. Par exemple, vous pouvez mesurer le taux d&#8217;erreur, le temps de traitement d&#8217;une requête ou encore le pourcentage de requêtes réussies. Ces métriques offrent une flexibilité et une précision accrues pour vos analyses.</li>



<li><strong>Rapports détaillés</strong> : Les rapports générés par K6 incluent des données complètes sur les performances de vos tests. Vous pouvez visualiser les tendances, les erreurs et les temps de réponse sous différentes formes, facilitant ainsi la prise de décision pour optimiser votre application.</li>



<li><strong>Gestion des scénarios avancés</strong> : K6 offre une configuration flexible des scénarios de test, permettant de simuler des comportements proches de ceux des utilisateurs réels. Cela inclut la possibilité de moduler progressivement la charge, d&#8217;ajouter des délais entre les actions des utilisateurs ou de tester différentes étapes d&#8217;un processus utilisateur complexe.</li>
</ul>



<h2 class="wp-block-heading" id="Prise-en-main-avec-K6"><strong>Prise en main avec K6</strong></h2>



<h2 class="wp-block-heading" id="Installation"><strong>Installation</strong></h2>



<p>Pour installer K6, utilisez le gestionnaire de paquets approprié à votre système :</p>



<h3 class="wp-block-heading" id="Sous-macOS"><strong>Sous macOS</strong></h3>



<pre class="wp-block-code"><code class="">brew install k6</code></pre>



<h3 class="wp-block-heading"><strong>Sous Linux</strong></h3>



<pre class="wp-block-code"><code class="">sudo apt update &amp;&amp; sudo apt install -y k6</code></pre>



<h3 class="wp-block-heading"><strong>Sous Windows</strong></h3>



<p><a href="https://k6.io/docs/get-started/installation/">Téléchargez l&#8217;exécutable</a> et ajoutez-le à votre PATH.</p>



<h2 class="wp-block-heading" id="Création-d'un-script-de-test"><strong>Création d&#8217;un script de test</strong></h2>



<p>Un script K6 est écrit en JavaScript ES6. Voici un exemple simple pour tester une API :</p>



<pre class="wp-block-code"><code class="">import http from 'k6/http';
import { check } from 'k6';
export default function () {
    const res = http.get('http://localhost:3000/slow');
    check(res, {
        'status est 200': (r) =&gt; r.status === 200,
    });
}</code></pre>



<h2 class="wp-block-heading" id="Présentation-du-serveur-Express"><strong>Présentation du serveur Express</strong></h2>



<p>Pour les tests réalisés avec K6, nous avons utilisé un petit serveur Express local qui simule deux types de requêtes : une requête rapide et une requête lente. Ce serveur est conçu pour servir de base à nos tests de charge et de performance.</p>



<p>Voici le code de ce serveur :</p>



<pre class="wp-block-code"><code class="">const express = require('express');
const app = express();
const port = 3000;
app.get('/fast', (req, res) =&gt; {
    setTimeout(() =&gt; res.send('Fast response!'), 50);
});
app.get('/slow', (req, res) =&gt; {
    setTimeout(() =&gt; res.send('Slow response!'), 2000);
});
app.listen(port, () =&gt; {
    console.log(`Server running at http://localhost:${port}`);
});</code></pre>



<h2 class="wp-block-heading" id="Exécution-d'un-test"><strong>Exécution d&#8217;un test</strong></h2>



<p>Pour exécuter le script ci-dessus, utilisez la commande suivante :</p>



<pre class="wp-block-code"><code class="">k6 run script.js</code></pre>



<p>Le résultat obtenu est le suivant :</p>



<pre class="wp-block-code"><code class="">checks.........................: 100.00% 1 out of 1
     data_received..................: 241 B   120 B/s
     data_sent......................: 84 B    42 B/s
     http_req_blocked...............: avg=1.26ms min=1.26ms med=1.26ms max=1.26ms p(90)=1.26ms p(95)=1.26ms
     http_req_connecting............: avg=210µs  min=210µs  med=210µs  max=210µs  p(90)=210µs  p(95)=210µs 
     http_req_duration..............: avg=2s     min=2s     med=2s     max=2s     p(90)=2s     p(95)=2s    
       { expected_response:true }...: avg=2s     min=2s     med=2s     max=2s     p(90)=2s     p(95)=2s    
     http_req_failed................: 0.00%   0 out of 1
     http_req_receiving.............: avg=224µs  min=224µs  med=224µs  max=224µs  p(90)=224µs  p(95)=224µs 
     http_req_sending...............: avg=121µs  min=121µs  med=121µs  max=121µs  p(90)=121µs  p(95)=121µs 
     http_req_tls_handshaking.......: avg=0s     min=0s     med=0s     max=0s     p(90)=0s     p(95)=0s    
     http_req_waiting...............: avg=2s     min=2s     med=2s     max=2s     p(90)=2s     p(95)=2s    
     http_reqs......................: 1       0.497928/s
     iteration_duration.............: avg=2s     min=2s     med=2s     max=2s     p(90)=2s     p(95)=2s    
     iterations.....................: 1       0.497928/s
     vus............................: 1       min=1      max=1
     vus_max........................: 1       min=1      max=1</code></pre>



<h3 class="wp-block-heading" id="Définition-des-résultats-générés"><strong>Définition des résultats générés</strong></h3>



<ul>
<li><strong>checks</strong> : Indique le pourcentage et le nombre de vérifications réussies.</li>



<li><strong>data_received</strong> : Volume total de données reçues par le script.</li>



<li><strong>data_sent</strong> : Volume total de données envoyées par le script.</li>



<li><strong>http_req_blocked</strong> : Temps passé à établir une connexion (y compris l’attente si toutes les connexions disponibles sont utilisées).</li>



<li><strong>http_req_connecting</strong> : Temps passé à établir la connexion TCP.</li>



<li><strong>http_req_duration</strong> : Durée totale de la requête, incluant le temps d’attente pour une réponse et l’échange de données.</li>



<li><strong>http_req_failed</strong> : Pourcentage de requêtes HTTP ayant échoué.</li>



<li><strong>http_req_receiving</strong> : Temps pris pour recevoir les données après qu&#8217;une réponse a commencé.</li>



<li><strong>http_req_sending</strong> : Temps pris pour envoyer les données au serveur.</li>



<li><strong>http_req_tls_handshaking</strong> : Temps pris pour établir une connexion TLS (si applicable).</li>



<li><strong>http_req_waiting</strong> : Temps d&#8217;attente avant de recevoir la première réponse du serveur.</li>



<li><strong>http_reqs</strong> : Nombre total de requêtes HTTP effectuées.</li>



<li><strong>iteration_duration</strong> : Temps total pris pour exécuter une itération complète du script.</li>



<li><strong>iterations</strong> : Nombre total d’itérations exécutées pendant le test.</li>



<li><strong>vus</strong> : Nombre d’utilisateurs virtuels actifs pendant le test.</li>



<li><strong>vus_max</strong> : Nombre maximal d’utilisateurs virtuels pendant le test.</li>
</ul>



<h2 class="wp-block-heading" id="Exemples-de-tests"><strong>Exemples de tests</strong></h2>



<h3 class="wp-block-heading" id="Smoke-Test"><strong>Smoke Test</strong></h3>



<pre class="wp-block-code"><code class="">import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
    http.get('http://localhost:3000/fast');
    sleep(1);
}</code></pre>



<h4 class="wp-block-heading" id="Résultat-attendu"><strong>Résultat attendu</strong></h4>



<p>Voici un exemple de résultat obtenu lors de l&#8217;exécution d&#8217;un Smoke Test :</p>



<pre class="wp-block-code"><code class="">scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop):
              * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s)
     data_received..................: 241 B 221 B/s
     data_sent......................: 84 B  77 B/s
     http_req_blocked...............: avg=7.09ms  min=7.09ms  med=7.09ms  max=7.09ms  p(90)=7.09ms  p(95)=7.09ms 
     http_req_connecting............: avg=189µs   min=189µs   med=189µs   max=189µs   p(90)=189µs   p(95)=189µs  
     http_req_duration..............: avg=74.24ms min=74.24ms med=74.24ms max=74.24ms p(90)=74.24ms p(95)=74.24ms
       { expected_response:true }...: avg=74.24ms min=74.24ms med=74.24ms max=74.24ms p(90)=74.24ms p(95)=74.24ms
     http_req_failed................: 0.00% 0 out of 1
     http_req_receiving.............: avg=55µs    min=55µs    med=55µs    max=55µs    p(90)=55µs    p(95)=55µs   
     http_req_sending...............: avg=422µs   min=422µs   med=422µs   max=422µs   p(90)=422µs   p(95)=422µs  
     http_req_tls_handshaking.......: avg=0s      min=0s      med=0s      max=0s      p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=73.76ms min=73.76ms med=73.76ms max=73.76ms p(90)=73.76ms p(95)=73.76ms
     http_reqs......................: 1     0.918662/s
     iteration_duration.............: avg=1.08s   min=1.08s   med=1.08s   max=1.08s   p(90)=1.08s   p(95)=1.08s  
     iterations.....................: 1     0.918662/s
     vus............................: 1     min=1      max=1
     vus_max........................: 1     min=1      max=1</code></pre>



<p>Le rapport montre que l&#8217;API répond correctement avec des temps de réponse très courts, ce qui est attendu dans un Smoke Test.</p>



<h3 class="wp-block-heading" id="Stress-Test"><strong>Stress Test</strong></h3>



<p>Le Stress Test pousse le système au-delà de ses limites pour évaluer sa stabilité et identifier les points de défaillance. Il permet de déterminer à quel moment le système commence à échouer lorsqu&#8217;il est soumis à une charge importante.</p>



<h4 class="wp-block-heading" id="Exemple-de-script"><strong>Exemple de script</strong></h4>



<pre class="wp-block-code"><code class="">import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
    stages: [
        { duration: '30s', target: 200 },
        { duration: '1m', target: 15000 },
        { duration: '20s', target: 0 },
    ],
};
export default function () {
    http.get('http://localhost:3000/slow');
    sleep(1);
}</code></pre>



<h4 class="wp-block-heading" id="Résultat-attendu.1"><strong>Résultat attendu</strong></h4>



<p>Voici un exemple de résultat obtenu lors d&#8217;un Stress Test :</p>



<pre class="wp-block-code"><code class="">scenarios: (100.00%) 1 scenario, 15000 max VUs, 2m0s max duration (incl. graceful stop):
              * default: Up to 15000 looping VUs for 2m0s over 3 stages (gracefulRampDown: 20s, gracefulStop: 20s)
    ...
    WARN[0088] Request Failed                                error="Get \"http://localhost:3000/slow\": dial tcp 127.0.0.1:3000: connect: connection reset by peer"
    WARN[0088] Request Failed                                error="Get \"http://localhost:3000/slow\": read tcp 127.0.0.1:59822-&gt;127.0.0.1:3000: read: connection reset by peer"
    ...
     data_received..................: 50 MB  445 kB/s
     data_sent......................: 18 MB  155 kB/s
     http_req_blocked...............: avg=1.03ms   min=0s    med=3µs  max=1.92s    p(90)=23µs  p(95)=221µs
     http_req_connecting............: avg=1.01ms   min=0s    med=0s   max=1.92s    p(90)=0s    p(95)=181µs
     http_req_duration..............: avg=2.02s    min=0s    med=2s   max=3.59s    p(90)=2.07s p(95)=2.17s
       { expected_response:true }...: avg=2.02s    min=1.99s med=2s   max=3.59s    p(90)=2.07s p(95)=2.17s
     http_req_failed................: 0.01%  26 out of 208653
     http_req_receiving.............: avg=58.19µs  min=0s    med=18µs max=156.64ms p(90)=64µs  p(95)=129µs
     http_req_sending...............: avg=165.75µs min=0s    med=6µs  max=295.11ms p(90)=35µs  p(95)=98µs 
     http_req_tls_handshaking.......: avg=0s       min=0s    med=0s   max=0s       p(90)=0s    p(95)=0s   
     http_req_waiting...............: avg=2.02s    min=0s    med=2s   max=3.59s    p(90)=2.07s p(95)=2.17s
     http_reqs......................: 208653 1847.535897/s
     iteration_duration.............: avg=3.03s    min=1s    med=3s   max=4.93s    p(90)=3.08s p(95)=3.18s
     iterations.....................: 208653 1847.535897/s
     vus............................: 37     min=3            max=15000
     vus_max........................: 15000  min=15000        max=15000
running (1m52.9s), 00000/15000 VUs, 208653 complete and 0 interrupted iterations</code></pre>



<p>Ce résultat montre que le système est soumis à une charge très élevée, avec des utilisateurs simultanés atteignant 15 000 au pic. Les temps de réponse restent raisonnables bien que légèrement augmentés sous la charge. Quelques erreurs peuvent apparaître (par exemple, 0.01% d&#8217;échecs), mais cela est attendu dans des tests de stress extrêmes. Une analyse plus approfondie peut être nécessaire pour optimiser les performances sous ces conditions.</p>



<h2 class="wp-block-heading" id="Personnalisation-des-métriques"><strong>Personnalisation des métriques</strong></h2>



<p>K6 permet de créer des métriques personnalisées pour enrichir les rapports. Voici un exemple mesurant le taux d&#8217;erreurs :</p>



<pre class="wp-block-code"><code class="">import http from 'k6/http';
import { Rate } from 'k6/metrics';
const errorRate = new Rate('error_rate');
export default function () {
    const res = http.get('http://localhost:3000/fast');
    errorRate.add(res.status &gt;= 122);
}</code></pre>



<pre class="wp-block-code"><code class="">data_received..................: 241 B   4.2 kB/s
     data_sent......................: 84 B    1.5 kB/s
     error_rate.....................: 100.00% 1 out of 1
     http_req_blocked...............: avg=1.39ms  min=1.39ms  med=1.39ms  max=1.39ms  p(90)=1.39ms  p(95)=1.39ms 
running (00m00.1s), 0/1 VUs, 1 complete and 0 interrupted iterations</code></pre>



<h2 class="wp-block-heading" id="Intégration-avec-Grafana-et-Prometheus"><strong>Intégration avec Grafana et Prometheus</strong></h2>



<p>Voici une configuration complète pour visualiser vos résultats dans Grafana et Prometheus.</p>



<h3 class="wp-block-heading" id="Pré-requis"><strong>Pré-requis</strong></h3>



<ul>
<li>Docker et Docker Compose installés sur votre machine.</li>
</ul>



<h3 class="wp-block-heading" id="Configuration-Docker-Compose"><strong>Configuration Docker Compose</strong></h3>



<p>Créez un fichier <code>docker-compose.yml</code> :</p>



<pre class="wp-block-code"><code class="">version: '3.7'
services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--web.enable-remote-write-receiver"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - monitoring
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3001:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    networks:
      - monitoring
networks:
  monitoring:
volumes:
  grafana-data:</code></pre>



<h3 class="wp-block-heading" id="Configuration-Prometheus"><strong>Configuration Prometheus</strong></h3>



<p>Créez un fichier <code>prometheus.yml</code> :</p>



<pre class="wp-block-code"><code class="">global:
  scrape_interval: 15s
scrape_configs:
  - job_name: 'k6'
    static_configs:
      - targets: ['host.docker.internal:6565']</code></pre>



<h3 class="wp-block-heading" id="Exécution"><strong>Exécution</strong></h3>



<p>Démarrez les conteneurs :</p>



<pre class="wp-block-code"><code class="">docker-compose up -d</code></pre>



<h3 class="wp-block-heading" id="Lancer-un-test-K6-avec-Prometheus-Remote-Write"><strong>Lancer un test K6 avec Prometheus Remote Write</strong></h3>



<p>Ajoutez cette configuration dans votre script K6 :</p>



<pre class="wp-block-code"><code class="">import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
    stages: [
        { duration: '30s', target: 50 },  // Monter jusqu'à 50 utilisateurs virtuels
        { duration: '1m', target: 10000 }, // Monter jusqu'à 10000 utilisateurs virtuels
        { duration: '2m', target: 200 }, // Monter jusqu'à 200 utilisateurs virtuels
        { duration: '30s', target: 0 },  // Descendre progressivement à 0
    ],
    thresholds: {
        http_req_duration: ['p(95)&lt;2000'], // 95% des requêtes doivent répondre en moins de 2s
        http_req_failed: ['rate&lt;0.01'],   // Moins de 1% des requêtes échouées
    },
    ext: {
        experimental: {
            prometheus_rww: {
                address: 'http://host.docker.internal:9090/api/v1/write',
                pushInterval: '5s',
            },
        },
    },
};
export default function () {
    const fastRes = http.get('http://localhost:3000/fast');
    check(fastRes, {
        'status is 200': (r) =&gt; r.status === 200,
        'response time &lt; 100ms': (r) =&gt; r.timings.duration &lt; 100,
    });
    const slowRes = http.get('http://localhost:3000/slow');
    check(slowRes, {
        'status is 200': (r) =&gt; r.status === 200,
        'response time &lt; 300ms': (r) =&gt; r.timings.duration &lt; 300,
    });
    sleep(1);
}</code></pre>



<h3 class="wp-block-heading" id="Configurer-Grafana"><strong>Configurer Grafana</strong></h3>



<ol start="1">
<li>Accédez à Grafana via <a href="http://localhost:3001/">http://localhost:3001</a>.</li>



<li>Connectez-vous (utilisateur : admin, mot de passe : admin).</li>



<li>Ajoutez Prometheus comme source de données :
<ul>
<li>URL : <code>http://prometheus:9090</code></li>
</ul>
</li>



<li>Importez un tableau de bord K6 disponible sur Grafana Dashboards (ID : 19665). (<a href="https://grafana.com/grafana/dashboards/19665-k6-prometheus/">k6 Prometheus | Grafana Labs</a> )</li>
</ol>



<p>Exécution du test :</p>



<pre class="wp-block-code"><code class="">k6 run --out experimental-prometheus-rw script.js</code></pre>



<h2 class="wp-block-heading" id="Résultats-des-tests-et-visualisation-dans-Grafana"><strong>Résultats des tests et visualisation dans Grafana</strong></h2>



<p>Après avoir exécuté le test de charge avec K6, nous avons intégré les données dans Prometheus et visualisé les résultats dans Grafana. Cette configuration permet une analyse approfondie des performances de votre API en temps réel. Voici deux exemples de tableaux de bord obtenus lors des tests et disponible sur localhost:3001:</p>



<h3 class="wp-block-heading" id="Exemple-de-tableau-de-bord-1"><strong>Exemple de tableau de bord 1</strong></h3>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/374bf795-d675-46d1-b960-b6071e8b4051/variants/fdfc879d-e3a5-43a4-9cf3-ed92feb2e682/src" alt="" style="width:486px;height:auto"/></figure>



<p>Ce tableau affiche les métriques clés suivantes :</p>



<ul>
<li><strong>Taux de transfert (data sent/received)</strong> : Analyse de la quantité de données envoyées et reçues au cours du test.</li>



<li><strong>Durée des requêtes HTTP</strong> : Répartition des durées de réponse pour les requêtes réussies, ainsi que les statistiques détaillées par URL.</li>



<li><strong>Taux de requêtes par seconde</strong> : Indication de la charge générée par les utilisateurs virtuels (Virtual Users).</li>
</ul>



<h3 class="wp-block-heading" id="Exemple-de-tableau-de-bord-2"><strong>Exemple de tableau de bord 2</strong></h3>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/99f724cc-2a65-4905-9b62-bf6b901ab0cc/variants/85928072-5bfe-4e34-b376-cd2ded61b698/src" alt="" style="width:496px;height:auto"/></figure>



<p>Dans ce tableau, nous pouvons observer :</p>



<ul>
<li><strong>Vue d&#8217;ensemble des performances</strong> : Indication des utilisateurs virtuels actifs (VUs), des requêtes HTTP envoyées, et des taux de succès/échec.</li>



<li><strong>Durée des requêtes HTTP</strong> : Visualisation des temps de réponse moyens et des percentiles élevés (p95, p99) pour détecter les points d&#8217;anomalie.</li>



<li><strong>Rythme des requêtes</strong> : Statistiques sur les requêtes par seconde au pic de la charge.</li>
</ul>



<p>Ces graphiques mettent en évidence les performances globales de votre système et permettent de diagnostiquer les éventuels goulots d&#8217;étranglement.</p>



<h2 class="wp-block-heading" id="Meilleures-pratiques-pour-K6"><strong>Meilleures pratiques pour K6</strong></h2>



<ul>
<li><strong>Modularité</strong> : Divisez vos scripts pour une meilleure lisibilité et maintenance.</li>



<li><strong>Validation</strong> : Utilisez des <code>check</code> pour valider les réponses de vos API.</li>



<li><strong>Rapports avancés</strong> : Intégrez avec Grafana pour visualiser les métriques en temps réel.</li>



<li><strong>Automatisation</strong> : Intégrez K6 dans vos pipelines CI/CD pour surveiller continuellement les performances.</li>
</ul>



<h2 class="wp-block-heading" id="Conclusion"><strong>Conclusion</strong></h2>



<p>K6 est un outil indispensable pour évaluer la performance et la résilience des applications modernes. Sa simplicité, ses hautes performances et ses nombreuses options en font un choix idéal pour les développeurs et les équipes DevOps. Essayez-le pour garantir une expérience utilisateur optimale, même sous des charges importantes.</p>



<h2 class="wp-block-heading" id="Sources"><strong>Sources</strong></h2>



<ul>
<li><a href="https://grafana.com/docs/k6/latest/get-started/running-k6/"><strong>grafana.com/docs/k6/latest</strong></a></li>



<li><a href="https://grafana.com/docs/k6/latest/results-output/grafana-dashboards"><strong>grafana-dashboards</strong></a></li>



<li><a href="https://medium.com/@srinivasnali/load-testing-made-easy-with-grafana-k6-ab1df5d95636"><strong>https://medium.com/@srinivasnali/load-testing&#8230;</strong></a></li>



<li><a href="https://systemsdigest.com/videos/intro-load-testing-k6-and-grafana-k6-data-source-plugin-and-prometheus-remote-write"><strong>https://systemsdigest.com/videos/intro-load-testing-k6&#8230;</strong></a></li>
</ul>
<p>L’article <a href="https://ouidou.fr/2025/12/09/introduction-a-k6/">Introduction à K6</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/Introduciton-a-K6.png" medium="image"></media:content>
				</item>
		<item>
		<title>Créer une API en Python avec FastAPI</title>
		<link>https://ouidou.fr/2025/12/03/creer-une-api-en-python-avec-fastapi/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Wed, 03 Dec 2025 16:16:37 +0000</pubDate>
				<category><![CDATA[Technique]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17867</guid>

					<description><![CDATA[<p>Écrit par Mohamed S. Introduction Un Framework est un ensemble de structures, de modules et de packages qui facilite le développement d&#8217;applications ou de systèmes. Les<span class="excerpt-hellip"> […]</span></p>
<p>L’article <a href="https://ouidou.fr/2025/12/03/creer-une-api-en-python-avec-fastapi/">Créer une API en Python avec FastAPI</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Écrit par Mohamed S.</em></p>



<h2 class="wp-block-heading" id="Introduction"><strong>Introduction</strong></h2>



<p>Un <strong>Framework</strong> est un ensemble de structures, de modules et de packages qui facilite le développement d&#8217;applications ou de systèmes.</p>



<p>Les trois principaux Framework Python les plus utilisés sont <strong>Django</strong>, <strong>Flask</strong> et <strong>FastAPI</strong>, chacun représente ses avantages et ses inconvénients.</p>



<p>Ça peut être utile de mettre en place une API par exemple dans le cas où on a une application web/mobile qui a besoin de <strong>consommer des datas</strong> de façon standardisé sans avoir à gérer les accès à une base de données.</p>



<p><strong>FastAPI</strong> est un Framework web de haute performance, open source. Lancé en 2018, il permet de créer des APIs avec Python à partir de la version 3.6.</p>



<p>Comme son nom l&#8217;indique, FastAPI est très <strong>rapide</strong> et <strong>facile</strong> à coder, il est très intuitif à l&#8217;utilisation, avec des fonctionnalités de complétion et de débogage, il est basé sur le standard ouvert <strong>OpenAI</strong> et <strong>JASON</strong> <strong>Schéma</strong>.</p>



<p>Le principal usage du Framework est la création de <strong>Endpoints</strong> <strong>APIs</strong>, principalement pour les applications de Data Science et e-commerce.</p>



<p>Toutefois, FastAPI ne se limite pas à créer des APIs, il est possible de l&#8217;utiliser pour n&#8217;importe quel usage d&#8217;un <strong>Framework web</strong>. Il a été désigné meilleur Framework open source en 2021.</p>



<h2 class="wp-block-heading" id="Prérequis"><strong>Prérequis</strong></h2>



<p>Pour utiliser FastAPI, vous devez avoir :</p>



<ul>
<li>Une <strong>base en programmation</strong> et une bonne <strong>compréhension des concepts</strong> de base de langage Python.</li>



<li>Une <strong>connaissance des principes</strong> des API REST et des requêtes HTTP.</li>
</ul>



<h2 class="wp-block-heading" id="Installation"><strong>Installation</strong></h2>



<p>Assurez-vous que vous avez bien installé <strong><a href="https://www.python.org/" target="_blank" rel="noreferrer noopener">Python</a></strong>.</p>



<p>Dans un seconde temps, un éditeur de texte/IDE est nécessaire, tel que <strong>VS Code</strong>.</p>



<p>Pour installer FastAPI, vous devez exécuter la commande suivante :</p>



<pre class="wp-block-code"><code class="">$ pip install fastapi</code></pre>



<p>Vous aurez également besoin d&#8217;un serveur web local pour tester vos API. Pour cela Python mis à disposition <strong>Uvicorn</strong>, qui est un serveur web ASGI (Asynchronous Server Gateway Interface).</p>



<p>Pour installer <strong>Uvicorn</strong>, vous devez exécuter cette commande :</p>



<pre class="wp-block-code"><code class="">$ pip install "uvicorn[standard]"</code></pre>



<h2 class="wp-block-heading" id="Développement"><strong>Développement</strong></h2>



<p>Dans cet article, nous allons créer une <strong>application CRUD</strong> avec FastAPI.</p>



<p>Une API REST fonctionne avec des requêtes HTTP, c&#8217;est ce protocole qui permet de connecter au serveur, il existe différents types de requêtes HTTP, et chaque requête dépend de l&#8217;action que l&#8217;on souhaite effectuer.</p>



<p>Les types de requêtes :</p>



<ul>
<li><strong>POST</strong> : servent à créer un nouvel élément dans la base de données</li>



<li><strong>GET</strong> : servent à récupérer des données (en mode lecture)</li>



<li><strong>PUT</strong> : servent à modifier un élément déjà existant dans la base de données</li>



<li><strong>DELETE</strong> : servent à supprimer des éléments dans la base de données</li>
</ul>



<h3 class="wp-block-heading" id="Création-de-l'application"><strong>Création de l&#8217;application</strong></h3>



<p>Nous allons commencer par la création de notre modèle utilisateur, et ce modèle aura <strong>5 attributs</strong> :</p>



<pre class="wp-block-code"><code class="">id : un identifiant unique
first_name : le prénom de l'utilisateur
last_name : le nom de famille de l'utilisateur
genre : le sexe de l'utilisateur
role : la liste des rôles de l'utilisateur</code></pre>



<p>Ce modèle sera créé dans un nouveau fichier nommé <em><strong>models.py</strong></em> :</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/d3781d18-1878-44a9-acbf-c13ebcd6f680/variants/355b3aad-7b25-4903-8dc3-5004697de921/src" alt="fichier model.py" style="width:278px;height:auto"/></figure></div>


<p>Dans le fichier <em><strong>main.py</strong></em> nous allons créer notre base de données de la manière suivante :</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/77061c31-630f-4ef9-b1b4-fdfd3f630939/variants/c4b2eb6d-b11b-4fed-8472-15f9898a421b/src" alt="fichier main.py" style="width:278px;height:auto"/></figure></div>


<p>Jusqu&#8217;ici, nous avons créé une base de données avec 4 utilisateurs, chacun avec des attributs requis.</p>



<p>La ligne du fichier <em><strong>main.py</strong></em> :</p>



<pre class="wp-block-code"><code class="">app = FastAPI()</code></pre>



<p>permet de créer une instance de FastAPI.</p>



<h3 class="wp-block-heading" id="Lecture-des-éléments-de-la-base-de-données"><strong>Lecture des éléments de la base de données</strong></h3>



<p>Pour créer une route qui récupère les utilisateurs, nous allons créer un décorateur dans le fichier <em><strong>main.py</strong></em> :</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/e6feb8e8-dbe4-48f2-b851-f8a9026494c3/variants/8ae2598c-df6e-41ca-a017-49aa57ce5dbf/src" alt="fichier main.py"/></figure></div>


<p>Le décorateur</p>



<pre class="wp-block-code"><code class="">@app.get("api/get_users")</code></pre>



<p>permet de spécifier le chemin URL et l&#8217;action HTTP de notre API, et cette fonction fait appel à la méthode <strong>GET</strong>.</p>



<p>La fonction &#8216;<strong>get_users()</strong>&#8216; sera exécutée chaque fois qu&#8217;un utilisateur visitera le chemin URL spécifié par le décorateur.</p>



<p>Pour lancer le serveur d&#8217;API et tester la fonction, nous allons exécuter la commande suivante dans le terminal :</p>



<pre class="wp-block-code"><code class="">$ uvicorn main:app --reload</code></pre>



<p>Uvicorn est le serveur local, il prend en paramètres le nom du fichier : le nom de l&#8217;instance FastAPI.</p>



<p>Dans cet exemple, le nom du fichier est : <em><strong>main</strong></em>, et le nom de l&#8217;instance est <em><strong>app</strong></em>.</p>



<p>L&#8217;option &#8216;<strong>&#8211;reload</strong>&#8216; indique au serveur de se recharger automatiquement lorsque une modification est apportée.</p>



<p>Quand nous exécutons la commande, si tout se passe bien nous allons avoir quelque chose comme ceci dans le terminal :</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/04619e6b-a589-4343-8032-d42df256c4ab/variants/e05c92f6-9257-4af2-9877-4a4ac0f129f9/src" alt="terminal lors du lancement de fastapi" style="width:546px;height:auto"/></figure></div>


<p>Nous allons retenir l&#8217;URL du localhost et le port 8000, il nous servira d&#8217;afficher les résultats de l&#8217;API.</p>



<p>FastAPI en plus de mettre en place rapidement et facilement une API, il génère automatiquement une documentation de l&#8217;API, cette documentation est basé sur l&#8217;interface utilisateur Swagger, pour y accéder on rajoute juste &#8216;/docs&#8217; à notre URL.</p>



<pre class="wp-block-code"><code class="">127.0.0.1:8000/docs</code></pre>



<p>Nous allons exécuter l&#8217;endpoint qui représente la récupération des utilisateurs, nous allons avoir ce résultat qui regroupe les utilisateurs.</p>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/1ab90675-ced5-47a2-97db-26d999dc2674/variants/d08a3c6a-986a-4b77-be7d-dd5a26e5bd48/src" alt="endpoint get_users()" style="width:512px;height:auto"/></figure>



<h3 class="wp-block-heading" id="Création-de-nouveaux-éléments-dans-la-base-de-données"><strong>Création de nouveaux éléments dans la base de données</strong></h3>



<p>Nous allons créer un endpoint dans le fichier <em><strong>main.py</strong></em>, qui permettra de créer de nouveaux éléments et de les enregistrer en base de données.</p>


<div class="wp-block-image">
<figure class="aligncenter"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/fdf04977-1dcd-40c9-b0d8-dd2d56d0189e/variants/56468417-da5a-4d49-996a-41d0643421a2/src" alt="fonction create_users"/></figure></div>


<p>Dans cette fonction nous avons utilisé l&#8217;action HTTP <strong>POST</strong>, qui permet la création en base de données.</p>



<p>L&#8217;interface du Swagger après avoir ajouté le nouvel élément ressemblera à l&#8217;image suivante :</p>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/ff8a30fe-51a8-40ff-8306-dfa2369df31f/variants/86f2a2ed-afe4-4c97-8cb5-f68e3bc4f25d/src" alt="endpoint create_users()" style="width:504px;height:auto"/></figure>



<p><strong>L&#8217;utilisateur toto titi a été bien ajouté en base de données.</strong></p>



<h3 class="wp-block-heading" id="Suppression-d'un-élément-de-la-base-de-données"><strong>Suppression d&#8217;un élément de la base de données</strong></h3>



<p>Etant donné que nous créons une application CRUD, l&#8217;application doit avoir la possibilité de supprimer une ressource existante.</p>



<p>Pour cela, nous allons créer un endpoint toujours dans le fichier <em><strong>main.py</strong></em>, qui permettra la suppression :</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/33618ea6-899b-45f2-8aa6-bd3123dd8f50/variants/04e31b8d-4082-4c1c-898a-097015854878/src" alt="fonction delete_user()" style="width:421px;height:auto"/></figure></div>


<p>Dans le décorateur, nous avons utilisé l&#8217;action HTTP <strong>DELETE</strong>, qui permet la suppression en base de données.</p>



<p>La fonction nécessitera un <strong>id</strong> à supprimer, si l&#8217;<strong>id</strong> de l&#8217;utilisateur est introuvable un message d&#8217;erreur sera renvoyé, c&#8217;est le cas dans l&#8217;image suivante, où nous allons renseigner un <strong>id</strong> qui n&#8217;existe pas dans la base de données :</p>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/2b242418-1d5f-43f3-8f5c-4bf5bec5428b/variants/75461c4f-44f7-4ec3-9225-25c0712e2c6b/src" alt="endpoint suppression" style="width:500px;height:auto"/></figure>



<p>Et quand nous allons renseigner un bon <strong>id</strong> qui existe dans la base de données, l&#8217;utilisateur qui a cet <strong>id</strong> ne sera plus dans la base de données, il sera supprimé.</p>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/ad74de9e-e957-4a6e-bd60-2c3b521512a6/variants/fa5f8592-76f9-4802-80e9-6ead5f50c8e7/src" alt="endpoint suppression 2 " style="width:502px;height:auto"/></figure>



<h3 class="wp-block-heading" id="Mettre-à-jour-un-élément-de-la-base-de-données"><strong>Mettre à jour un élément de la base de données</strong></h3>



<p>Dans cette partie, nous allons créer un endpoint qui permettra de mettre à jour un élément qui existe déjà en base de données, en utilisant l&#8217;action HTTP <strong>PUT</strong>.</p>



<p>Toujours dans le fichier <em><strong>main.py</strong></em>, on ajoute la fonction suivante :</p>


<div class="wp-block-image">
<figure class="aligncenter is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/12f8e1bb-545f-4e39-b5c8-ade2f7f506e5/variants/0b3130aa-1604-42ed-9987-49d63256c2e9/src" alt="fonction update_user()" style="width:250px;height:auto"/></figure></div>


<p>Dans les paramètres de la fonction qui met à jour les éléments, l&#8217;<strong>id</strong> est à renseigner obligatoirement, par contre les autres champs sont facultatifs, d&#8217;où leurs déclarations : &#8216;<strong>Optional[str] = None</strong>&#8216; qui veut dire que c&#8217;est optionnel et que la valeur par défaut est nulle.</p>



<p>Dans le cas ou l&#8217;<strong>id</strong> renseigné est introuvable en base de données, l&#8217;API générera une erreur.</p>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://narcisse.ouidou.fr/attachments/551c712a-e805-41b1-a654-36cd57a41d82/variants/29a60364-3194-4d29-bf48-bedd19624075/src" alt="endpoint update" style="width:469px;height:auto"/></figure>



<h2 class="wp-block-heading" id="Conclusion"><strong>Conclusion</strong></h2>



<p>Dans cet article, nous avons découvert le cadre <strong>FastAPI</strong> pour <strong>python</strong> et constaté à quelle vitesse nous pouvons mettre en place une application alimentée par <strong>FastAPI</strong>.</p>



<p>Nous avons appris à créer des <strong>endpoints</strong> (points de terminaison) d&#8217;<strong>API CRUD</strong>, c&#8217;est-à-dire créer, lire, mettre à jour et supprimer (Create, Read, Update, Delete) des éléments de base de données.</p>



<p>En conclusion, FastAPI est un framework Python moderne, rapide et efficace pour la création d&#8217;API web. Grâce à son utilisation des annotations de type Python, il permet de garantir la validation automatique des données et de générer une documentation interactive, facilitant ainsi le développement et la maintenance des API.</p>



<p>FastAPI représente un excellent choix pour les développeurs cherchant à construire des API robustes, performantes et facile à maintenir.</p>



<h2 class="wp-block-heading" id="Références"><strong>Références</strong></h2>



<ul>
<li><a href="https://fastapi.tiangolo.com/">Site Officiel de FastAPI</a> (en)</li>
</ul>
<p>L’article <a href="https://ouidou.fr/2025/12/03/creer-une-api-en-python-avec-fastapi/">Créer une API en Python avec FastAPI</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/Creer-une-API-en-Python-avec-FastAPI.png" medium="image"></media:content>
				</item>
		<item>
		<title>Optimiser vos tests avec Cucumber</title>
		<link>https://ouidou.fr/2025/11/17/optimiser-vos-tests-avec-cucumber/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Mon, 17 Nov 2025 10:11:16 +0000</pubDate>
				<category><![CDATA[Technique]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17852</guid>

					<description><![CDATA[<p>Écrit par Faiez T. Introduction : Qu&#8217;est-ce que Cucumber ? Cucumber est un outil puissant utilisé pour automatiser les tests logiciels, qui repose sur la méthodologie<span class="excerpt-hellip"> […]</span></p>
<p>L’article <a href="https://ouidou.fr/2025/11/17/optimiser-vos-tests-avec-cucumber/">Optimiser vos tests avec Cucumber</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Écrit par Faiez T.</em></p>



<h2 class="wp-block-heading" id="Introduction-:"><strong>Introduction :</strong></h2>



<p><strong>Qu&#8217;est-ce que Cucumber ?</strong></p>



<p><a href="https://cucumber.io/" target="_blank" rel="noreferrer noopener">Cucumber</a> est un <strong>outil puissant</strong> utilisé pour automatiser les tests logiciels, qui repose sur la méthodologie du <strong>Behavior Driven Development (BDD)</strong>. Il permet de décrire le <strong>comportement attendu</strong> d&#8217;une application sous forme de scénarios simples et compréhensibles par tous, facilitant ainsi la collaboration entre les différentes équipes.</p>



<p><strong>Qu&#8217;est-ce que BDD ?</strong></p>



<p>Le <strong>Behavior Driven Development (BDD)</strong> est une approche de développement logiciel qui se concentre sur la description du <strong>comportement attendu</strong> d&#8217;une application à travers des scénarios clairs et accessibles. Ces scénarios peuvent être compris par toutes les parties prenantes, qu&#8217;il s&#8217;agisse de développeurs, de testeurs, d&#8217;analystes métiers ou d&#8217;utilisateurs finaux, facilitant ainsi la communication et la collaboration tout au long du processus de développement.</p>



<h2 class="wp-block-heading" id="Pourquoi-utiliser-Cucumber-?"><strong>Pourquoi utiliser Cucumber ?</strong></h2>



<h4 class="wp-block-heading" id="1.-Langage-naturel-avec-Gherkin"><strong>1. Langage naturel avec Gherkin</strong></h4>



<p>L’un des points forts de <strong>Cucumber</strong> est qu’il utilise un <strong>langage naturel</strong> appelé <strong>Gherkin</strong> pour définir les tests. <strong>Gherkin</strong> est une <strong>syntaxe simple</strong> qui permet d’écrire des <strong>scénarios</strong> en anglais ou dans d’autres langues, en suivant une <strong>structure intuitive</strong>.</p>



<ul>
<li><strong>Exemple d’un scénario Gherkin :</strong></li>
</ul>



<pre class="wp-block-code"><code class="">Feature: Connexion utilisateur  
 Scenario: Connexion réussie avec des identifiants valides  
   Given un utilisateur avec un identifiant valide "faiez.tmar"  
   When il tente de se connecter avec son mot de passe  
   Then il est redirigé vers la page d'accueil</code></pre>



<h4 class="wp-block-heading" id="2.-Tests-lisibles-et-compréhensibles"><strong>2. Tests lisibles et compréhensibles</strong></h4>



<p>Les <strong>scénarios</strong> écrits avec <strong>Cucumber</strong> sont compréhensibles par toutes les <strong>parties prenantes</strong> du projet, qu’elles soient techniques ou non. Cela permet :</p>



<ul>
<li>Une collaboration accrue entre les développeurs, les testeurs et les responsables métier.</li>



<li>Une meilleure compréhension des fonctionnalités attendues de l’application.</li>
</ul>



<h4 class="wp-block-heading" id="3.-Automatisation-des-Tests"><strong>3. Automatisation des Tests</strong></h4>



<p>Une fois les <strong>scénarios</strong> définis, <strong>Cucumber</strong> permet de les <strong>automatiser</strong>, ce qui améliore la <strong>qualité du logiciel</strong> en garantissant :</p>



<ul>
<li>Une exécution rapide et fiable des tests.</li>



<li>La détection rapide des régressions lors des phases de développement.</li>
</ul>



<h2 class="wp-block-heading" id="Les-concepts-clés-de-Cucumber"><strong>Les concepts clés de Cucumber</strong></h2>



<h4 class="wp-block-heading" id="1.-Feature">1. Feature</h4>



<p>Une <strong>Feature</strong> est un fichier <strong>.feature</strong> qui décrit une <strong>fonctionnalité spécifique</strong> de l’application. Ce fichier regroupe plusieurs <strong>scénarios</strong> liés à cette fonctionnalité.</p>



<ul>
<li><strong>Exemple :</strong></li>
</ul>



<pre class="wp-block-code"><code class="">Feature: Gestion des utilisateurs
Afin de pouvoir accéder à l'application
En tant qu'utilisateur enregistré
Je veux pouvoir me connecter avec mes identifiants</code></pre>



<h4 class="wp-block-heading" id="3.-Steps">2. Scénario</h4>



<p>Un <strong>Scenario</strong> décrit une <strong>situation</strong> ou un <strong>cas d’utilisation spécifique</strong>, en détaillant le <strong>comportement attendu</strong> de l&#8217;application dans ce cas.</p>



<ul>
<li><strong>Exemple :</strong></li>
</ul>



<pre class="wp-block-code"><code class="">Scenario: Connexion avec des identifiants valides
Given un utilisateur avec l'identifiant "faiez.tmar"
When il saisit son mot de passe correct
Then il est redirigé vers la page d'accueil</code></pre>



<h4 class="wp-block-heading" id="3.-Steps">3. Steps</h4>



<p>Les <strong>Steps</strong> ou <strong>étapes</strong> définissent les <strong>actions à réaliser</strong> et les <strong>résultats attendus</strong> dans le <strong>scénario</strong>. Elles se décomposent en <strong>trois catégories principales</strong> :</p>



<ul>
<li><strong>Given</strong> : Décrit le contexte initial.</li>



<li><strong>When</strong> : Décrit l’action ou l’événement déclencheur.</li>



<li><strong>Then</strong> : Définit le résultat attendu.</li>
</ul>



<p><strong>Syntaxe des Steps :</strong></p>



<pre class="wp-block-code"><code class="">Given un utilisateur est sur la page de connexion  
When il saisit ses identifiants corrects  
Then il est redirigé vers la page d'accueil</code></pre>



<h4 class="wp-block-heading" id="4.-Step-Definitions"><strong>4. Step Definitions</strong></h4>



<p>Les <strong>Step Definitions</strong> sont des <strong>méthodes</strong> implémentées en <strong>Java</strong> (ou dans un autre <strong>langage compatible</strong>) qui définissent le <strong>comportement à exécuter</strong> pour chaque <strong>étape du scénario</strong>.</p>



<ul>
<li><strong>Exemple en Java :</strong></li>
</ul>



<pre class="wp-block-code"><code class="">@Given("un utilisateur est sur la page de connexion")
public void userOnLoginPage() {
// Code pour naviguer vers la page de connexion
}
@When("il saisit ses identifiants corrects")
public void provideCorrectCredentials() {
// Code pour saisir les identifiants
}
@Then("il est redirigé vers la page d'accueil")
public void redirectedToHomePage() {
// Code pour vérifier la redirection
}</code></pre>



<h2 class="wp-block-heading" id="Exemple-d’Implémentation-de-Cucumber-avec-Spring-Boot"><strong>Exemple d’Implémentation de Cucumber avec Spring Boot</strong></h2>



<h4 class="wp-block-heading" id="1.-Configuration-du-Projet">1. Configuration du Projet</h4>



<p>Pour <strong>intégrer Cucumber</strong> dans un projet <strong>Spring Boot</strong>, vous devez ajouter les <strong>dépendances nécessaires</strong> dans le fichier <strong>pom.xml</strong> :</p>



<pre class="wp-block-code"><code class="">&lt;dependencies&gt;
    &lt;!-- Dépendance Cucumber --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.cucumber&lt;/groupId&gt;
        &lt;artifactId&gt;cucumber-java&lt;/artifactId&gt;
        &lt;version&gt;7.0.0&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;io.cucumber&lt;/groupId&gt;
        &lt;artifactId&gt;cucumber-spring&lt;/artifactId&gt;
        &lt;version&gt;7.0.0&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!-- Dépendance Spring Boot Test --&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</code></pre>



<p><strong>Créez une classe CucumberTest.java :</strong></p>



<pre class="wp-block-code"><code class="">import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(features = "classpath:features", plugin = {"pretty"})
public class CucumberTest {
}</code></pre>



<h4 class="wp-block-heading" id="2.-Exemple-de-scénario-Gherkin-:"><strong>2. Exemple de scénario Gherkin :</strong></h4>



<p>Dans un fichier <strong>article.feature</strong>, nous allons définir des <strong>scénarios</strong> en <strong>Gherkin</strong> pour tester la <strong>gestion des articles</strong>. Chaque scénario correspond à une <strong>action CRUD</strong> sur un <strong>article</strong>.</p>



<pre class="wp-block-code"><code class="">Feature: Gestion des articles
  Afin de gérer les informations de mes articles
  En tant qu'administrateur
  Je veux pouvoir créer, lire, mettre à jour et supprimer des articles.
Scenario: Création d'un nouvel article
  Given un article avec le titre "Cucumber et Spring Boot"
  When l'article est créé
  Then l'article doit être enregistré dans la base de données
Scenario: Lecture d'un article
  Given un article avec le titre "Cucumber et Spring Boot"
  When je consulte l'article
  Then le titre de l'article doit être "Cucumber et Spring Boot"
Scenario: Mise à jour d'un article
  Given un article avec le titre "Cucumber et Spring Boot"
  When je mets à jour l'article avec le titre "Cucumber avancé"
  Then le titre de l'article doit être "Cucumber avancé"
Scenario: Suppression d'un article
  Given un article avec le titre "Cucumber et Spring Boot"
  When je supprime l'article
  Then l'article ne doit plus exister dans la base de données</code></pre>



<h4 class="wp-block-heading" id="3.-Implémentation-des-steps-en-Java"><strong>3. Implémentation des steps en Java</strong></h4>



<p>Dans la classe <strong>ArticleStepDefinitions.java</strong>, nous allons <strong>implémenter les étapes</strong> des <strong>scénarios</strong>.</p>



<pre class="wp-block-code"><code class="">import io.cucumber.java.en.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.web.client.TestRestTemplate;
import static org.junit.Assert.*;
@SpringBootTest
public class ArticleStepDefinitions {
    @Autowired
    private ArticleRepository articleRepository;
    private Article article;
    @Given("un article avec le titre {string}")
    public void givenAnArticleWithTitle(String titre) {
        article = new Article();
        article.setTitre(titre);
    }
    @When("l'article est créé")
    public void whenArticleIsCreated() {
        articleRepository.save(article); 
    }
    @Then("l'article doit être enregistré dans la base de données")
    public void thenArticleShouldBeSavedInDatabase() {
        Article savedArticle = articleRepository.findByTitre(article.getTitre());
        assertNotNull(savedArticle); 
        assertEquals(article.getTitre(), savedArticle.getTitre()); 
    }
    @When("je consulte l'article")
    public void whenGetArticle() {
        article = articleRepository.findByTitre(article.getTitre());
    }
    @Then("le titre de l'article doit être {string}")
    public void thenTitleOfArticleShouldBe(String titre) {
        assertEquals(titre, article.getTitre()); 
    }
    @When("je mets à jour l'article avec le titre {string}")
    public void whenIUpdateTheArticleWithTitle(String nouveauTitre) {
        article.setTitre(nouveauTitre);
        articleRepository.save(article); 
    }
    @Then("le titre de l'article doit être {string}")
    public void thenTitleOfArticleShouldBeUpdated(String titre) {
        article = articleRepository.findByTitre(titre);
        assertNotNull(article); 
        assertEquals(titre, article.getTitre()); 
    }
    @When("je supprime l'article")
    public void whenIDeleteTheArticle() {
        articleRepository.delete(article); 
    }
    @Then("l'article ne doit plus exister dans la base de données")
    public void thenArticleShouldNotExistInDatabase() {
        Article deletedArticle = articleRepository.findByTitre(article.getTitre());
        assertNull(deletedArticle); 
    }
}</code></pre>



<h4 class="wp-block-heading" id="4.-Exécution-des-Tests"><strong>4. Exécution des Tests</strong></h4>



<p>Vous pouvez maintenant <strong>exécuter vos tests</strong> avec <strong>Maven</strong> en utilisant la <strong>commande suivante</strong> :</p>



<pre class="wp-block-code"><code class=""><code>mvn test</code></code></pre>



<p>Les <strong>tests Cucumber</strong> vont s&#8217;<strong>exécuter</strong>, et vous pourrez vérifier les <strong>résultats</strong> pour vous assurer que les <strong>opérations CRUD</strong> sur les <strong>articles</strong> fonctionnent correctement.</p>



<h2 class="wp-block-heading" id="Conclusion"><strong>Conclusion</strong></h2>



<p>En <strong>conclusion</strong>, <strong>Cucumber</strong>, en tant que <strong>framework</strong> basé sur la méthodologie <strong>BDD</strong>, facilite l’<strong>automatisation des tests</strong> et améliore la <strong>collaboration entre les équipes</strong> grâce à son utilisation de <strong>scénarios écrits dans un langage naturel</strong>. Son approche permet une <strong>compréhension claire</strong> des <strong>comportements attendus</strong> de l’application, tant pour les <strong>techniciens</strong> que pour les <strong>non-techniciens</strong>.</p>



<p>Grâce à l&#8217;<strong>intégration</strong> avec des outils comme <strong>Spring Boot</strong>, <strong>Cucumber</strong> permet d’<strong>implémenter</strong> et d’<strong>exécuter efficacement des tests automatisés</strong>, garantissant ainsi une <strong>meilleure qualité logicielle</strong> et une <strong>détection rapide des régressions</strong>.</p>
<p>L’article <a href="https://ouidou.fr/2025/11/17/optimiser-vos-tests-avec-cucumber/">Optimiser vos tests avec Cucumber</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/Optimiser-vos-tests-avec-Cucumber.png" medium="image"></media:content>
				</item>
		<item>
		<title>Comment préparer votre Jira Cloud dès maintenant ? </title>
		<link>https://ouidou.fr/2025/11/14/comment-preparer-votre-jira-cloud-des-maintenant/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Fri, 14 Nov 2025 15:32:01 +0000</pubDate>
				<category><![CDATA[Tous les articles]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17846</guid>

					<description><![CDATA[<p>L’article <a href="https://ouidou.fr/2025/11/14/comment-preparer-votre-jira-cloud-des-maintenant/">Comment préparer votre Jira Cloud dès maintenant ? </a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p></p>
<p>L’article <a href="https://ouidou.fr/2025/11/14/comment-preparer-votre-jira-cloud-des-maintenant/">Comment préparer votre Jira Cloud dès maintenant ? </a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/formation-jira-1.png" medium="image"></media:content>
				</item>
		<item>
		<title>Replay webinaire IA</title>
		<link>https://ouidou.fr/2025/11/05/replay-webinaire-ia/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Wed, 05 Nov 2025 17:11:41 +0000</pubDate>
				<category><![CDATA[Tous les articles]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17818</guid>

					<description><![CDATA[<p>L’article <a href="https://ouidou.fr/2025/11/05/replay-webinaire-ia/">Replay webinaire IA</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p></p>



<p></p>



<p></p>



<p></p>
<p>L’article <a href="https://ouidou.fr/2025/11/05/replay-webinaire-ia/">Replay webinaire IA</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/replay.png" medium="image"></media:content>
				</item>
		<item>
		<title>Atlassian arrête le Data Center : pourquoi votre migration doit commencer maintenant</title>
		<link>https://ouidou.fr/2025/11/05/atlassian-accelere-son-virage-cloud-la-fin-du-data-center-dici-2029/</link>
		
		<dc:creator><![CDATA[Emmie Pommeret]]></dc:creator>
		<pubDate>Wed, 05 Nov 2025 14:23:14 +0000</pubDate>
				<category><![CDATA[Tous les articles]]></category>
		<guid isPermaLink="false">https://ouidou.fr/?p=17809</guid>

					<description><![CDATA[<p>L’article <a href="https://ouidou.fr/2025/11/05/atlassian-accelere-son-virage-cloud-la-fin-du-data-center-dici-2029/">Atlassian arrête le Data Center : pourquoi votre migration doit commencer maintenant</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>L’article <a href="https://ouidou.fr/2025/11/05/atlassian-accelere-son-virage-cloud-la-fin-du-data-center-dici-2029/">Atlassian arrête le Data Center : pourquoi votre migration doit commencer maintenant</a> est apparu en premier sur <a href="https://ouidou.fr">Ouidou</a>.</p>
]]></content:encoded>
					
		
		
		<media:content url="https://ouidou.fr/wp-content/uploads/2025/11/formation-jira.png" medium="image"></media:content>
				</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Mise en cache de page à l’aide de Disk: Enhanced 
Chargement différé (feed)
Mibnifié utilisant Disk

Served from: ouidou.fr @ 2026-04-10 18:00:29 by W3 Total Cache
-->