Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Guía de pruebas de complementos
Los autores de complementos escriben y prueban los complementos de Lua completamente en Lua, sin necesidad de usar la cadena de herramientas Go. Las pruebas se ubican junto con el complemento init_test.lua y se ejecutan mediante el comando. inspector-sbomgen plugin test
Para obtener información general sobre la creación de complementos, consulte la. Guía para desarrolladores de complementos Para ver el catálogo completo de funciones (incluida la testing.* API), consulta laReferencia de la API de complementos.
-- 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 (Inicio rápido)
1. Cree un archivo de prueba
init_test.luaColócalo junto al de tu plugininit.lua:
my-plugin/ ├── discovery/cross-platform/extra-ecosystems/curl/ │ ├── init.lua │ ├── init_test.lua │ └── _testdata/ │ └── include/curl/curlver.h
2. Escribe funciones de prueba
test_Se descubre y ejecuta cualquier función global que comience por:
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. Ejecute pruebas
inspector-sbomgen plugin test --path ./my-plugin
Diseño del directorio
Estructura del plugin
Los archivos de prueba y los datos de prueba se ubican en el mismo lugar que el complemento:
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
Nombre de los archivos de prueba
-
Predeterminado: al
init_test.lualado del plugininit.lua -
Varios archivos de prueba por plugin:
*_test.luase descubre cualquier archivo que coincida -
Ejemplos:
init_test.lua,parsing_test.luaydiscovery_test.lua
Datos de prueba: _testdata/
Los datos de prueba se _testdata/ encuentran junto al complemento. El subrayado inicial es una convención que mantiene los dispositivos separados visualmente de la fuente del complemento; el plugin test comando no se utiliza _testdata/ cuando se buscan *_test.lua archivos, por lo que los dispositivos nunca se confunden con los archivos de prueba.
Los archivos de prueba hacen referencia a dispositivos con rutas relativas:
local result = testing.scan_directory("_testdata/include/curl")
Las rutas se resuelven en relación con el directorio que contiene el archivo de prueba.
La API de testing.*
Funciones de escaneo
Cada función de escaneo crea un artefacto, ejecuta el proceso de descubrimiento → recolección del complemento y devuelve los hallazgos. El autor de la prueba nunca crea artefactos, buses de eventos o registros manualmente.
-- 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")
Cada función de escaneo:
-
Crea un artefacto nuevo para cada llamada (sin pérdidas de estado entre llamadas)
-
Carga solo el par Discovery + Collection del plugin actual
-
Devuelve una tabla de resultados
Tabla de resultados
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)
Aserciones
-- 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 estándar
La sbomgen.* API completa (E/S de archivos, expresiones regulares, información del sistema, registro, etc.) está disponible en los archivos de prueba, al igual que en los complementos de producción. Sin embargo, sbomgen.* las funciones que requieren un artefacto (por ejemplosbomgen.read_file()) solo funcionan dentro de una testing.scan_* devolución de llamada; no están disponibles en el nivel superior de una función de prueba.
Ejecución de pruebas
# 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
La --path bandera acepta un directorio raíz de complementos (que contiene discovery/ and/or collection/) o un directorio de ecosistema único (detectado automáticamente). El comando se cierra con un valor distinto de cero si alguna prueba falla.
Formato de salida
Con-v, cada prueba imprime una === RUN línea y una línea de resultado (--- PASS--- FAIL, o--- SKIP). Sin ellas-v, solo se imprimen las pruebas fallidas. Al final se imprime una línea de resumen:
=== 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
Probando los ayudantes de complementos
El archivo de prueba se carga en la misma máquina virtual de Lua que el plugin. init.lua Las funciones globales definidas en el complemento se pueden invocar desde las pruebas. Para probar las funciones auxiliares, expóngalas como globales o en una tabla de módulos:
-- 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
Las funciones declaradas local en no init.lua están visibles en el archivo de prueba. Este es el alcance estándar de Lua.
Comportamiento e invariantes
VM compartida, estado compartido
Las funciones de prueba dentro de un único archivo comparten una máquina virtual Lua. Una variable global establecida en una test_* función es visible para las funciones subsiguientes. Si dos funciones definen la misma global, la segunda sobrescribe a la primera. Cada prueba debe ser independiente y no depender del estado de otras pruebas.
Orden de ejecución no determinista
Las funciones de prueba se descubren iterando la tabla global de Lua, que utiliza un orden basado en hash. No se garantiza que las pruebas se ejecuten en el orden en que están definidas. No escriba pruebas que dependan del orden de ejecución.
Artefacto nuevo por llamada de escaneo
Cada llamada a testing.scan_directory() (o cualquier función de escaneo) crea un artefacto completamente nuevo. No se transmite ningún estado entre las llamadas de escaneo dentro de una prueba o entre las pruebas.
Carga del plugin
Los complementos se cargan una vez por ejecución de prueba, no una vez por archivo de prueba. El ejecutor de pruebas carga todos los complementos del sistema de archivos proporcionado y, a continuación, hace coincidir cada archivo de prueba con la máquina virtual del complemento correspondiente por fase, plataforma, categoría y ecosistema.
Comportamiento de las aserciones
Cuando una aserción falla, se registra el error, pero la función de prueba continúa ejecutándose; las aserciones y sentencias subsiguientes se siguen ejecutando. Si más de una afirmación falla en la misma prueba, el error más reciente es el mensaje indicado en el resumen; los errores anteriores se sobrescriben. Para detener una prueba cuando se produce el primer error, regresa de la función después de la afirmación fallida (o utilízala testing.fail() dentro de una condicional).
Limitaciones
-
locallas funciones no se pueden comprobar. Solo las funciones globales deinit.luason visibles en el archivo de prueba. Exponga a los ayudantes a través de una tabla de módulos si necesitan probarlos. -
No hay ningún
sbomgen.*archivo I/O fuera de las llamadas de escaneo. Funciones como estassbomgen.read_file()requieren un contexto de artefacto, que solo existe dentro detesting.scan_*las llamadas. -
Sin ganchos durante el ciclo de vida. No hay
before_each,after_eachsetup, oteardown. Cada función de prueba gestiona su propio estado. -
No hay tiempo de espera de la prueba. Una función de prueba que se repite indefinidamente bloqueará el corredor.
-
No hay informes de cobertura. No hay forma de medir qué líneas
init.luase ejercieron. -
No hay puntos de referencia. El marco de pruebas no admite los puntos de referencia de rendimiento.
Responsabilidades del desarrollador
Al escribir un nuevo complemento de Lua
-
Crea
init_test.luajunto a tuinit.lua -
Crea
_testdata/con accesorios mínimos que ejerciten la lógica de tu complemento -
Escribe
test_*funciones que abarquen: la detección correcta, la extracción de versiones, los casos extremos y los escenarios de no coincidencia -
Ejecute las pruebas localmente antes de enviarlas
Directrices sobre los datos de las pruebas
-
Mantenga los dispositivos al mínimo: utilice el archivo más pequeño que ejercite el comportamiento
-
Evite almacenar archivos binarios grandes
_testdata/cuando bastaría con un pequeño elemento de texto -
Cada complemento
_testdata/debe ser independiente, sin referencias a archivos fuera del directorio de complementos