

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Guide de test des plugins
<a name="sbomgen-plugin-testing-guide"></a>

 Les auteurs de plugins écrivent et testent les plugins Lua entièrement dans Lua. Aucune chaîne d'outils Go n'est requise. Les tests sont colocalisés avec le plugin ci-dessous `init_test.lua` et exécutés via la `inspector-sbomgen plugin test` commande. 

 Pour la création générale de plugins, consultez le[Guide du développeur de plugins](sbomgen-plugin-developer-guide.md). Pour le catalogue complet des fonctions (y compris l'`testing.*`API), consultez le[Référence de l'API du plugin](sbomgen-plugin-api-reference.md). 

```
-- init_test.lua (next to init.lua)
function test_discovers_curl_version()
    local result = testing.scan_directory("_testdata/include/curl")
    testing.assert_equals(1, #result.findings)
    testing.assert_equals("libcurl", result.findings[1].name)
    testing.assert_equals("8.14.1", result.findings[1].version)
end
```

```
# Run every test under a plugin directory
inspector-sbomgen plugin test --path ./my-plugins

# Verbose output — show each test name and result
inspector-sbomgen plugin test --path ./my-plugins -v
```

## Quick Start
<a name="sbomgen-plugin-testing-guide-quick-start"></a>

### 1. Création d'un fichier de test
<a name="sbomgen-plugin-testing-guide-1-create-a-test-file"></a>

 Placez à `init_test.lua` côté de celui de votre plugin `init.lua` : 

```
my-plugin/
├── discovery/cross-platform/extra-ecosystems/curl/
│   ├── init.lua
│   ├── init_test.lua
│   └── _testdata/
│       └── include/curl/curlver.h
```

### 2. Écrire des fonctions de test
<a name="sbomgen-plugin-testing-guide-2-write-test-functions"></a>

 Toute fonction globale commençant par `test_` est découverte et exécutée : 

```
function test_finds_libcurl()
    local result = testing.scan_directory("_testdata/include/curl")
    testing.assert_equals(1, #result.findings)
    testing.assert_equals("libcurl", result.findings[1].name)
end

function test_no_findings_for_empty_dir()
    local result = testing.scan_directory("_testdata/empty")
    testing.assert_equals(0, #result.findings)
end
```

### 3. Exécuter des tests
<a name="sbomgen-plugin-testing-guide-3-run-tests"></a>

```
inspector-sbomgen plugin test --path ./my-plugin
```

## Disposition du répertoire
<a name="sbomgen-plugin-testing-guide-directory-layout"></a>

### Structure du plugin
<a name="sbomgen-plugin-testing-guide-plugin-structure"></a>

 Les fichiers de test et les données de test sont situés au même endroit que le plugin : 

```
my-plugins/
├── discovery/
│   └── cross-platform/
│       └── extra-ecosystems/
│           └── curl/
│               ├── init.lua          # plugin source
│               ├── init_test.lua     # test file
│               └── _testdata/        # test fixtures
│                   ├── include/curl/curlver.h
│                   └── binaries/unix/curl
├── collection/
│   └── cross-platform/
│       └── extra-ecosystems/
│           └── curl-installation/
│               ├── init.lua
│               └── init_test.lua
```

### Nommage des fichiers de test
<a name="sbomgen-plugin-testing-guide-test-file-naming"></a>
+ Par défaut : à `init_test.lua` côté du plugin `init.lua`
+ Plusieurs fichiers de test par plugin : tout fichier correspondant `*_test.lua` est découvert
+ Exemples : `init_test.lua`, `parsing_test.lua`, `discovery_test.lua`

### Données de test : `_testdata/`
<a name="sbomgen-plugin-testing-guide-test-data-testdata"></a>

 Les données de test se `_testdata/` trouvent à côté du plugin. Le trait de soulignement principal est une convention qui permet de séparer visuellement les appareils de la source du plugin ; la `plugin test` commande n'est pas abordée `_testdata/` lors de la recherche de `*_test.lua` fichiers, de sorte que les appareils ne sont jamais confondus avec des fichiers de test. 

 Les fichiers de test font référence aux appareils avec des chemins relatifs : 

```
local result = testing.scan_directory("_testdata/include/curl")
```

 Les chemins sont résolus par rapport au répertoire contenant le fichier de test. 

## API `testing.*`
<a name="sbomgen-plugin-testing-guide-the-testing-api"></a>

### Fonctions de numérisation
<a name="sbomgen-plugin-testing-guide-scan-functions"></a>

 Chaque fonction de numérisation crée un artefact, exécute le pipeline de découverte → de collecte du plugin et renvoie les résultats. L'auteur du test ne crée jamais manuellement d'artefacts, de bus d'événements ou de registres. 

```
-- Scan a directory of test fixtures (most common)
local result = testing.scan_directory("_testdata/curl")

-- Alias for scan_directory (archives use the same backend)
local result = testing.scan_archive("_testdata/app.tar.gz")

-- Scan as a localhost artifact
local result = testing.scan_localhost("_testdata/curl")

-- Scan a compiled binary
local result = testing.scan_binary("_testdata/binaries/curl")

-- Scan a mounted volume
local result = testing.scan_volume("_testdata/volume-root")

-- Scan a container image tarball
local result = testing.scan_container("_testdata/images/alpine.tar")
```

 Chaque fonction de numérisation : 
+ Crée un nouvel artefact pour chaque appel (aucune fuite d'état entre les appels)
+ Charge uniquement la paire découverte et collection du plugin actuel
+ Renvoie un tableau de résultats

### Tableau des résultats
<a name="sbomgen-plugin-testing-guide-result-table"></a>

```
result.findings              -- array of finding tables
result.findings[1].name      -- package name (string)
result.findings[1].version   -- package version (string)
result.findings[1].purl      -- package URL (string)
result.findings[1].component_type -- component type (string)
result.findings[1].properties    -- table<string, string>
result.findings[1].children      -- array of nested finding tables (same shape)
```

### Assertions
<a name="sbomgen-plugin-testing-guide-assertions"></a>

```
-- Equality
testing.assert_equals(expected, actual, message?)
testing.assert_not_equals(expected, actual, message?)

-- Truthiness
testing.assert_true(value, message?)
testing.assert_false(value, message?)

-- Nil checks
testing.assert_nil(value, message?)
testing.assert_not_nil(value, message?)

-- String
testing.assert_contains(haystack, needle, message?)
testing.assert_matches(string, pattern, message?)

-- Tables
testing.assert_length(table, expected_length, message?)

-- Control flow
testing.fail(message)    -- immediately fail the current test
testing.skip(message)    -- skip the current test (not a failure)
```

### `sbomgen.*`API standard
<a name="sbomgen-plugin-testing-guide-standard-sbomgen-api"></a>

 L'`sbomgen.*`API complète (E/S de fichiers, regex, informations système, journalisation, etc.) est disponible dans les fichiers de test, comme dans les plugins de production. Cependant, `sbomgen.*` les fonctions qui nécessitent un artefact (par exemple,`sbomgen.read_file()`) ne fonctionnent que dans un `testing.scan_*` rappel ; elles ne sont pas disponibles au niveau supérieur d'une fonction de test. 

## Exécution de tests
<a name="sbomgen-plugin-testing-guide-running-tests"></a>

```
# Run all tests under a plugin directory
inspector-sbomgen plugin test --path ./my-plugins

# Filter by regex pattern
inspector-sbomgen plugin test --path ./my-plugins --run curl

# Verbose output (show each test name and result)
inspector-sbomgen plugin test --path ./my-plugins -v

# Stop on the first failing test
inspector-sbomgen plugin test --path ./my-plugins --fail-fast
```

 L'`--path`indicateur accepte un répertoire racine du plugin (contenant `discovery/` and/or `collection/`) ou un répertoire unique de l'écosystème (détecté automatiquement). La commande sort d'une valeur différente de zéro en cas d'échec d'un test. 

### Format de sortie
<a name="sbomgen-plugin-testing-guide-output-format"></a>

 Avec`-v`, chaque test imprime une `=== RUN` ligne et une ligne de résultat (`--- PASS``--- FAIL`, ou`--- SKIP`). Sans`-v`, seuls les tests qui échouent sont imprimés. Une ligne récapitulative est imprimée à la fin : 

```
=== RUN   curl/discovery/init_test/test_discovers_libcurl_header
--- PASS: curl/discovery/init_test/test_discovers_libcurl_header (0.04s)
=== RUN   curl/discovery/init_test/test_discovers_curl_binary_unix
--- PASS: curl/discovery/init_test/test_discovers_curl_binary_unix (0.04s)
=== RUN   curl/discovery/init_test/test_no_findings_for_unrelated_files
--- PASS: curl/discovery/init_test/test_no_findings_for_unrelated_files (0.04s)
ok    3 tests passed
```

## Tester les aides aux plugins
<a name="sbomgen-plugin-testing-guide-testing-plugin-helpers"></a>

 Le fichier de test est chargé dans la même machine virtuelle Lua que celle du `init.lua` plugin. Les fonctions globales définies dans le plugin sont appelables à partir de tests. Pour tester les fonctions d'assistance, exposez-les sous forme de variables globales ou dans une table de modules : 

```
-- init.lua
M = {}
function M.parse_version(raw)
    return string.match(raw, "(%d+%.%d+%.%d+)")
end

function collect(file_path)
    local ver = M.parse_version(...)
    -- ...
end
```

```
-- init_test.lua
function test_parse_version_extracts_semver()
    testing.assert_equals("1.2.3", M.parse_version("curl/1.2.3"))
end

function test_parse_version_returns_nil_for_garbage()
    testing.assert_nil(M.parse_version("not-a-version"))
end
```

 Les fonctions déclarées `local` dans ne `init.lua` sont pas visibles dans le fichier de test. Il s'agit du scoping Lua standard. 

## Comportement et invariants
<a name="sbomgen-plugin-testing-guide-behavior-and-invariants"></a>

### VM partagée, état partagé
<a name="sbomgen-plugin-testing-guide-shared-vm-shared-state"></a>

 Les fonctions de test au sein d'un même fichier partagent une machine virtuelle Lua. Une variable globale définie dans une `test_*` fonction est visible pour les fonctions suivantes. Si deux fonctions définissent la même valeur globale, la seconde remplace la première. Chaque test doit être autonome et ne pas dépendre de l'état des autres tests. 

### Ordre d'exécution non déterministe
<a name="sbomgen-plugin-testing-guide-non-deterministic-execution-order"></a>

 Les fonctions de test sont découvertes en itérant la table globale de Lua, qui utilise un ordre basé sur le hachage. **Il n'est pas garanti que les tests s'exécutent dans l'ordre dans lequel ils ont été définis.** N'écrivez pas de tests qui dépendent de l'ordre d'exécution. 

### Artefact frais par appel de numérisation
<a name="sbomgen-plugin-testing-guide-fresh-artifact-per-scan-call"></a>

 Chaque appel à `testing.scan_directory()` (ou toute autre fonction de numérisation) crée un artefact complètement nouveau. Aucun état n'est transmis entre les appels de scan au sein d'un test ou entre les tests. 

### Chargement du plugin
<a name="sbomgen-plugin-testing-guide-plugin-loading"></a>

 Les plugins sont chargés une fois par test, et non une fois par fichier de test. Le lanceur de tests charge tous les plugins à partir du système de fichiers fourni, puis associe chaque fichier de test à la machine virtuelle de plug-in correspondante par phase, plate-forme, catégorie et écosystème. 

### Comportement d'assertion
<a name="sbomgen-plugin-testing-guide-assertion-behavior"></a>

 Lorsqu'une assertion échoue, l'échec est enregistré mais la fonction de test continue de s'exécuter. Les assertions et instructions suivantes sont toujours exécutées. Si plusieurs assertions échouent au cours du même test, l'échec le **plus récent** est le message indiqué dans le résumé ; les échecs antérieurs sont remplacés. Pour arrêter un test lors de son premier échec, revenez de la fonction après l'échec de l'assertion (ou utilisez-la `testing.fail()` dans un conditionnel). 

## Limitations
<a name="sbomgen-plugin-testing-guide-limitations"></a>
+ **`local`les fonctions ne sont pas testables.** Seules les fonctions globales de `init.lua` sont visibles dans le fichier de test. Exposez les assistants via une table de modules s'ils ont besoin d'être testés.
+ **Aucun `sbomgen.*` fichier I/O en dehors des appels de numérisation.** Des fonctions comme `sbomgen.read_file()` celles-ci nécessitent un contexte d'artefact, qui n'existe que dans `testing.scan_*` les appels.
+ **Aucun crochet lié au cycle de vie.** Il n'y a pas `before_each``after_each`,`setup`, ou`teardown`. Chaque fonction de test gère son propre état.
+ **Aucun délai d'attente pour le test.** Une fonction de test qui tourne en boucle indéfiniment bloquera le coureur.
+ **Aucun rapport de couverture.** Il n'existe aucun moyen de mesurer quelles lignes `init.lua` ont été exercées.
+ **Pas de points de repère.** Le framework de test ne prend pas en charge les benchmarks de performance.

## Responsabilités du développeur
<a name="sbomgen-plugin-testing-guide-developer-responsibilities"></a>

### Lors de l'écriture d'un nouveau plugin Lua
<a name="sbomgen-plugin-testing-guide-when-writing-a-new-lua-plugin"></a>
+ Créez à `init_test.lua` côté de votre `init.lua`
+ Créez `_testdata/` avec un minimum de fonctionnalités qui mettent en œuvre la logique de votre plugin
+ Rédiger `test_*` des fonctions couvrant : la détection réussie, l'extraction de version, les cas extrêmes et les scénarios de non-correspondance
+ Exécutez les tests localement avant de les soumettre

### Directives relatives aux données de test
<a name="sbomgen-plugin-testing-guide-test-data-guidelines"></a>
+ Réduisez le nombre de fixations au minimum : utilisez le plus petit fichier qui exerce le comportement
+ Évitez de valider de gros fichiers binaires `_testdata/` alors qu'un petit dispositif de texte suffirait
+ Chaque plugin `_testdata/` doit être autonome : aucune référence à des fichiers situés en dehors du répertoire du plugin