---
title: "Invité mystère"
type: "test-smell"
slug: "mystery-guest"
url: "http://localhost:3000/fr/test-smells/mystery-guest.md"
category: "Odeurs de fixture"
description: "Un test dont les entrées ou les résultats attendus se trouvent dans une ressource externe — un fichier, un jeu de données de base de données (seed) ou une fixture partagée — de sorte que vous ne pouvez ni comprendre ni faire confiance au test en le lisant seul."
---
# Invité mystère

> Un test dont les entrées ou les résultats attendus se trouvent dans une ressource externe — un fichier, un jeu de données de base de données (seed) ou une fixture partagée — de sorte que vous ne pouvez ni comprendre ni faire confiance au test en le lisant seul.

## Signs and Symptoms

Vous ne pouvez pas comprendre un test en le lisant : les données qui le pilotent (et qui justifient ses assertions) se trouvent quelque part hors champ — un fichier CSV/JSON, un script de seed de base de données, un module de fixture partagé, ou une annotation de fixture de données du framework. Le test référence une ressource opaque puis fait des assertions sur des valeurs « magiques » dont la signification est cachée dans cette ressource.

Signes révélateurs :

* Le corps appelle quelque chose comme `readFileSync('fixtures/subscribers.csv')`, `loadSeed('invoices.sql')`, `getResource(...)`, ou un `beforeAll` global qui alimente une base de données partagée.
* Les valeurs attendues semblent arbitraires (`toHaveLength(3)`, un id/e-mail spécifique) et vous devez ouvrir un autre fichier pour apprendre _pourquoi_.
* Une fixture partagée/« générale » est réutilisée par de nombreux tests, de sorte que les entrées pertinentes pour _ce_ test sont noyées parmi des données dont il n'a que faire.
* Les tests se cassent lorsqu'un coéquipier modifie une fixture partagée pour un test sans rapport.

```js
test('returns active subscribers', async () => {
  // Invité mystère : quelles lignes contient ce fichier ? pourquoi 3 est-il correct ?
  const subscribers = await loadSubscribersFromCsv('./fixtures/subscribers.csv');
  const result = filterActive(subscribers);
  expect(result).toHaveLength(3); // la justification se trouve en dehors du test
});

```

L'exemple original du catalogue de Meszaros/des Test Smells a la même forme : `loadAirportsAndFlightsFromFile("test-flights.csv")` suivi de `assertEquals(1, flightsAtOrigin.size())` — le "1" n'a de sens que si vous lisez `test-flights.csv`.

## Reasons for the Problem

**Pourquoi cela arrive**

* _Le principe DRY poussé trop loin._ Les données de test sont extraites dans un fichier partagé ou une « fixture générale » pour éviter la duplication, échangeant la lisibilité contre la réutilisation.
* _La commodité des données réelles._ Déverser un CSV/JSON de production ou un `seed.sql` semble plus facile que de construire des objets en ligne.
* _Configuration héritée/d'intégration._ Les suites qui démarrent une base de données partagée ou s'appuient sur des annotations de fixtures de données du framework (`@magentoDataFixture …`) héritent d'un état caché par défaut.

**Pourquoi cela nuit**

* _Lisibilité / cause à effet._ Le lien entre l'entrée et la sortie attendue est rompu. Un lecteur ne peut pas voir _pourquoi_ l'assertion est correcte sans quitter le test, ce qui va à l'encontre du rôle d'un test en tant que documentation exécutable.
* _Fausse confiance._ Vous ne savez pas réellement ce que le test exerce ; le fichier peut contenir plus (ou moins) que ce que vous supposez, de sorte qu'une exécution réussie prouve moins qu'il n'y paraît.
* _Fiabilité / déterminisme._ La ressource externe peut être manquante, renommée, reformatée, ou différer selon l'environnement, le système d'exploitation, l'encodage ou la locale — les échecs reflètent alors l'état de la _fixture_, et non un véritable défaut (tests instables).
* _Maintenabilité / couplage._ Lorsque plusieurs tests partagent une même ressource, quiconque la modifie pour un test peut silencieusement casser les autres, et personne ne sait de quels champs chaque test dépend.

## Treatment

Rendez l'entrée _pertinente_ visible à l'intérieur du test, à côté de l'assertion qui en dépend (une **Fresh Fixture** / configuration en ligne). L'objectif est que la valeur attendue devienne évidente.

Étapes concrètes :

1. **Inlinez les données qui comptent.** Construisez dans le corps du test les quelques objets/lignes qui intéressent le test, afin que la valeur attendue de l'assertion soit manifestement correcte.
2. **Si vous avez réellement besoin d'un fichier, construisez-le dans le test.** Utilisez une fonction utilitaire qui ne prend que les paramètres significatifs et écrit dans un chemin temporaire, puis nettoyez — de sorte que les valeurs significatives apparaissent dans le test, et non dans un blob versionné.
3. **Remplacez les fixtures partagées/« générales » par des fixtures propres à chaque test**, ou exposez des créateurs/chercheurs au nom explicite (`createProductWithName('Simple Product')`, `getRecentlyAddedProduct()`) afin que les attributs testés soient explicites tandis que la configuration sans rapport reste cachée derrière un constructeur bien nommé — et non derrière une ressource opaque.

Avant → après :

```js
// Avant — Invité mystère : les données et le "2" sont cachés dans un fichier seed
test('flags overdue invoices', async () => {
  await seedDatabaseFromFixture('invoices.sql');
  const overdue = await findOverdueInvoices();
  expect(overdue).toHaveLength(2);
});

// Après — les entrées sont visibles ; le résultat attendu est évident
test('flags overdue invoices', async () => {
  await insertInvoice({ id: 1, dueDate: '2020-01-01', paid: false }); // en retard
  await insertInvoice({ id: 2, dueDate: '2099-01-01', paid: false }); // pas encore échu
  const overdue = await findOverdueInvoices();
  expect(overdue.map(i => i.id)).toEqual([1]);
});

```

Pour le cas du fichier, préférez une fonction utilitaire ciblée à un fichier versionné :

```js
const csv = makeSubscriberCsv(tmpFile, 'active@x.com', 'active@y.com', 'active@z.com');
// désormais, "3 actifs" est justifié par ce que vous voyez dans le test, et non par un fichier caché

```
