View a markdown version of this page

Guía de pruebas de complementos - Amazon Inspector

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.lua lado del plugin init.lua

  • Varios archivos de prueba por plugin: *_test.lua se descubre cualquier archivo que coincida

  • Ejemplos: init_test.lua, parsing_test.lua y discovery_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 de init.lua son 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 estas sbomgen.read_file() requieren un contexto de artefacto, que solo existe dentro de testing.scan_* las llamadas.

  • Sin ganchos durante el ciclo de vida. No haybefore_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.lua se 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.lua junto a tu init.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