As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Guia de teste de plug-ins
Os autores de plug-ins escrevem e testam plug-ins Lua inteiramente em Lua, sem a necessidade de uma cadeia de ferramentas Go. Os testes são colocados junto com o plug-in abaixo init_test.lua e executados por meio do inspector-sbomgen plugin test comando.
Para a criação geral de plug-ins, consulte o. Guia do desenvolvedor de plug-ins Para ver o catálogo completo de funções (incluindo a testing.* API), consulte Referência da API de plug-in o.
-- 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
Início rápido
1. Crie um arquivo de teste
Coloque init_test.lua ao lado do seu plugininit.lua:
my-plugin/ ├── discovery/cross-platform/extra-ecosystems/curl/ │ ├── init.lua │ ├── init_test.lua │ └── _testdata/ │ └── include/curl/curlver.h
2. Escreva funções de teste
Qualquer função global que comece com test_ é descoberta e executada:
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. Execute testes
inspector-sbomgen plugin test --path ./my-plugin
Layout do diretório
Estrutura do plugin
Os arquivos de teste e os dados de teste são co-localizados com o plug-in:
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
Nomeação do arquivo de teste
-
Padrão: ao
init_test.lualado do plugininit.lua -
Vários arquivos de teste por plug-in: qualquer arquivo correspondente
*_test.luaé descoberto -
Exemplos:
init_test.lua,parsing_test.lua,discovery_test.lua
Dados do teste: _testdata/
Os dados de teste estão _testdata/ ao lado do plug-in. O sublinhado principal é uma convenção que mantém os acessórios visualmente separados da fonte do plug-in; o plugin test comando não aparece _testdata/ ao pesquisar *_test.lua arquivos, portanto, os acessórios nunca são confundidos com arquivos de teste.
Arquivos de teste referenciam luminárias com caminhos relativos:
local result = testing.scan_directory("_testdata/include/curl")
Os caminhos são resolvidos em relação ao diretório que contém o arquivo de teste.
A API do testing.*
Funções de digitalização
Cada função de escaneamento cria um artefato, executa o pipeline de descoberta → coleta do plug-in e retorna as descobertas. O autor do teste nunca cria manualmente artefatos, barramentos de eventos ou registros.
-- 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 função de digitalização:
-
Cria um novo artefato para cada chamada (sem vazamentos de estado entre as chamadas)
-
Carrega somente o par de descoberta + coleção do plugin atual
-
Retorna uma tabela de resultados
Tabela 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)
Asserções
-- 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 padrão
A sbomgen.* API completa (E/S de arquivo, regex, informações do sistema, registro etc.) está disponível em arquivos de teste, assim como nos plug-ins de produção. No entanto, sbomgen.* funções que exigem um artefato (por exemplo,sbomgen.read_file()) só funcionam dentro de um testing.scan_* retorno de chamada — elas não estão disponíveis no nível superior de uma função de teste.
Execução de testes
# 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
O --path sinalizador aceita um diretório raiz do plug-in (contendo discovery/ and/or collection/) ou um único diretório de ecossistema (detectado automaticamente). O comando sai de forma diferente de zero se algum teste falhar.
Formato de saída
Com-v, cada teste imprime uma === RUN linha e uma linha de resultado (--- PASS,--- FAIL, ou--- SKIP). Sem-v, apenas testes falhos são impressos. Uma linha de resumo é impressa no final:
=== 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
Testando auxiliares de plug-ins
O arquivo de teste é carregado na mesma Lua VM que a do init.lua plug-in. As funções globais definidas no plug-in podem ser chamadas a partir de testes. Para testar funções auxiliares, exponha-as como globais ou em uma tabela 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
As funções init.lua declaradas local em não são visíveis no arquivo de teste. Esse é o escopo padrão de Lua.
Comportamento e invariantes
VM compartilhada, estado compartilhado
Funções de teste em um único arquivo compartilham uma Lua VM. Uma variável global definida em uma test_* função é visível para as funções subsequentes. Se duas funções definem o mesmo global, a segunda substitui a primeira. Cada teste deve ser independente e não depender do estado de outros testes.
Ordem de execução não determinística
As funções de teste são descobertas pela iteração da tabela global de Lua, que usa ordenação baseada em hash. Não é garantido que os testes sejam executados na ordem em que foram definidos. Não escreva testes que dependam da ordem de execução.
Novo artefato por chamada de escaneamento
Cada chamada para testing.scan_directory() (ou qualquer função de escaneamento) cria um artefato completamente novo. Não há nenhum estado transmitido entre as chamadas de escaneamento em um teste ou entre os testes.
Carregando o plugin
Os plug-ins são carregados uma vez por execução de teste, não uma vez por arquivo de teste. O executor de teste carrega todos os plug-ins do sistema de arquivos fornecido e, em seguida, combina cada arquivo de teste com a VM de plug-in correspondente por fase, plataforma, categoria e ecossistema.
Comportamento de afirmação
Quando uma afirmação falha, a falha é registrada, mas a função de teste continua em execução — afirmações e instruções subsequentes ainda são executadas. Se mais de uma afirmação falhar no mesmo teste, a falha mais recente será a mensagem relatada no resumo; as falhas anteriores serão substituídas. Para interromper um teste em sua primeira falha, retorne da função após a afirmação com falha (ou use testing.fail() dentro de uma condicional).
Limitações
-
localas funções não são testáveis. Somente as funções globais deinit.luasão visíveis no arquivo de teste. Exponha os ajudantes por meio de uma tabela de módulos se eles precisarem de testes. -
Nenhum
sbomgen.*arquivo I/O fora das chamadas de escaneamento. Funções comosbomgen.read_file()exigem um contexto de artefato, que só existe dentro dastesting.scan_*chamadas. -
Sem ganchos para o ciclo de vida. Não há
before_each,after_each,setup, outeardown. Cada função de teste gerencia seu próprio estado. -
Sem tempo limite de teste. Uma função de teste que se repete eternamente suspenderá o corredor.
-
Sem relatórios de cobertura. Não há como medir quais linhas de
init.luaforam exercidas. -
Sem benchmarks. A estrutura de teste não oferece suporte a benchmarks de desempenho.
Responsabilidades do desenvolvedor
Ao escrever um novo plugin Lua
-
Crie
init_test.luaao lado do seuinit.lua -
Crie
_testdata/com o mínimo de acessórios que exercem a lógica do seu plugin -
test_*Funções de gravação que abrangem: detecção bem-sucedida, extração de versões, casos extremos e cenários sem correspondência -
Execute testes localmente antes de enviar
Diretrizes de dados de teste
-
Mantenha o mínimo de luminárias — use o menor arquivo que exercita o comportamento
-
Evite comprometer binários grandes
_testdata/quando uma pequena configuração de texto seria suficiente -
Cada plug-in
_testdata/deve ser independente — sem referências a arquivos fora do diretório do plug-in