

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Leitfaden zum Testen von Plugins
<a name="sbomgen-plugin-testing-guide"></a>

 Plugin-Autoren schreiben und testen Lua-Plugins vollständig in Lua — es ist keine Go-Toolchain erforderlich. Die Tests befinden sich zusammen mit dem Plugin unter `init_test.lua` und werden über den Befehl ausgeführt. `inspector-sbomgen plugin test` 

 Allgemeine Informationen zur Plugin-Erstellung finden Sie im. [Leitfaden für Plugin-Entwickler](sbomgen-plugin-developer-guide.md) Den vollständigen Funktionskatalog (einschließlich der `testing.*` API) finden Sie unter[Plugin-API-Referenz](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
```

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

### 1. Erstellen Sie eine Testdatei
<a name="sbomgen-plugin-testing-guide-1-create-a-test-file"></a>

 Platziere es `init_test.lua` neben deinem Plugin`init.lua`: 

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

### 2. Schreiben Sie Testfunktionen
<a name="sbomgen-plugin-testing-guide-2-write-test-functions"></a>

 Jede globale Funktion, die mit beginnt, `test_` wird erkannt und ausgeführt: 

```
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. Tests ausführen
<a name="sbomgen-plugin-testing-guide-3-run-tests"></a>

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

## Verzeichnis-Layout
<a name="sbomgen-plugin-testing-guide-directory-layout"></a>

### Struktur des Plugins
<a name="sbomgen-plugin-testing-guide-plugin-structure"></a>

 Testdateien und Testdaten befinden sich zusammen mit dem 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
```

### Benennung der Testdateien
<a name="sbomgen-plugin-testing-guide-test-file-naming"></a>
+ Standard: `init_test.lua` neben den Plugins `init.lua`
+ Mehrere Testdateien pro Plugin: Jede passende Datei `*_test.lua` wird erkannt
+ Beispiele: `init_test.lua`, `parsing_test.lua`, `discovery_test.lua`.

### Testdaten: `_testdata/`
<a name="sbomgen-plugin-testing-guide-test-data-testdata"></a>

 Die Testdaten befinden sich `_testdata/` neben dem Plugin. Der führende Unterstrich ist eine Konvention, die Fixtures visuell von der Plugin-Quelle trennt. Der `plugin test` Befehl wird `_testdata/` bei der Suche nach `*_test.lua` Dateien nicht angezeigt, sodass Fixtures niemals mit Testdateien verwechselt werden. 

 Testdateien verweisen auf Fixtures mit relativen Pfaden: 

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

 Pfade werden relativ zu dem Verzeichnis aufgelöst, das die Testdatei enthält. 

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

### Funktionen scannen
<a name="sbomgen-plugin-testing-guide-scan-functions"></a>

 Jede Scanfunktion erzeugt ein Artefakt, führt die Discovery → Collection-Pipeline des Plugins aus und gibt Ergebnisse zurück. Der Testautor erstellt Artefakte, Event-Busse oder Register niemals manuell. 

```
-- 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")
```

 Jede Scanfunktion: 
+ Erzeugt für jeden Anruf ein neues Artefakt (keine Statuslecks zwischen Aufrufen)
+ Lädt nur das Discovery \+ Collection-Paar des aktuellen Plugins
+ Gibt eine Ergebnistabelle zurück

### Ergebnistabelle
<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)
```

### Assertionen
<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.*`Standard-API
<a name="sbomgen-plugin-testing-guide-standard-sbomgen-api"></a>

 Die vollständige `sbomgen.*` API (Datei-I/O, Regex, Systeminformationen, Protokollierung usw.) ist in Testdateien verfügbar, genau wie in Produktions-Plugins. `sbomgen.*`Funktionen, die ein Artefakt benötigen (z. B.`sbomgen.read_file()`), funktionieren jedoch nur innerhalb eines `testing.scan_*` Callbacks — sie sind nicht auf der obersten Ebene einer Testfunktion verfügbar. 

## Ausführen von 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
```

 Das `--path` Flag akzeptiert ein Plugin-Stammverzeichnis (enthält `discovery/` and/or `collection/`) oder ein einzelnes Ökosystemverzeichnis (automatisch erkannt). Der Befehl wird mit einem Wert ungleich Null beendet, wenn ein Test fehlschlägt. 

### Ausgabeformat
<a name="sbomgen-plugin-testing-guide-output-format"></a>

 Mit `-v` druckt jeder Test eine `=== RUN` Zeile und eine Ergebniszeile (`--- PASS`,`--- FAIL`, oder`--- SKIP`). Ohne werden `-v` nur fehlgeschlagene Tests gedruckt. Am Ende wird eine Übersichtszeile gedruckt: 

```
=== 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
```

## Plugin-Helfer testen
<a name="sbomgen-plugin-testing-guide-testing-plugin-helpers"></a>

 Die Testdatei wird in dieselbe Lua-VM geladen wie die des `init.lua` Plugins. Im Plugin definierte globale Funktionen können von Tests aus aufgerufen werden. Um Hilfsfunktionen zu testen, stellen Sie sie als globale Funktionen oder in einer Modultabelle zur Verfügung: 

```
-- 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
```

 `local`In deklarierte Funktionen `init.lua` sind für die Testdatei nicht sichtbar. Das ist Standard-Lua-Scoping. 

## Verhalten und Invarianten
<a name="sbomgen-plugin-testing-guide-behavior-and-invariants"></a>

### Gemeinsam genutzte VM, gemeinsam genutzter Status
<a name="sbomgen-plugin-testing-guide-shared-vm-shared-state"></a>

 Testfunktionen innerhalb einer einzigen Datei teilen sich eine Lua-VM. Eine in einer `test_*` Funktion festgelegte globale Variable ist für nachfolgende Funktionen sichtbar. Wenn zwei Funktionen dieselbe globale Definition definieren, überschreibt die zweite die erste. Jeder Test sollte eigenständig sein und nicht vom Status anderer Tests abhängen. 

### Nicht deterministische Ausführungsreihenfolge
<a name="sbomgen-plugin-testing-guide-non-deterministic-execution-order"></a>

 Testfunktionen werden erkannt, indem die globale Tabelle von Lua iteriert wird, die eine Hash-basierte Reihenfolge verwendet. **Es kann nicht garantiert werden, dass Tests in der Reihenfolge ausgeführt werden, in der sie definiert sind.** Schreiben Sie keine Tests, die von der Ausführungsreihenfolge abhängen. 

### Neues Artefakt pro Scanaufruf
<a name="sbomgen-plugin-testing-guide-fresh-artifact-per-scan-call"></a>

 Jeder Aufruf `testing.scan_directory()` (oder jede Scanfunktion) erzeugt ein völlig neues Artefakt. Es gibt keinen Status zwischen Scanaufrufen innerhalb eines Tests oder zwischen Tests. 

### Das Plugin wird geladen
<a name="sbomgen-plugin-testing-guide-plugin-loading"></a>

 Plugins werden einmal pro Testlauf geladen, nicht einmal pro Testdatei. Der Test-Runner lädt alle Plugins aus dem bereitgestellten Dateisystem und ordnet dann jede Testdatei der entsprechenden Plugin-VM nach Phase, Plattform, Kategorie und Ökosystem zu. 

### Verhalten der Assertion
<a name="sbomgen-plugin-testing-guide-assertion-behavior"></a>

 Wenn eine Assertion fehlschlägt, wird der Fehler aufgezeichnet, aber die Testfunktion wird weiterhin ausgeführt — nachfolgende Assertionen und Anweisungen werden weiterhin ausgeführt. Wenn mehr als eine Assertion im selben Test fehlschlägt, ist der **jüngste** Fehler die in der Zusammenfassung gemeldete Meldung. Frühere Fehler werden überschrieben. Um einen Test beim ersten Fehler zu beenden, kehren Sie nach der fehlgeschlagenen Assertion von der Funktion zurück (oder verwenden Sie die Funktion `testing.fail()` innerhalb einer Bedingung). 

## Einschränkungen
<a name="sbomgen-plugin-testing-guide-limitations"></a>
+ **`local`Funktionen sind nicht testbar.** Nur globale Funktionen von `init.lua` sind für die Testdatei sichtbar. Stellen Sie Helfer über eine Modultabelle zur Verfügung, wenn sie getestet werden müssen.
+ **Es werden keine I/O externen Scan-Aufrufe für `sbomgen.*` Dateien angezeigt.** Funktionen wie `sbomgen.read_file()` benötigen einen Artefaktkontext, der nur innerhalb von `testing.scan_*` Aufrufen existiert.
+ **Keine Lifecycle-Hooks.** Es gibt kein `before_each``after_each`,`setup`, oder`teardown`. Jede Testfunktion verwaltet ihren eigenen Status.
+ **Kein Test-Timeout.** Eine Testfunktion, die für immer wiederholt wird, lässt den Runner hängen.
+ **Keine Berichterstattung.** Es gibt keine Möglichkeit zu messen, welche Linien trainiert `init.lua` wurden.
+ **Es gibt keine Benchmarks.** Das Testframework unterstützt keine Leistungsbenchmarks.

## Verantwortlichkeiten des Entwicklers
<a name="sbomgen-plugin-testing-guide-developer-responsibilities"></a>

### Beim Schreiben eines neuen Lua-Plugins
<a name="sbomgen-plugin-testing-guide-when-writing-a-new-lua-plugin"></a>
+ Erstelle `init_test.lua` neben deinem `init.lua`
+ Erstellen Sie `_testdata/` mit minimalen Vorrichtungen, die die Logik Ihres Plugins trainieren
+ Schreiben Sie `test_*` Funktionen, die Folgendes abdecken: erfolgreiche Erkennung, Versionsextraktion, Grenzfälle und Szenarien ohne Übereinstimmung
+ Führen Sie Tests vor dem Absenden lokal aus

### Richtlinien für Testdaten
<a name="sbomgen-plugin-testing-guide-test-data-guidelines"></a>
+ Halten Sie die Fixtures auf ein Minimum — verwenden Sie die kleinste Datei, die das Verhalten trainiert
+ Vermeiden Sie es, große Binärdateien zu speichern, `_testdata/` wenn eine kleine Textfixierung ausreichen würde
+ Jedes Plugin `_testdata/` sollte eigenständig sein — keine Verweise auf Dateien außerhalb des Plugin-Verzeichnisses