本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
外掛程式測試指南
外掛程式作者完全在 Lua 中撰寫和測試 Lua 外掛程式,不需要 Go 工具鏈。測試與 下的外掛程式共置,init_test.lua並透過 inspector-sbomgen plugin test命令執行。
如需一般外掛程式撰寫,請參閱 外掛程式開發人員指南。如需完整的函數目錄 (包括 testing.* API),請參閱 外掛程式 API 參考。
-- 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. 建立測試檔案
放置在外掛程式的 init_test.lua旁init.lua:
my-plugin/ ├── discovery/cross-platform/extra-ecosystems/curl/ │ ├── init.lua │ ├── init_test.lua │ └── _testdata/ │ └── include/curl/curlver.h
2. 寫入測試函數
探索並執行任何以 開頭test_的全域函數:
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. 執行測試
inspector-sbomgen plugin test --path ./my-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
測試檔案命名
-
預設: 外掛程式的
init_test.lua旁init.lua -
每個外掛程式有多個測試檔案:
*_test.lua發現任何檔案比對 -
範例:
init_test.lua、parsing_test.lua、discovery_test.lua
測試資料: _testdata/
測試資料存在於 外掛程式_testdata/旁。前導底線是一種慣例,可讓固定裝置在視覺上與外掛程式來源分開;在搜尋*_test.lua檔案_testdata/時,plugin test命令不會遞減至 ,因此固定裝置永遠不會誤認為測試檔案。
具有相對路徑的測試檔案參考配件:
local result = testing.scan_directory("_testdata/include/curl")
路徑會相對於包含測試檔案的目錄解析。
testing.* API
掃描函數
每個掃描函數都會建立成品、執行外掛程式的探索 → 集合管道,並傳回問題清單。測試作者永遠不會手動建立成品、事件匯流排或登錄檔。
-- 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")
每個掃描函數:
-
為每個呼叫建立新的成品 (呼叫之間沒有狀態洩漏)
-
僅載入目前外掛程式的探索 + 集合對
-
傳回結果資料表
結果資料表
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)
聲明
-- 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
完整的 sbomgen.* API (檔案 I/O、regex、系統資訊、記錄等) 可在測試檔案中使用,與生產外掛程式相同。不過,需要成品 (例如 sbomgen.read_file()) 的sbomgen.*函數只能在回testing.scan_*呼內運作,無法在測試函數的最上層使用。
執行測試
# 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
--path 旗標接受外掛程式根目錄 (包含 discovery/和/或 collection/) 或單一生態系統目錄 (自動偵測)。如果任何測試失敗,命令會結束非零。
輸出格式
使用 -v時,每個測試都會列印一=== RUN行和一行結果 (--- PASS、 --- FAIL或 --- SKIP)。如果沒有 -v,則只會列印失敗的測試。摘要行會在結尾列印:
=== 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
測試外掛程式協助程式
測試檔案會載入與外掛程式 相同的 Lua VMinit.lua。外掛程式中定義的全域函數可從測試呼叫。若要測試協助程式函數,請將它們公開為全域或模組資料表中:
-- 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
測試檔案init.lua看不到local在 中宣告的函數。這是標準 Lua 範圍。
行為和變異
共用 VM、共用狀態
單一檔案內的測試函數會共用 Lua VM。後續test_*函數可看見一個函數中設定的全域變數。如果兩個函數定義相同的全域,第二個函數會覆寫第一個函數。每個測試應該是獨立的,而不是依賴其他測試的狀態。
非確定性執行順序
透過反覆使用以雜湊為基礎的排序來探索測試函數。測試不保證按照定義的順序執行。請勿撰寫相依於執行順序的測試。
每次掃描呼叫的新鮮成品
每次呼叫 testing.scan_directory()(或任何掃描函數) 都會建立全新的成品。在測試內的掃描呼叫之間或跨測試之間,不會傳送任何狀態。
外掛程式載入
每次測試執行會載入一次外掛程式,而不是每個測試檔案載入一次。測試執行器會從提供的檔案系統載入所有外掛程式,然後依階段、平台、類別和生態系統將每個測試檔案與其對應的外掛程式 VM 配對。
聲明行為
當宣告失敗時,會記錄失敗,但測試函數會繼續執行 - 後續宣告和陳述式仍會執行。如果同一個測試中有多個宣告失敗,最近的失敗是摘要中報告的訊息;先前的失敗會被覆寫。若要在第一次失敗時停止測試,請在失敗宣告後從函數傳回 (或在條件式testing.fail()中使用)。
限制
-
local函數無法測試。只有來自 的全域函數init.lua會顯示在測試檔案中。如果需要測試,請透過模組資料表公開協助程式。 -
掃描呼叫外沒有
sbomgen.*檔案 I/O。像 的函數sbomgen.read_file()需要成品內容,它只存在於testing.scan_*呼叫中。 -
無生命週期關聯。沒有
before_each、setup、after_each或teardown。每個測試函數都會管理自己的狀態。 -
沒有測試逾時。永遠循環的測試函數會掛起執行器。
-
無涵蓋範圍報告。無法測量
init.lua已執行哪些 行。 -
無基準。測試架構不支援效能基準。
開發人員責任
寫入新的 Lua 外掛程式時
-
在
init_test.lua旁邊建立init.lua -
_testdata/使用最少的固定裝置來建立 ,以練習外掛程式的邏輯 -
撰寫
test_*函數,涵蓋:成功偵測、版本擷取、邊緣案例和不相符案例 -
在提交之前於本機執行測試
測試資料準則
-
將固定裝置降至最低 - 使用可練習行為的最小檔案
-
當小型文字固定裝置足夠
_testdata/時,避免將大型二進位檔遞交給 -
每個外掛程式的
_testdata/應該是獨立的 - 不參考外掛程式目錄外部的檔案