Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Guida al test dei plugin
Gli autori dei plugin scrivono e testano i plugin Lua interamente in Lua, senza bisogno della toolchain Go. I test sono collocati insieme al plugin sotto init_test.lua ed eseguiti tramite il comando. inspector-sbomgen plugin test
Per la creazione generale dei plugin, consulta. Guida per sviluppatori di plugin Per il catalogo completo delle funzioni (inclusa l'testing.*API), consultaRiferimento all'API del plugin.
-- 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
1. Crea un file di test
Posiziona init_test.lua accanto a quello del tuo plugininit.lua:
my-plugin/ ├── discovery/cross-platform/extra-ecosystems/curl/ │ ├── init.lua │ ├── init_test.lua │ └── _testdata/ │ └── include/curl/curlver.h
2. Scrivi funzioni di test
Qualsiasi funzione globale che inizia con test_ viene rilevata ed eseguita:
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. Esegui test
inspector-sbomgen plugin test --path ./my-plugin
Layout delle directory
Struttura del plugin
I file di test e i dati di test si trovano insieme al 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
Denominazione dei file di test
-
Predefinito:
init_test.luaaccanto al plugininit.lua -
Più file di test per plugin:
*_test.luaviene rilevata qualsiasi corrispondenza tra file -
Esempi:
init_test.lua,parsing_test.lua,discovery_test.lua
Dati di test: _testdata/
I dati di test si _testdata/ trovano accanto al plugin. La caratteristica principale è una convenzione che mantiene le fixture visivamente separate dalla sorgente del plugin; il plugin test comando non viene utilizzato _testdata/ durante la ricerca di *_test.lua file, quindi le fixture non vengono mai scambiate per file di test.
I file di test fanno riferimento a dispositivi con percorsi relativi:
local result = testing.scan_directory("_testdata/include/curl")
I percorsi vengono risolti in relazione alla directory contenente il file di test.
L'API testing.*
Funzioni di scansione
Ogni funzione di scansione crea un artefatto, esegue la pipeline discovery → collection del plugin e restituisce i risultati. L'autore del test non crea mai manualmente artefatti, bus di eventi o registri.
-- 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")
Ogni funzione di scansione:
-
Crea un nuovo artefatto per ogni chiamata (nessuna perdita di stato tra le chiamate)
-
Carica solo la coppia di raccolta discovery+ del plugin corrente
-
Restituisce una tabella dei risultati
Tabella dei risultati
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)
Asserzioni
-- 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
L'sbomgen.*API completa (file I/O, regex, informazioni di sistema, registrazione, ecc.) è disponibile nei file di test, come nei plugin di produzione. Tuttavia, sbomgen.* le funzioni che richiedono un artefatto (ad esempiosbomgen.read_file()) funzionano solo all'interno di un testing.scan_* callback: non sono disponibili al livello superiore di una funzione di test.
Esecuzione di test.
# 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
Il --path flag accetta una directory principale del plug-in (contenente discovery/ and/or collection/) o una singola directory dell'ecosistema (rilevata automaticamente). Il comando esce da un valore diverso da zero se un test fallisce.
Formato di output
Con-v, ogni test stampa una === RUN riga e una riga di risultato (--- PASS--- FAIL, o--- SKIP). Senza-v, vengono stampati solo i test non riusciti. Alla fine viene stampata una riga riassuntiva:
=== 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
Testare gli helper dei plugin
Il file di test viene caricato nella stessa macchina virtuale Lua del plugin. init.lua Le funzioni globali definite nel plugin sono richiamabili dai test. Per testare le funzioni di supporto, esponile come globali o in una tabella di moduli:
-- 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
Le funzioni dichiarate local in non init.lua sono visibili nel file di test. Questo è lo scoping Lua standard.
Comportamento e invarianti
VM condivisa, stato condiviso
Le funzioni di test all'interno di un singolo file condividono una VM Lua. Una variabile globale impostata in una test_* funzione è visibile alle funzioni successive. Se due funzioni definiscono lo stesso globale, la seconda sovrascrive la prima. Ogni test deve essere autonomo e non dipendere dallo stato degli altri test.
Ordine di esecuzione non deterministico
Le funzioni di test vengono scoperte iterando la tabella globale di Lua, che utilizza l'ordinamento basato su hash. Non è garantito che i test vengano eseguiti nell'ordine in cui sono stati definiti. Non scrivete test che dipendono dall'ordine di esecuzione.
Nuovi artefatti per ogni chiamata di scansione
Ogni chiamata a testing.scan_directory() (o qualsiasi funzione di scansione) crea un artefatto completamente nuovo. Non viene rilevato alcuno stato tra le chiamate di scansione all'interno di un test o tra i test.
Caricamento del plugin
I plugin vengono caricati una volta per esecuzione di test, non una volta per file di test. Il test runner carica tutti i plugin dal filesystem fornito, quindi abbina ogni file di test alla macchina virtuale del plug-in corrispondente per fase, piattaforma, categoria ed ecosistema.
Comportamento di asserzione
Quando un'asserzione fallisce, l'errore viene registrato ma la funzione di test continua a essere eseguita e le asserzioni e le istruzioni successive continuano a essere eseguite. Se più di un'asserzione fallisce nello stesso test, l'errore più recente è il messaggio riportato nel riepilogo; gli errori precedenti vengono sovrascritti. Per interrompere un test al primo errore, tornate dalla funzione dopo l'asserzione fallita (o testing.fail() usatela all'interno di un condizionale).
Limitazioni
-
localle funzioni non sono testabili. Solo le funzioni globali diinit.luasono visibili nel file di test. Esponete gli helper tramite una tabella di moduli se hanno bisogno di essere testati. -
Nessun
sbomgen.*file I/O al di fuori delle chiamate di scansione. Funzioni come quellesbomgen.read_file()richiedono un contesto di artefatti, che esiste solo all'internotesting.scan_*delle chiamate. -
Nessun aggancio al ciclo di vita. Non c'è
before_each,after_each,setupo.teardownOgni funzione di test gestisce il proprio stato. -
Nessun timeout per il test. Una funzione di test che si ripete per sempre bloccherà il runner.
-
Nessuna segnalazione sulla copertura. Non c'è modo di misurare quali linee
init.luasono state esercitate. -
Nessun benchmark. Il framework di test non supporta i benchmark delle prestazioni.
Responsabilità degli sviluppatori
Quando si scrive un nuovo plugin Lua
-
Crea
init_test.luaaccanto al tuoinit.lua -
Crea
_testdata/con dispositivi minimi che esercitano la logica del tuo plugin -
Scrivi
test_*funzioni che coprono: rilevamento riuscito, estrazione della versione, casi limite e scenari senza corrispondenza -
Esegui i test localmente prima di inviarli
Linee guida sui dati dei test
-
Riduci al minimo le apparecchiature: utilizza il file più piccolo che esercita il comportamento
-
Evita di inserire file binari di grandi dimensioni in
_testdata/cui sarebbe sufficiente una piccola finestra di testo -
Ogni plugin
_testdata/dovrebbe essere autonomo, senza riferimenti a file al di fuori della directory dei plugin