<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jérémy Chauvin</title>
    <description>The latest articles on Forem by Jérémy Chauvin (@singebob).</description>
    <link>https://forem.com/singebob</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F294107%2Fc263cfe2-08da-47b2-96d0-09861b5b6e06.png</url>
      <title>Forem: Jérémy Chauvin</title>
      <link>https://forem.com/singebob</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/singebob"/>
    <language>en</language>
    <item>
      <title>Tester son interface efficacement : des patterns pour des tests d’UI robustes</title>
      <dc:creator>Jérémy Chauvin</dc:creator>
      <pubDate>Thu, 13 Mar 2025 16:53:40 +0000</pubDate>
      <link>https://forem.com/singebob/tester-son-interface-efficacement-des-patterns-pour-des-tests-dui-robustes-2402</link>
      <guid>https://forem.com/singebob/tester-son-interface-efficacement-des-patterns-pour-des-tests-dui-robustes-2402</guid>
      <description>&lt;p&gt;&lt;em&gt;Article co-écrit avec &lt;a class="mentioned-user" href="https://dev.to/manon_carbonnel"&gt;@manon_carbonnel&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tester l’interface (UI) est un défi&lt;/strong&gt; : les tests doivent être &lt;strong&gt;fiables, lisibles et maintenables&lt;/strong&gt; dans le temps, tout en restant suffisamment souples pour suivre les évolutions du produit. Malheureusement, l’UI est amenée à évoluer régulièrement, et ces tests sont souvent &lt;strong&gt;fragiles&lt;/strong&gt; et difficiles à faire évoluer si leur conception n’est pas rigoureuse. Nous voulons également des tests cohérents avec des parcours réalistes.&lt;/p&gt;

&lt;p&gt;Cet article explore des &lt;strong&gt;patterns éprouvés&lt;/strong&gt; pour améliorer la qualité des tests d’UI. Ces tests sont aussi l’occasion de se mettre à la place des utilisateur·ices de nos applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  User Facing Attributes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ce pattern propose d’utiliser des sélecteurs basés sur des attributs ou propriétés visibles par l’utilisateur·ice&lt;/strong&gt; (rôles accessibles, labels, textes, etc.) pour identifier et interagir avec les éléments de l'interface. Cela permet de rendre les tests plus intuitifs et orientés vers l'expérience réelle de l'utilisateur·ice, en étant moins dépendants de CSS, tout en favorisant des pratiques de développement prenant en compte l’accessibilité.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 C’est aujourd’hui l’approche préconisée par la majorité des outils d’automatisation de navigateur comme &lt;a href="https://playwright.dev/docs/locators" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;.&lt;br&gt;
Si vous utilisez &lt;a href="https://docs.cypress.io/app/core-concepts/best-practices#Selecting-Elements" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, bien que la documentation évoque Testing Library, elle préconise l’utilisation de &lt;code&gt;data-test-id&lt;/code&gt;.&lt;br&gt;
Mais nous ne sommes pas d’accord avec cette recommandation :D.&lt;br&gt;
Dans la même idée, utiliser des locators basés sur le CSS ou le XPath ne sont pas recommandés, car le DOM peut souvent changer, ce qui conduit à des tests non résilients.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Exemples de code pour accéder aux éléments du DOM d’une page web
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Exemple d’utilisation avec Testing Library&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/homepage.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomePage - User Facing Attributes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;devrait afficher un titre contenant "Playwright" et un lien "Get started" visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://playwright.dev/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Sélection basée sur des attributs exposés à l'utilisateur·ice&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/Playwright/i&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getStartedLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/Get started/i&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getStartedLink&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exemple d’utilisation avec Playwright&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/homepage.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Locator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PlaywrightHomePage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../pages/PlaywrightHomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test du site Playwright via User Facing Attributes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vérifier que le titre principal contient "Playwright" et que le lien "Get started" est visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://playwright.dev/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Sélection basée sur des attributs exposés à l'utilisateur·ice&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getStartedLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/Get started/i&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toContainText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getStartedLink&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Robustesse des tests :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les tests sont moins susceptibles de casser lors de modifications techniques (comme des changements d'attributs CSS ou ordre des balises dans le DOM).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Alignement avec l'UX :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les sélecteurs utilisés correspondent à ce que voit et utilise réellement l'utilisateur·ice, améliorant ainsi la pertinence des tests.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Promotion des bonnes pratiques d'accessibilité :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Toutes les interfaces ne sont pas toujours dotées d'attributs ou de rôles pertinents, ce pattern incite donc développer des interfaces accessibles et bien structurées.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lisibilité et clarté :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les tests sont plus explicites, car ils décrivent les éléments de l'interface tels qu'une personne les perçoit.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dépendance au contenu textuel :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les tests peuvent devenir fragiles si les libellés ou textes changent fréquemment, même si la fonctionnalité reste correcte.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Moins de contrôle sur des sélecteurs complexes :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pour certaines interactions spécifiques ou des éléments très dynamiques (comme un élément dans un tableau ou une liste de données), il peut être nécessaire d'utiliser des sélecteurs techniques en complément ou remplacement.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Page Object Model
&lt;/h2&gt;

&lt;p&gt;Son objectif principal est de &lt;strong&gt;séparer la logique de test&lt;/strong&gt; (les scénarios et assertions) de la &lt;strong&gt;logique d'interaction avec l'interface&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemples de code avec Playwright
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// pages/PlaywrightHomePage.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Locator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlaywrightHomePage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Locator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// On cible ici le titre principal de la page (par exemple, l'élément h1)&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Méthode pour naviguer vers la page d'accueil&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://playwright.dev/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Méthode pour récupérer le texte du titre&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getHeaderText&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exemple d’utilisation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/homepage.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PlaywrightHomePage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../pages/PlaywrightHomePage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test du site Playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vérifier que le titre principal contient "Playwright"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Instanciation de la page via notre Page Object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;homePage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PlaywrightHomePage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;homePage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;homePage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHeaderText&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headerText&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Playwright&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Séparation des responsabilités :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Le POM sépare la logique de test de l’implémentation de l’interface. Cela permet aux tests de se concentrer sur la validation du comportement métier.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modularité et évolutivité :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Chaque page ou composant est représenté par une classe spécifique, facilitant ainsi l’organisation et l’évolution de la suite de tests.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Maintenance facilitée :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Lorsqu'une modification est apportée à l'interface (changement de sélecteur, structure HTML modifiée…), il suffit de mettre à jour la classe correspondante, sans toucher aux tests eux-mêmes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Réutilisabilité :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les méthodes et sélecteurs encapsulés dans un objet peuvent être réutilisés dans plusieurs tests, réduisant ainsi la duplication de code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lisibilité et clarté des tests :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En déléguant les interactions à des objets dédiés, les scénarios de tests restent concis et lisibles. On peut ainsi comprendre rapidement l’intention du test sans se perdre dans les détails d’implémentation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Risque de duplication si mal structuré :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sans une bonne conception, on peut se retrouver avec des classes qui dupliquent des comportements similaires pour des composants récurrents, au lieu d’extraire des composants communs. Dans le cas où on trouverait plusieurs fois le même composant sur une page, il suffit d’y accéder en précisant le bloc parent dans le sélecteur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Couplage si contenu dans une librairie à part :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Conserver le POM dans un repository / une librairie à part entraîne des problèmes d’alignement des sélecteurs lors de mise à jour des pages.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Screenplay Pattern : alternative au POM
&lt;/h2&gt;

&lt;p&gt;Le Screenplay Pattern est une approche pour structurer les tests d'UI en mettant l'accent sur les actions et les intentions des utilisateur·ices, plutôt que sur la structure technique des pages. Particulièrement utile pour des &lt;strong&gt;suites de tests larges et évolutives&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Au lieu de manipuler directement les éléments de l’UI via un Page Object Model (POM), il introduit des "acteur·ices" qui interagissent avec l'interface en utilisant des "tâches" et des "questions".&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemples de code avec Playwright
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Définition des intéractions&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EnterText&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Click&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Définition des tâches&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Login&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;EnterText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;EnterText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Click&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#login-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Définition des questions&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IsLoggedIn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;answeredBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#welcome-message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exemple d’utilisation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/login.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IsLoggedIn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./login-screenplay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice peut se connecter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// L'utilisateur·ice joue le rôle d'un·e acteur·ice réalisant une tâche&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;securepassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Vérification de la connexion&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;IsLoggedIn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;answeredBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loggedIn&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modularité :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les interactions et tâches sont réutilisables.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lisibilité :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Le code ressemble plus à un scénario utilisateur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Maintenance facilitée :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modifier l’implémentation d’une interaction ne casse pas toute la suite de tests.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scalabilité :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Facilite l’ajout de nouvelles tâches sans dupliquer du code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Complexité initiale :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Plus de fichiers et d'abstraction qu'un simple Page Object Model qui est parfois suffisant pour de petits tests simple.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Courbe d’apprentissage :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nécessite de bien comprendre la séparation entre acteurs, tâches et interactions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Outils et bibliothèques populaires pour des test d’UI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing Library
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://testing-library.com/" rel="noopener noreferrer"&gt;Testing library&lt;/a&gt; est une solution légère pour tester des UI en interagissant avec le DOM de manière similaire à une personne. Son approche repose sur la recherche et l'interaction avec les éléments via leurs &lt;strong&gt;user-facing attributes.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Playwright
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; est un outil d'automatisation de navigateurs conçu pour offrir une &lt;strong&gt;developer experience&lt;/strong&gt; confortable et puissante. Il prend en charge plusieurs langages (TypeScript, JavaScript, Python, C#, Java) et permet de tester des applications sur différents navigateurs (Chromium, Firefox, WebKit) et plateformes (Windows, Linux, macOS). Son API facilite la manipulation du DOM et intègre nativement les &lt;strong&gt;user-facing attributes&lt;/strong&gt; pour interagir avec les éléments. Playwright se distingue également par ses fonctionnalités avancées comme le &lt;strong&gt;record &amp;amp; replay&lt;/strong&gt;, les &lt;strong&gt;tests en parallèle&lt;/strong&gt;, et le &lt;strong&gt;debugging interactif&lt;/strong&gt; avec des outils visuels comme le trace viewer.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>french</category>
      <category>testing</category>
    </item>
    <item>
      <title>Mieux tester en optimisant la génération de données de test : Panorama des patterns</title>
      <dc:creator>Jérémy Chauvin</dc:creator>
      <pubDate>Thu, 13 Mar 2025 16:44:47 +0000</pubDate>
      <link>https://forem.com/singebob/mieux-tester-en-optimisant-la-generation-de-donnees-de-test-panorama-des-patterns-1cde</link>
      <guid>https://forem.com/singebob/mieux-tester-en-optimisant-la-generation-de-donnees-de-test-panorama-des-patterns-1cde</guid>
      <description>&lt;p&gt;&lt;em&gt;Article co-écrit avec &lt;a class="mentioned-user" href="https://dev.to/manon_carbonnel"&gt;@manon_carbonnel&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Écrire des tests automatisés efficaces ne se résume pas à vérifier que notre code fonctionne : il faut aussi que les tests soient lisibles, maintenables et rapides à écrire. Pour cela, la manière dont on génère les données de test joue un rôle clé.&lt;/p&gt;

&lt;p&gt;Les patterns que nous vous présentons permettent d’éviter de la duplication, de rendre les tests plus clairs et de mieux maîtriser la complexité des objets manipulés.&lt;/p&gt;

&lt;p&gt;Dans cet article, nous allons explorer différentes approches, leurs avantages et leurs limites, et cibler la stratégie à adopter selon le contexte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pourquoi faire varier ses jeux de données ?
&lt;/h2&gt;

&lt;p&gt;Pour certains tests, il est primordial de rendre visible la variation des données afin d'expliciter la règle métier sous-jacente.&lt;/p&gt;

&lt;p&gt;Par exemple, pour déterminer si un utilisateur est majeur, vous devez modifier son âge dans vos tests et créer deux fixtures. Cependant, ce qui vous intéresse réellement, c'est de voir la règle métier apparaître clairement dans vos tests. Il est crucial de bien mettre en évidence l'âge que vous attribuez.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Ces patterns ne sont pas spécifiques au langage TypeScript que nous avons choisi dans nos exemples, et sont implémentables avec n’importe quel langage généraliste.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Utilisation des Fixtures
&lt;/h2&gt;

&lt;p&gt;Les Fixtures sont des ensembles de données préconfigurées utilisées pour initialiser l'état d'un test. Elles permettent de définir des conditions de test spécifiques et de garantir que les tests sont reproductibles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemples de code pour créer et utiliser des Fixtures en TypeScript
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// personaFixtures.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;johnDoe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="c1"&gt;// ... your full Persona caracteristics, to be used in several tests&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;johnDoe&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./personaFixtures&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;johnDoe&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...code&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;johnDoe&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simplicité et facilité d'utilisation.&lt;/li&gt;
&lt;li&gt;Reproductibilité des tests.&lt;/li&gt;
&lt;li&gt;Utilisation des persona UX&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Peuvent devenir difficiles à gérer pour des ensembles de données complexes.&lt;/li&gt;
&lt;li&gt;Moins flexibles pour des variations de données.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Utilisation des Object Mother
&lt;/h2&gt;

&lt;p&gt;Le pattern Object Mother consiste à créer des objets complexes à partir de méthodes de fabrication centralisées. Cela permet de simplifier la création d'objets de test et de garantir la cohérence des données.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemples de code pour créer des objets complexes avec des Object Mothers en TypeScript
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// objectMother.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserMother&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserMother&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./objectMother&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UserMother&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Avec un objet plus complexe :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les types&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// interfaces.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Object Mother pour Order&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// orderMother.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./interface&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderMother&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;with2Items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A very specific item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Another specific item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}];&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rich customer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;previousValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;previousValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;withoutItems&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Poor customer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
            &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;johnDoeBuysATable&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}];&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;previousValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;previousValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemple d’utilisation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;OrderMother&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./orderMother&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Order Mother&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create an order with items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OrderMother&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with2Items&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;320&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create an order without items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;OrderMother&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withoutItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Centralisation de la création d'objets.&lt;/li&gt;
&lt;li&gt;Facilité de maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Peut devenir complexe pour des objets très variés.&lt;/li&gt;
&lt;li&gt;Moins flexible pour des variations spécifiques.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Utilisation des Factory Functions
&lt;/h2&gt;

&lt;p&gt;Les Factory Functions sont des fonctions qui retournent des objets. Elles sont simples à utiliser et permettent de créer des objets de manière concise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemples de code pour créer des objets avec des Factory Functions en TypeScript
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 En TypeScript, l'utilisation du type &lt;strong&gt;&lt;code&gt;Partial&lt;/code&gt;&lt;/strong&gt; offre un avantage supplémentaire. Le type &lt;strong&gt;&lt;code&gt;Partial&lt;/code&gt;&lt;/strong&gt; permet de créer des objets partiels, ce qui signifie que vous pouvez définir uniquement les propriétés nécessaires pour un test spécifique. Cela rend les tests plus lisibles et plus faciles à maintenir. Vous pouvez déstructurer votre type pour rendre votre test plus lisible et explicite.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jane.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jonh Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jonh Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simplicité et facilité d'utilisation.&lt;/li&gt;
&lt;li&gt;Flexibilité pour créer des objets avec des variations spécifiques.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Moins adapté pour des objets très complexes.&lt;/li&gt;
&lt;li&gt;Peut devenir difficile à gérer pour des ensembles de données importants.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Utilisation des Test Data Builders / Builders
&lt;/h2&gt;

&lt;p&gt;Le pattern Builder permet de construire des objets complexes de manière incrémentale. Il est particulièrement utile pour créer des objets avec des variations spécifiques.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemples de code pour créer des objets complexes avec des builders en TypeScript
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// userBuilder.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;withName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;withEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserBuilder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./userBuilder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user with custom name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Avec un objet plus complexe:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Les types&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// interfaces.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test Data Builder pour Order&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ItemBuilder.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./interface&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ItemBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Default Item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;withName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;withId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;withPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;withQuantity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./interface&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ItemBuilder&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./itemBuilder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ItemBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt; &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;withCustomerName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;withItems&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;previousValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;previousValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemple d’utilisation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Simple test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create an order with default builder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create an order with 2 items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ItemBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ItemBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;withQuantity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;withId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;should create a John Doe's order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;withCustomerName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customerName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Flexibilité pour créer des objets avec des variations spécifiques.&lt;/li&gt;
&lt;li&gt;Facilité de lecture et de maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Vous pouvez également créer des builders avec des valeurs par défaut. C'est ce que recommande le livre "&lt;a href="http://www.growing-object-oriented-software.com" rel="noopener noreferrer"&gt;Growing Object-Oriented Software, Guided by Tests&lt;/a&gt;". Vous aurez ainsi une ou plusieurs méthodes statiques qui vous permettront de configurer vos tests à partir de personas ou de cas métiers spécifiques.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Inconvénients
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Peut devenir verbeux pour des objets simples.&lt;/li&gt;
&lt;li&gt;Nécessite une configuration initiale.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Nos préférences pour la création de jeu de données
&lt;/h2&gt;

&lt;p&gt;Pour nous, ce qui est important, c'est d'avoir une série de tests qui soit lisible et facile à écrire. C'est pourquoi nous mettons en avant trois critères pour choisir le pattern que nous voulons utiliser :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Visibilité des Variations de Données&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API Fluide et Lisibilité&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplicité et Flexibilité&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C’est pour cela que nous préférons les patterns &lt;strong&gt;Factory Function&lt;/strong&gt; et &lt;strong&gt;Test Data Builder.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Nous avons des préférences pour ces patterns, mais parfois nous allons utiliser une fixture ou un object mother, car le nommage métier peut être plus explicite que la simple variation des données, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Pourquoi le pattern Factory Function ?
&lt;/h3&gt;

&lt;p&gt;Pour des objets simples et sans profondeur, le pattern Factory Function est une approche efficace. Elle permet de créer des objets de manière concise.&lt;/p&gt;

&lt;p&gt;L'utilisation du type &lt;strong&gt;&lt;code&gt;Partial&lt;/code&gt;&lt;/strong&gt; en TypeScript facilite la création d'objets partiels, ce qui est particulièrement utile pour les tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pourquoi le pattern Test Data Builder ?
&lt;/h3&gt;

&lt;p&gt;Le pattern Builder est particulièrement adapté pour les objets avec plusieurs niveaux de profondeur. Il permet de construire des objets complexes de manière incrémentale, en chaînant des méthodes pour définir les différentes propriétés de l'objet. Cette approche offre une grande flexibilité et permet de voir facilement les variations de données, ce qui est crucial pour valider les tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Outils et bibliothèques populaires pour la création de jeux de données
&lt;/h2&gt;

&lt;h3&gt;
  
  
  faker.js
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Génération de données fictives réalistes.&lt;/li&gt;
&lt;li&gt;Idéal pour tester des scénarios avec des données variées.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  factory.ts
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Création structurée d'objets de test.&lt;/li&gt;
&lt;li&gt;Idéal pour des objets complexes et des variations spécifiques.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://fakerjs.dev/" rel="noopener noreferrer"&gt;faker.js&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;faker.js&lt;/code&gt; est une bibliothèque populaire pour générer des données fictives. Elle permet de créer des données réalistes pour les tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// fakerExample.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;faker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./email.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should generate a fake user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;a href="https://github.com/willryan/factory.ts" rel="noopener noreferrer"&gt;factory.ts&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;factory.ts&lt;/code&gt; est une bibliothèque TypeScript pour créer des objets de test de manière structurée.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// factoryExample.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Factory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;factory.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;makeFactory&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should create a user with factory.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  À partir de quoi faire varier les données ?
&lt;/h3&gt;

&lt;p&gt;Nous vous recommandons fortement de faire varier vos données à partir de personas UX ou de cas métiers bien identifiés. Ces éléments définiront vos valeurs par défaut pour la plupart des patterns décrits ci-dessus. L'objectif d'avoir ces valeurs par défaut (personas UX ou cas métiers) est de rendre vos tests lisibles et de les utiliser comme documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Où ranger ces patterns dans le code ?
&lt;/h3&gt;

&lt;p&gt;Ces fichiers servant uniquement aux tests, ils ont leur place à leurs côtés. Vous pouvez l’utiliser à côté du test qui l’utilise, mais s’il y a de la réutilisation ailleurs, il faudra créer un dossier et fichier dédié.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/test
    /order
        /order.ts
    /dataBuilders
        /orderBuilder.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La création de jeux de données pour les tests est essentielle pour garantir la qualité et la fiabilité du code. Chaque méthode a ses forces et ses limites, et le choix du bon pattern dépend de la complexité des éléments à générer.&lt;/p&gt;

&lt;p&gt;Il n’existe pas de solution universelle : la clé réside dans une réflexion collective et des décisions alignées avec les besoins de votre projet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pour aller plus loin
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://philippe.bourgau.net/how-to-use-test-data-builders-to-avoid-mocks-and-keep-your-tests-clear/" rel="noopener noreferrer"&gt;How to use Test Data Builders to avoid mocks and keep your tests clear | Philippe Bourgau’s XP Coaching Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.c2.com/?TestDataBuilder" rel="noopener noreferrer"&gt;https://wiki.c2.com/?TestDataBuilder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.growing-object-oriented-software.com" rel="noopener noreferrer"&gt;Growing Object-Oriented Software Guided by Tests&lt;/a&gt; de Steve Freeman et Nat Pryce&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.c2.com/?TestFixture" rel="noopener noreferrer"&gt;https://wiki.c2.com/?TestFixture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://refactoring.guru/design-patterns/factory-method" rel="noopener noreferrer"&gt;https://refactoring.guru/design-patterns/factory-method&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.codeleak.pl/2014/06/test-data-builders-and-object-mother.html" rel="noopener noreferrer"&gt;Test Data Builders and Object Mother: another look&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>softwarecraft</category>
      <category>french</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Guide pratique de l'utilisation des Linters</title>
      <dc:creator>Jérémy Chauvin</dc:creator>
      <pubDate>Wed, 24 Apr 2024 12:30:54 +0000</pubDate>
      <link>https://forem.com/singebob/guide-pratique-de-lutilisation-des-linters-1d50</link>
      <guid>https://forem.com/singebob/guide-pratique-de-lutilisation-des-linters-1d50</guid>
      <description>&lt;p&gt;Nous avons tous déjà vécu un onboarding sur un projet où on fait des copier/coller d’une autre fonctionnalité qui ressemble à ce qu’on veut faire. Nous réadaptons le code, nous commitons et nous pushons. Nous ouvrons la MR/PR et la revue est catastrophique. Le code que nous avons copié-collé est du code legacy, nous avons 15 fois le même commentaire qui nous dit d'utiliser des &lt;em&gt;const&lt;/em&gt; pour déclarer nos variables, etc. Tout cela nous fait perdre du temps, et ne nous met pas dans les meilleures conditions pour apprécier le projet.&lt;/p&gt;

&lt;p&gt;Dans cet article vous allez (re)découvrir comment les linters peuvent vous éviter ces pièges et vous aider à développer.&lt;/p&gt;

&lt;p&gt;Avant d’aborder les avantages d’un linter, nous allons expliquer ce que c’est&lt;/p&gt;

&lt;h2&gt;
  
  
  Qu’est-ce qu’un linter ?
&lt;/h2&gt;

&lt;p&gt;Techniquement, c’est un outil qui fait de l’analyse statique de votre code donc directement dans votre fichier sans que le code soit build ou soit en train de run. &lt;/p&gt;

&lt;p&gt;Cela permet d’avoir une boucle de feedback très courte 🤩&lt;/p&gt;

&lt;h3&gt;
  
  
  Sévérité
&lt;/h3&gt;

&lt;p&gt;Vous allez retrouver en général deux types de sévérité dans un linter qui sont les &lt;em&gt;Warnings&lt;/em&gt; et les &lt;em&gt;Errors.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Les &lt;em&gt;Warnings&lt;/em&gt; sont des problèmes potentiels qui n'empêchent pas l'exécution du code, mais indiquent des pratiques à améliorer pour maintenir la qualité et la cohérence du code.&lt;/p&gt;

&lt;p&gt;Les &lt;em&gt;Errors&lt;/em&gt; sont des problèmes bloquants qui empêchent le code de fonctionner correctement. Elles doivent être corrigées avant de pouvoir compiler ou exécuter le programme.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🧐 Pour information&lt;br&gt;
Dans la plupart des projets, vous allez retrouver la règle &lt;em&gt;no-warning&lt;/em&gt; dans notre CI. Ce qui fait que si vous avez une règle en &lt;em&gt;warning&lt;/em&gt; qui est détecté alors votre CI va planter.&lt;br&gt;
Personnellement, je n’aime pas cette feature, car elle vous obligent à tout faire d’un coup. Je vous en reparle dans la partie “Mieux refactorer du code legacy”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Rendre l’implicite explicite
&lt;/h2&gt;

&lt;p&gt;En mettant en place un ou des linters, vous allez pouvoir rendre l’implicite &lt;strong&gt;explicite&lt;/strong&gt;, c'est-à-dire faire émerger des règles et des conventions qui peuvent ne pas être documentées ou comprises par tous les membres de l'équipe.&lt;/p&gt;

&lt;p&gt;Par exemple, un linter peut vérifier que vos attributs sont dans l’ordre alphabétique, que vos variables sont bien immuables (en JS, n'utiliser que des &lt;em&gt;const&lt;/em&gt;), que vous respectez les normes sur le nommage de variable, de classes ou de fonctions dans votre projet. Ces règles peuvent sembler mineures, mais elles contribuent à la lisibilité et à la compréhension du code par tous les membres de l'équipe.&lt;/p&gt;

&lt;p&gt;En rendant ces règles explicites grâce à un linter, vous pouvez vous assurer que tout le monde suit les mêmes conventions et que le code soit cohérent et facile à comprendre. Cela peut également faciliter l'intégration de nouveaux membres dans l'équipe, car les règles sont clairement définies et documentées.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apprendre
&lt;/h2&gt;

&lt;p&gt;En utilisant un linter, vous pouvez apprendre de nouvelles pratiques. Les linters peuvent vous aider à découvrir des règles et des conventions que vous ne connaissiez peut-être pas auparavant, ainsi que les raisons pour lesquelles ces règles sont importantes.&lt;/p&gt;

&lt;p&gt;Par exemple, en utilisant un linter pour JavaScript, vous pouvez apprendre que la méthode "reduce" peut être moins performante qu'une boucle "for" dans certaines situations. En comprenant pourquoi cette règle est importante, vous pouvez prendre de meilleures décisions&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(&lt;a href="https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-reduce.md" rel="noopener noreferrer"&gt;https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-reduce.md&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;De plus, les linters peuvent vous aider à améliorer votre code que ça soit sur la lisibilité, la séparation de la logique, la sécurité (&lt;a href="https://snyk.io/fr/" rel="noopener noreferrer"&gt;Snyk&lt;/a&gt;, &lt;a href="https://www.sonarsource.com/products/sonarqube/" rel="noopener noreferrer"&gt;Sonar&lt;/a&gt; etc) et la performance. En comprenant pourquoi ces règles sont importantes, vous pouvez non seulement écrire du code plus propre et plus efficace, mais également vous améliorer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mieux refactorer du code legacy
&lt;/h2&gt;

&lt;p&gt;Lorsque vous travaillez sur une application existante avec du code legacy, un linter peut être un outil très utile pour vous aider à nettoyer et à mettre à jour votre code. Vous pouvez aussi identifier les parties de votre code qui doivent être mises à jour ou supprimées, et suivre votre progression au fil du temps.&lt;/p&gt;

&lt;p&gt;Par exemple, supposons que vous souhaitiez supprimer une bibliothèque (comme Lodash) de votre application. Cependant, le faire d'un coup peut être trop risqué ou trop complexe. Dans ce cas, vous pouvez commencer par ajouter une règle de linter en mode &lt;em&gt;warning&lt;/em&gt; sur l'utilisation de Lodash. Cela vous permettra de savoir chaque fois que vous utilisez Lodash dans votre code et de commencer à le supprimer progressivement. De plus, l’ajouter en mode &lt;em&gt;warning&lt;/em&gt; permet aussi à ce qu’un nouveau ou une personne qui rentre de vacances sache qu’il ne doit plus l’utiliser.&lt;/p&gt;

&lt;p&gt;En suivant le nombre d'avertissements de cette règle, vous pouvez suivre votre progression. Aussi, vous pouvez être sûr que tout nouveau code que vous écrivez ne dépendra pas de Lodash, ce qui facilitera la suppression complète de la bibliothèque à l'avenir.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Je vous conseille fortement de ne pas avoir plus d’une règle en &lt;em&gt;warning&lt;/em&gt; pour ne pas avoir trop de choses à faire d’un coup&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Attention, un linter apporte aussi une certaine complexité, qui peut vous freiner ou être un point de souffrance.&lt;/p&gt;

&lt;p&gt;Par exemple, vous avez deux règles qui, individuellement, semblent cohérentes :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mets en dernier les paramètres qui ont une valeur par défaut&lt;/li&gt;
&lt;li&gt;Trie les paramètres dans l’ordre alphabétique&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tant que vous n’avez pas les deux en même temps, il n’y a aucun problème. Mais si vous avez ça:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Mets en dernier les paramètres qui ont une valeur par défaut&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleThings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Trie les paramètre dans l'ordre alphabétique&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleThings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
     &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vos règles vont se marcher dessus. Pour éviter cela, je vous conseille donc de faire attention à ces deux points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ajout de règle sans cesse
&lt;/h2&gt;

&lt;p&gt;L'ajout de règles sans limite peut devenir contre-productif et entraver le bon déroulement du projet. Il est important de trouver un équilibre entre la qualité du code et la productivité de l'équipe.&lt;br&gt;
Je vous recommande de ne pas ajouter trop de règles d'un coup, mais plutôt de les introduire progressivement en fonction des besoins du projet et de l'équipe. Il est également utile de régulièrement réévaluer les règles existantes pour s'assurer qu'elles soient toujours pertinentes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Je vous conseille fortement de faire des discussions régulières pour parler des règles de linter, de choisir si vous devez la garder ou rajouter des règles si besoin. Pendant ces discussions il est important de documenter pourquoi vous mettez en place une règle ou pourquoi vous enlevez une règle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Le nombre idéal de règles dépend du projet et de l'équipe. &lt;/p&gt;

&lt;p&gt;La seule question que vous devez vous poser c’est si la règle est &lt;strong&gt;pertinente&lt;/strong&gt; dans votre contexte. &lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration complexe
&lt;/h2&gt;

&lt;p&gt;La configuration d'un linter peut devenir compliquée avec le temps et nécessitera une maintenance régulière pour rester efficace. Si la configuration n'est pas bien gérée, cela peut entraîner des problèmes tels que des règles contradictoires ou non pertinentes pour le projet. &lt;/p&gt;

&lt;p&gt;Il est important de prendre le temps de comprendre l'historique de la configuration du linter avant de faire des modifications ou de critiquer la configuration actuelle. Il peut être utile de discuter avec les membres de l'équipe qui ont travaillé précédemment sur la configuration  pour comprendre les raisons derrière certaines décisions. &lt;/p&gt;

&lt;p&gt;En outre, il est important de documenter les changements apportés à la configuration du linter et de communiquer ces changements à l'équipe. Cela peut aider à éviter les conflits et à maintenir une configuration cohérente et efficace. &lt;/p&gt;

&lt;h3&gt;
  
  
  Comment gérer la documentation de son linter ?
&lt;/h3&gt;

&lt;p&gt;Je recommande de stocker la documentation de votre linter à proximité du code, dans le même dépôt git&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❓ Pourquoi proche du code ?&lt;br&gt;
Si vous stockez la documentation du linter dans un outil externe tel que Confluence ou un autre référentiel qui génère un site web à partir de fichiers markdown, vous risquez de rencontrer des problèmes de synchronisation. &lt;br&gt;
Par exemple, quelqu'un peut oublier de mettre à jour la documentation ou vous n'y avez pas accès pour une raison quelconque. &lt;br&gt;
En revanche, si vous stockez la documentation du linter au même endroit que le code, vous réduisez considérablement le risque de désynchronisation. &lt;br&gt;
De plus, cela facilite l'accès à la documentation pour les développeurs qui travaillent sur le projet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vous pouvez créer un dossier &lt;code&gt;docs&lt;/code&gt; à la racine de votre projet. Ce dossier va contenir d’autres dossiers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 N'oubliez pas d'exclure ce dossier de vos outils de build ou autres.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Par exemple, un dossier &lt;code&gt;eslint&lt;/code&gt;, qui contiendra un fichier où vous expliquerez pourquoi vous avez utilisé certains plugins eslint et pourquoi vous avez désactivé ou ajouté certaines règles de lint. Bien sûr, n'oubliez pas d'ajouter les dates.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Il est important que toutes les modifications de règles renvoient à la documentation de la règle ou du plugin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Voici un exemple de fichier :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddfg9rx38uv8now5i7rm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddfg9rx38uv8now5i7rm.png" alt="Exemple de doc sur un projet" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quelques linters pour vous lancer
&lt;/h2&gt;

&lt;p&gt;Voici une liste de linters pour vous lancer avec le langage ou le format du fichier :&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Langage&lt;/th&gt;
&lt;th&gt;Linter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JS/TS&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;eslint&lt;/a&gt;, &lt;a href="https://biomejs.dev/" rel="noopener noreferrer"&gt;Biome&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;&lt;a href="https://checkstyle.sourceforge.io/" rel="noopener noreferrer"&gt;checkstyle&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;&lt;a href="https://golangci-lint.run/" rel="noopener noreferrer"&gt;GolangCi-lint&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/rust-lang/rust-clippy?tab=readme-ov-file#clippy" rel="noopener noreferrer"&gt;Clippy&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Yaml&lt;/td&gt;
&lt;td&gt;&lt;a href="https://yamllint.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Yamllint&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenApi&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.stoplight.io/docs/spectral/674b27b261c3c-overview" rel="noopener noreferrer"&gt;Spectral&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Si vous recherchez un linter pour votre langage ou un format de fichier, je vous conseille de regarder sur &lt;a href="https://megalinter.io/latest/" rel="noopener noreferrer"&gt;Megalinter&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Voilà j’espère vous avoir donné envie d’utiliser un linter ou des pistes pour améliorer votre expérience avec les linters 🐵&lt;/p&gt;

</description>
      <category>french</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Tips&amp;Tricks pour améliorer votre CI/CD</title>
      <dc:creator>Jérémy Chauvin</dc:creator>
      <pubDate>Tue, 10 Oct 2023 19:45:11 +0000</pubDate>
      <link>https://forem.com/singebob/tipstricks-pour-ameliorer-votre-cicd-334k</link>
      <guid>https://forem.com/singebob/tipstricks-pour-ameliorer-votre-cicd-334k</guid>
      <description>&lt;p&gt;On a tous déjà ressenti de la frustration envers la pipeline du projet. Parce que la CI est trop lente ou encore elle nous sort des &lt;a href="https://www.jetbrains.com/fr-fr/teamcity/ci-cd-guide/concepts/flaky-tests/" rel="noopener noreferrer"&gt;tests flaky&lt;/a&gt; et il faut la relancer plusieurs fois pour que ça passe… Tout cela, fait que nous perdons beaucoup de temps avec quelque chose qui est censée nous aider et nous en faire gagner.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Au niveau de chaque point je vais mettre un ou plusieurs icônes pour indiquer le but de ce point :&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Icône&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🏎️&lt;/td&gt;
&lt;td&gt;Permet de gagner du temps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⭐&lt;/td&gt;
&lt;td&gt;Important de l’avoir ou de le faire&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Avant de vous parler d’astuce pour améliorer votre pipeline nous devons quand même qualifier le terme CI et CD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Définition CI/CD
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Intégration Continue (Continuous Integration)
&lt;/h3&gt;

&lt;p&gt;L’intégration continue est une &lt;strong&gt;pratique&lt;/strong&gt; consistant à exécuter différents &lt;strong&gt;contrôles&lt;/strong&gt; sur tout type de contribution à votre repo.&lt;/p&gt;

&lt;p&gt;Nous allons souvent rencontrer ces étapes-là :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build image ou du binaire&lt;/li&gt;
&lt;li&gt;Test&lt;/li&gt;
&lt;li&gt;Lint&lt;/li&gt;
&lt;li&gt;Scan de vulnérabilités&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Déploiement Continu (Continuous Deployment)
&lt;/h3&gt;

&lt;p&gt;Le déploiement continu est la &lt;strong&gt;pratique&lt;/strong&gt; qui consiste à déployer &lt;strong&gt;automatiquement&lt;/strong&gt; des nouvelles versions dans un environnement dédié.&lt;/p&gt;

&lt;p&gt;Nous allons souvent rencontrer ces étapes là :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Déploiement de l’image&lt;/li&gt;
&lt;li&gt;Génération de la release note&lt;/li&gt;
&lt;li&gt;Génération de la version (tag, release, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏎️ Mise en place de cache de dépendance
&lt;/h2&gt;

&lt;p&gt;Une des premières étapes de la CI consiste à télécharger les dépendances du projet pour pouvoir exécuter les tests ou faire le build. Bref, c’est une étape essentielle pour votre CI. &lt;/p&gt;

&lt;p&gt;Cette étape, qui est majeure pour votre CI, prend un certain temps. Plus le projet est gros plus ce temps est important. Il est donc primordial de mettre en place un cache pour gagner du temps. &lt;/p&gt;

&lt;p&gt;Il y a quand même plusieurs types de cache de dépendances :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on peut voir le cache de dépendance de &lt;em&gt;pnpm&lt;/em&gt; et &lt;em&gt;maven&lt;/em&gt; qui consiste à faire un dossier au niveau du user où il ne font simplement qu’un lien symbolique ou une copie dans le projet.&lt;/li&gt;
&lt;li&gt;Le deuxième cache consiste à prendre votre fichier de gestion dépendance (exemples : package-lock.json (npm en JS, TS), poetry.lock (poetry en python) …) et de le hasher. Ce qui va vous générer un code unique en fonction du contenu du fichier. Si vous avez une nouvelle dépendance ou une nouvelle version d’une dépendance alors le hash sera différent. Une fois le hash calculé, vous pouvez créer un lien symbolique entre votre dossier du hash et le dossier qui contient les dépendances.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comment on fait ? 💡
&lt;/h3&gt;

&lt;p&gt;Pour la plupart des outils de CI connus, vous pouvez définir une gestion de cache à partir d’un ou plusieurs fichier comme clé.&lt;/p&gt;

&lt;p&gt;Par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.gitlab.com/ee/ci/caching/#cache-nodejs-dependencies" rel="noopener noreferrer"&gt;Gitlab CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/actions/setup-node#caching-global-packages-data" rel="noopener noreferrer"&gt;Github Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://circleci.com/blog/config-best-practices-dependency-caching/" rel="noopener noreferrer"&gt;Circle CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⭐ 🏎️ Paralléliser un maximum
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Paralléliser vos stages/job dans votre CI ou votre CD.
&lt;/h3&gt;

&lt;p&gt;Vous devez paralleliser un maximum vos étapes pour gagner du temps. C’est simple dit comme ça, mais il faut y penser. On a tendance à faire beaucoup de synchronisme même dans nos étapes de pipelines, alors que nous pouvons simplement les paralleliser.&lt;/p&gt;

&lt;p&gt;Nous pouvons prendre l’exemple du CI qui ne va faire que le build, le test et un lint. Dans environ 80% des CI qui existent nous allons retrouver ça :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Le build en premier&lt;/li&gt;
&lt;li&gt;Les tests qui dépendent du build (si le build échoue, on ne lance pas les tests)&lt;/li&gt;
&lt;li&gt;La tache de lint qui dépend des tests (si les tests fail on ne lance pas le lint)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgovu89pe5ym1cp7amln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgovu89pe5ym1cp7amln.png" alt="CI sans Paralléliser" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La liaison entre le build et les tests peut exister pour les langages compilés. Par contre pour les langages interprétés du type JS, python etc, vous n’avez pas besoin d’attendre la fin du build pour exécuter vos tests.&lt;/p&gt;

&lt;p&gt;La liaison entre votre linter et vos tests (ou même implicitement votre build) n’a AUCUNE raison d’exister. Cette tâche peut être lancée en même temps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvibu1bkk93uqamkjoia1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvibu1bkk93uqamkjoia1.png" alt="CI Paralléliser" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Paralléliser vos tests
&lt;/h3&gt;

&lt;p&gt;Comme vous pouvez paralléliser vos jobs ou vos stages dans votre CI, vous pouvez tout aussi bien paralléliser vos tests en utilisant, par exemple, des test runners spécialement conçus à cet effet, tels que &lt;a href="https://github.com/avajs/ava" rel="noopener noreferrer"&gt;AvA&lt;/a&gt; en JS/TS.&lt;/p&gt;

&lt;p&gt;Avoir une étape de test dans votre CI ne veut pas dire que c’est un fourretout. Vous pouvez créer plusieurs étapes qui peuvent tourner en même temps. Comme par exemple avoir une étape de test unitaire, test d’intégration, etc&lt;/p&gt;

&lt;p&gt;On va être un peu plus précis pour les tests d'intégration qui sont complexes. Surtout sur la gestion de la base de données et des données qui y sont contenues. &lt;/p&gt;

&lt;p&gt;Premièrement, il incombe aux tests de lancer la base de données et de mettre en place les données nécessaires pour les tests.&lt;/p&gt;

&lt;p&gt;Deuxièmement, votre base de données n'est pas obligée d'être vidée et de réinsérer des données. Vous pouvez simplement, vous assurer que vos tests ne s'entremêlent pas en utilisant des données un peu plus aléatoires, comme par exemple des UUID au lieu d'auto-incrément, ce qui réduit les chances que les données entrent en collision si vous effectuez une insertion dans votre test.&lt;/p&gt;

&lt;p&gt;Troisièmement, sur des tests d’intégration je vous déconseille de vérifier des données avec des valeurs absolues mais de bien les vérifier à partir d’un objet généré avec des données générées. &lt;/p&gt;

&lt;p&gt;Une fois que vous avez fait tout ça, vous pouvez normalement les parralléliser simplement 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  ⭐ ⭐ Avoir les bonnes dimensions de machines
&lt;/h2&gt;

&lt;p&gt;Il est également très important de bien choisir les ressources que vous accordez à vos runners de votre pipeline.&lt;/p&gt;

&lt;p&gt;Si vos runners n'ont pas les ressources minimales pour exécuter certains logiciels, tels que Cypress ou d'autres outils qui peuvent être gourmands en ressources, vous vous retrouverez avec une étape lente ou, pire encore, une étape qui plante et qui va sortir des faux positifs.&lt;/p&gt;

&lt;p&gt;Ce qu'il y a de plus frustrant pour vos utilisateurs c’est de devoir relancer certains jobs et d'espérer que ça passe. Ils perdent beaucoup de temps et s'ils se produisent fréquemment, ils peuvent décider de supprimer ou de passer le test qui est en faux positif afin de contourner le problème.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏎️ 🏎️ Ne pas reproduire deux fois la même chose
&lt;/h2&gt;

&lt;p&gt;Je pense que cette étape est une étape qui peut vous faire gagner beaucoup de temps. Imaginons que nous soyons sur un projet qui utilise le git flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrggptarcwg1ctqpwkja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrggptarcwg1ctqpwkja.png" alt="Git Flow" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pour les branches de feature, nous n'exécutons que les étapes de notre CI, c'est-à-dire Build, Test et Lint. La CI met en tout 5 minutes à tourner. Lorsque la branche de feature est mergée ou rebasée sur votre branche de develop, la CI retourne également, tout comme lorsque vous arrivez sur votre branche de release. Cela signifie que pour le même commit, donc le même code, nous exécutons la CI 3 fois, ce qui nous donne exactement le même résultat. L'utilisateur doit attendre 5 minutes sur develop avant de pouvoir le déployer sur son environnement, et c'est la même chose sur sa branche de release.&lt;/p&gt;

&lt;p&gt;Pour éviter que votre utilisateur ne perde encore plus de temps sur votre pipeline, il y a une solution. Vous pouvez faire la promotion de l'artifact, c'est-à-dire que votre artifact sera créé sur votre branche de feature, en utilisant l'identifiant de votre commit comme identifiant de votre artifact.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Exemple de votre artefact :&lt;br&gt;
&lt;code&gt;application-0de83a78334c64250b18b5191f6cbd6b97e77f84&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Le nom de votre artefact peut être plus court si vous utilisez la version courte de l'ID du commit :&lt;br&gt;
&lt;code&gt;application-0de83a7&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mais vous pouvez aussi le combiner avec le futur numéro de version :&lt;br&gt;
&lt;code&gt;application-2.3.1-0de83a7&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dès que votre artefact est prêt, la première étape de votre CI sera de vérifier si l'artefact existe afin de sauter toute la partie CI et passer directement à votre CD sans attendre.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Vous pouvez aussi le faire si vous faites du trunk based 😁&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ⭐ 🏎️ Lancer vos stages/jobs que quand c’est utile
&lt;/h2&gt;

&lt;p&gt;Imaginons que dans votre projet, vous ayez vos fichiers de configuration de déploiement kubernetes, pour l’exemple on va parler de fichier helm. Ce qui nous donne ceci :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4flajxzu14i12vbd199.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4flajxzu14i12vbd199.png" alt="Image description" width="194" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lorsque vous modifiez uniquement les fichiers du dossier Helm, vous ne devez pas lancer toute la CI du projet. Vous ne devez lancer que la CI de ce dossier en particulier, par exemple un linter pour YAML ou le linter de Helm. De même, si le fichier n'a pas été modifié, vous n'avez pas besoin de lancer la CI de ce dossier. Ce qui signifie pas de tâche de linter Helm ou YAML pour ce dossier.&lt;/p&gt;

&lt;p&gt;Si vous suivez cette étape correctement, vous ou vos utilisateurs pourrez faire de petites modifications de configuration sans perdre de temps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comment on fait ? 💡
&lt;/h3&gt;

&lt;p&gt;Pour la plupart des outils de CI connus, vous pouvez définir des conditions sur le &lt;strong&gt;quand&lt;/strong&gt; lancer vos étapes/jobs. Et dans ces conditions, il y a la possibilité de choisir si un dossier ou un fichier a été modifié.&lt;/p&gt;

&lt;p&gt;Par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.gitlab.com/ee/ci/yaml/index.html#ruleschanges" rel="noopener noreferrer"&gt;Gitlab CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dorny/paths-filter#example" rel="noopener noreferrer"&gt;Github Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://circleci.com/developer/orbs/orb/circleci/path-filtering" rel="noopener noreferrer"&gt;Circle CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⭐ ⭐ ⭐ Définir une durée maximum au niveau de votre pipeline
&lt;/h2&gt;

&lt;p&gt;Ce tips est, pour moi, un des trois plus important de votre pipeline, il va vous permettre de ne pas (re)tomber dans une pipeline qui dure plus de 20 minutes ou plus.&lt;/p&gt;

&lt;p&gt;On va parler de la &lt;a href="https://fr.wikipedia.org/wiki/Loi_de_Parkinson" rel="noopener noreferrer"&gt;loi de Parkinson&lt;/a&gt;, qui nous apprend que le temps du travail a tendance à s'étendre pour occuper tout le temps disponible pour sa réalisation. En d'autres termes, si vous accordez une certaine quantité de temps pour accomplir une tâche (même si elle pourrait être terminée plus rapidement) elle prendra souvent tout le temps alloué.&lt;/p&gt;

&lt;p&gt;Il est donc très important de fixer une durée maximale pour votre CI/CD et également pour vos étapes le plus tôt possible. Car si vous ne le faites pas, le temps va continuer à s'étirer jusqu'à atteindre un point où il devient très compliqué et coûteux de revenir à un environnement stable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comment on fait ? 💡
&lt;/h3&gt;

&lt;p&gt;Pour la plupart des outils de CI connus, vous pouvez définir un timeout par job ou steps.&lt;/p&gt;

&lt;p&gt;Par exemple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run" rel="noopener noreferrer"&gt;Gitlab CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepstimeout-minutes" rel="noopener noreferrer"&gt;Github Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.circleci.com/hc/en-us/articles/4411204604059-Automatically-cancel-build-after-set-amount-of-time" rel="noopener noreferrer"&gt;Circle CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⭐ ⭐ ⭐ Mise en place d’alerting
&lt;/h2&gt;

&lt;p&gt;Comme le précédent tips, je le considère comme très important et pas seulement pour votre pipeline mais pour tout software.&lt;/p&gt;

&lt;p&gt;La mise en place d'un système d'alerte robuste dans votre CI/CD est d'une importance capitale pour garantir la réactivité et la fiabilité de vos opérations de développement et de déploiement. L'alerting permet de surveiller en temps réel chaque étape de votre pipeline CI/CD, identifiant ainsi toute anomalie, tout retard ou tout échec potentiel. En recevant des alertes immédiates lorsqu'un problème survient, l'équipe peut intervenir rapidement pour diagnostiquer, résoudre et rétablir la stabilité du pipeline. Cela réduit considérablement les temps d'arrêt, optimise le temps de réaction et contribue à maintenir la fluidité et l'efficacité de la chaîne de livraison logicielle.&lt;/p&gt;

&lt;p&gt;De plus, l'alerting dans la CI/CD favorise une culture de responsabilité et d'amélioration continue au sein de l'équipe de développement. En recevant des alertes en temps réel, chaque membre de l'équipe est informé de l'état du pipeline et de tout incident potentiel. Cela encourage une réactivité immédiate et incite les membres de l'équipe à résoudre les problèmes rapidement et efficacement. De plus, ces alertes fournissent des données exploitables pour effectuer des analyses post-mortem, identifier les problèmes récurrents et itérer constamment le processus afin d'améliorer la robustesse et l'efficacité de la CI/CD. En fin de compte, l'alerting sert non seulement à maintenir des opérations fluides, mais aussi à stimuler l'innovation et l'efficacité de l'équipe de développement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comment on fait ? 💡
&lt;/h3&gt;

&lt;p&gt;Pour la plupart des outils de CI connus, vous pouvez récupérer les métriques et les utiliser dans un dashboard datadog ou autre&lt;/p&gt;

&lt;p&gt;Par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.datadoghq.com/blog/monitor-gitlab-with-datadog/" rel="noopener noreferrer"&gt;Gitlab CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.datadoghq.com/blog/datadog-github-actions-ci-visibility/" rel="noopener noreferrer"&gt;Github Action&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Circle CI :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Circle CI ont leur propre solution de monitoring&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://circleci.com/docs/insights/" rel="noopener noreferrer"&gt;Voir les métriques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://circleci.com/docs/notifications/#notifications-with-orbs" rel="noopener noreferrer"&gt;Envoyer des notifications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Voilà j’espère vous avoir donner des idées pour améliorer votre pipeline de CI/CD 🐵&lt;/p&gt;

</description>
      <category>french</category>
      <category>cicd</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Différentes façons de déployer une application front faites en JS</title>
      <dc:creator>Jérémy Chauvin</dc:creator>
      <pubDate>Wed, 12 Jul 2023 17:18:19 +0000</pubDate>
      <link>https://forem.com/singebob/differentes-facons-de-deployer-une-application-front-faites-en-js-13of</link>
      <guid>https://forem.com/singebob/differentes-facons-de-deployer-une-application-front-faites-en-js-13of</guid>
      <description>&lt;p&gt;Nous avons tous déjà vécu l'expérience de travailler sur un side Project, de coder l'ensemble de l'application, puis de se demander : « Comment vais-je le déployer ? ». &lt;/p&gt;

&lt;p&gt;Dans cet article, vous allez (re)découvrir les différentes façons de déployer votre application front, ainsi que les cas où il est plus intéressant d'utiliser telle ou telle méthode.&lt;/p&gt;

&lt;p&gt;Mais avant de parler de déploiement, il faut expliquer les différentes implémentations d'application que vous pouvez rencontrer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plusieurs implémentations d’application front JS
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Ici on va expliquer grossièrement les différences entre les plusieurs types d’implémentations, car certains déploiements ne peuvent être fait avec certaines implémentations&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SPA ( Single Page Application )&lt;/p&gt;

&lt;p&gt;Ce genre d'implémentation est vraiment simple. Elle est composée d’un fichier HTML qui fait référence à un fichier JS (aussi appelé &lt;em&gt;bundle&lt;/em&gt;). Ce &lt;em&gt;bundle&lt;/em&gt; permet de charger tout le contenu de la page côté client.&lt;/p&gt;

&lt;p&gt;Lorsque vous exécutez votre commande de build pour votre application, vous obtenez:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index.html&lt;/li&gt;
&lt;li&gt;script.js (un &lt;em&gt;bundle&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;public (un dossier contenant des images et le favicon du site)&lt;/li&gt;
&lt;li&gt;style.css (un &lt;em&gt;bundle&lt;/em&gt; de votre CSS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ce genre d'implémentation est souvent utilisé dans les nouvelles librairies front telles que &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt;, &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt;, &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt; ou &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; (et sûrement d'autres).&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;SSG ( Static Site Generator )&lt;/p&gt;

&lt;p&gt;Cette implémentation permet de générer des pages HTML statiques à partir de fichiers sources, tels que des fichiers Markdown. Le SSG est très souvent utilisé pour créer des blogs ou des sites vitrines.&lt;/p&gt;

&lt;p&gt;Pour savoir si vous utilisez un SSG, c'est assez facile. Lorsque vous allez construire votre application, dans votre sortie vous allez voir votre structure de fichier être transformée en fichier HTML, par exemple :&lt;/p&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dg02503psbc1841wsqs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dg02503psbc1841wsqs.png" alt="Image description" width="432" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28jtimf93ingz0uzq018.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28jtimf93ingz0uzq018.png" alt="Image description" width="442" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Les bibliothèques/frameworks qui existent pour faire du SSG : &lt;a href="https://www.gitbook.com/" rel="noopener noreferrer"&gt;GitBook&lt;/a&gt;, &lt;a href="https://docusaurus.io/fr/" rel="noopener noreferrer"&gt;Docusaurus&lt;/a&gt;, &lt;a href="https://vitepress.dev/" rel="noopener noreferrer"&gt;Vitepress&lt;/a&gt;, &lt;a href="https://starlight.astro.build/" rel="noopener noreferrer"&gt;Starlight&lt;/a&gt;, &lt;a href="https://iles.pages.dev/" rel="noopener noreferrer"&gt;îles&lt;/a&gt; et pleins d'autres.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SSR ( Server Side Rendering )&lt;/p&gt;

&lt;p&gt;Cette implémentation permet de générer le rendu HTML côté serveur, comme en PHP ou en Java avec les JSP, et de n'envoyer que le strict minimum à l'utilisateur.&lt;/p&gt;

&lt;p&gt;Pour savoir si vous utilisez cette méthode d'implémentation, il faut consulter la documentation de votre framework ou de vos bibliothèques. Il n'y a pas de manière simple de le savoir.&lt;/p&gt;

&lt;p&gt;Parmi les frameworks qui proposent du SSR, on retrouve &lt;a href="https://astro.build/" rel="noopener noreferrer"&gt;Astro&lt;/a&gt;, &lt;a href="https://kit.svelte.dev/" rel="noopener noreferrer"&gt;SvelteKit&lt;/a&gt;, &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;, &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next&lt;/a&gt; et d'autres.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Différentes façons de déployer une application front
&lt;/h1&gt;

&lt;p&gt;Lorsqu'il s'agit de déployer une application front, il existe plusieurs méthodes à considérer. Voici les façons les plus courantes de le faire :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 J’ai mis en place un tableau dans les méthodes de déploiement pour savoir si elles sont adaptées en fonction de l’implémentation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Voici la légende du tableau: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pastille de couleurs&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;td&gt;Solution Idéale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Solution fonctionnelle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Impossible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Utilisation de bucket/S3
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implémentation front&lt;/th&gt;
&lt;th&gt;Possible ?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SPA&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSG&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Vous pouvez utiliser un service de stockage de fichiers (bucket) ou S3 pour héberger votre site web, mais cela n'est possible que pour les applications de type SSG et SPA. Il est impossible de déployer une application SSR sur un bucket car il n'y a pas de serveur node qui permet de générer les pages HTML.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Attention pour les SPA, si vous les déployez sur un bucket/S3, vous devez mettre l’&lt;em&gt;index.html&lt;/em&gt; en entrée par défaut et en entrée si le fichier n’est pas trouvé dans votre bucket. Par exemple, vous avez une route nommer &lt;em&gt;/blog&lt;/em&gt; votre bucket va chercher un fichier nommée &lt;em&gt;blog.html&lt;/em&gt; à la racine. Mais comme dit plus haut pour les SPA, il n’existe que votre fichier index.html&lt;/p&gt;

&lt;p&gt;⚠️ Un déploiement avec un bucket/S3 sera en HTTP. La redirection DNS suffit pour avoir votre site en HTTPS, mais il y a quand même un risque de sécurité. AWS à leur propre solution pour passer l’URL de votre S3 en HTTPS&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Les avantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Facile à mettre en place ( peu de connaissance technique pour le mettre en place )&lt;/li&gt;
&lt;li&gt;Évite les coûts et les contraintes d'un serveur&lt;/li&gt;
&lt;li&gt;Haute dispo &amp;amp; scalabilité&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Les désavantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Peut vite devenir cher, si vous avez beaucoup de visites&lt;/li&gt;
&lt;li&gt;Zéro contrôle sur l’environnement, vous ne pouvez seulement specifier le fichier d’entrées et le fichier si aucun fichier n’est trouvé&lt;/li&gt;
&lt;li&gt;Très peu sécurisés, tout les fichiers dans les buckets sont accessibles&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cas d’utilisation intéressant:
&lt;/h3&gt;

&lt;p&gt;Le cas d’utilisation intéressant pour ce type de déploiement est :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;les sites statiques ( blog, landing page )&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Utilisation de services de PaaS ( Plateforme as a Service )
&lt;/h2&gt;

&lt;p&gt;Les services de PaaS tels que &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;, &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; ou encore &lt;a href="https://www.clever-cloud.com/" rel="noopener noreferrer"&gt;Clever Cloud&lt;/a&gt; sont des plateformes de déploiement qui permettent de déployer rapidement des applications. Ces services prennent en charge la génération de sites statiques mais depuis peu les implémentations dynamiques comme le SSR.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implémentation front&lt;/th&gt;
&lt;th&gt;Possible ?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SPA&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSG&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Avantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Facile à mettre en place ( peu de connaissance technique pour le mettre en place )&lt;/li&gt;
&lt;li&gt;Évite les coûts et les contraintes d'un serveur&lt;/li&gt;
&lt;li&gt;La version gratuite peut-être suffisant au début&lt;/li&gt;
&lt;li&gt;Beaucoup de feature intéressante, comme les environnements générés sur chaque PR&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Désavantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Coût mensuel ou annuel pour l'utilisation de la plateforme&lt;/li&gt;
&lt;li&gt;Limitations de personnalisation et de configuration&lt;/li&gt;
&lt;li&gt;Dépendance à un tiers pour le déploiement et l'hébergement ( Un peu vrai pour tous les services cloud )&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cas d’utilisation intéressant:
&lt;/h3&gt;

&lt;p&gt;Le cas d’utilisation intéressant pour ce type de déploiement est :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Le début d’un side projet pour livrer le plus rapidement possible de la valeurs sans se prendre la tête&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Utilisation d’un service CaaS ( Container as a service )
&lt;/h2&gt;

&lt;p&gt;Vous pouvez aussi déployer votre application sous forme de containers. Pour ce faire, vous devez créer une image, avec un dockerfile ou encore en passant par &lt;a href="https://buildpacks.io/" rel="noopener noreferrer"&gt;buildpack&lt;/a&gt;. Une fois votre image créée et mise sur une registry accessible, vous pouvez la deployer via des services cloud comme GCP, AWS, Azure, Scaleway voir même sur certains services de PaaS comme Clever Cloud&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implémentation front&lt;/th&gt;
&lt;th&gt;Possible ?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SPA&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSG&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Avantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Possibilité de déployer sur de multiples environnements assez facilement&lt;/li&gt;
&lt;li&gt;Possibilité de personnaliser le déploiement et la configuration de l'environnement&lt;/li&gt;
&lt;li&gt;Possibilité de gérer efficacement les ressources et de réduire les coûts&lt;/li&gt;
&lt;li&gt;Possibilité de mettre en place des stratégies de scalabilité horizontales&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Désavantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Nécessite des compétences techniques et une certaine expertise pour mettre en place et gérer l'environnement de déploiement&lt;/li&gt;
&lt;li&gt;Coûts associés à l'utilisation de services cloud pour héberger l'application&lt;/li&gt;
&lt;li&gt;Complexité accrue par rapport à d'autres méthodes de déploiement plus simples&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cas d’utilisation intéressant:
&lt;/h3&gt;

&lt;p&gt;Le cas d’utilisation intéressant pour ce type de déploiement est :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si vous êtes en entreprise et qu’il y a déjà un cluster kube pour déployer vos applications et qu’on vous interdit d’utiliser un PaaS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Utilisation d’un Serveur ou VM dédié
&lt;/h2&gt;

&lt;p&gt;Vous pouvez aussi déployer vos applications front depuis un serveur dédié ou une VM. Pour ce faire, il suffit de mettre en place un reverse proxy comme Nginx, Traefik, HaProxy et certainement d’autres.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Si vous voulez déployer du SSR sur un serveur dédié, il faut penser à mettre en place un serveur node, si vous faites du Next, Nuxt ou SvelteKit. Si vous faites du PHP, n’oubliez pas d’en mettre un aussi sinon ça ne va pas fonctionner.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6t84uqp31gkuur3qy0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6t84uqp31gkuur3qy0c.png" alt="Image description" width="432" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implémentation front&lt;/th&gt;
&lt;th&gt;Possible ?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SPA&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSG&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSR&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Avantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Possibilité de personnaliser le déploiement&lt;/li&gt;
&lt;li&gt;Contrôle total sur l'environnement de l'application&lt;/li&gt;
&lt;li&gt;Pas de coûts supplémentaires pour l'utilisation d'une plateforme tierce&lt;/li&gt;
&lt;li&gt;Possibilité d'ajouter des modules et des bibliothèques personnalisées&lt;/li&gt;
&lt;li&gt;Possibilité de gérer les ressources et de réduire les coûts&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Désavantages :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Nécessite des compétences techniques et une certaine expertise pour la mise en place et la gestion de l'environnement de déploiement&lt;/li&gt;
&lt;li&gt;Complexité accrue par rapport à d'autres méthodes de déploiement plus simples&lt;/li&gt;
&lt;li&gt;Risques de sécurité plus élevés en cas d'erreurs de configuration&lt;/li&gt;
&lt;li&gt;Nécessite une maintenance régulière pour garantir la sécurité et les performances de l'application&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cas d’utilisation intéressant:
&lt;/h3&gt;

&lt;p&gt;Le cas d’utilisation intéressant pour ce type de déploiement est :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pour apprendre la complexité de deployer et de maintenir un serveur web soi-même&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tableau récapitulatif
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;SPA&lt;/th&gt;
&lt;th&gt;SSG&lt;/th&gt;
&lt;th&gt;SSR&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bucket/S3&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PaaS&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CaaS&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Serveur ou VM dédié&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;🌟&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Il existe beaucoup moyen de déployer une application front, mais chaque façon de déployer a des avantages comme des inconvénients. Il est donc important de le savoir, par contre ce choix ne doit pas vous bloquer. Vous pouvez logiquement le changer sans problèmes.&lt;/p&gt;

&lt;p&gt;Voilà j’espère vous avoir donner des idées pour déployer votre application front que ça soit votre blog ou vos sides projects 🐵&lt;/p&gt;

</description>
      <category>french</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
