測試執行環境的完整規格。
背景
Bazel BUILD 語言包含可用於以多種語言定義自動化測試程式的規則。
測試會使用 bazel test
執行。
使用者也可以直接執行測試二進位檔。我們允許這類行為,但不得背書。 因此叫用時不會遵循下述規定。
測試應是「遺傳性」:也就是說,測試只要求存取這些資源 而且已宣告依附元件如果測試無法正確隔離,就無法提供歷來可重現的結果。這可能會對找出問題所在 (判斷哪項變更導致測試失敗)、發布工程可稽核性,以及測試資源隔離 (自動化測試架構不應對伺服器進行分散式阻斷服務攻擊,因為某些測試會與伺服器通訊) 造成重大問題。
目標
本頁面的目標是正式建立執行階段環境, Bazel 測試的預期行為這個瀏覽器也會對測試施加要求 執行器和建構系統
測試環境規格有助於測試作者避免依賴 因此讓測試基礎架構更有餘裕 進行導入變更規格加緊 即使系統測試不夠單純 確定性及重新利用
本頁面旨在提供規範性和權威性資訊。如果這是 測試執行工具的實際規格和實作行為不一致, 會優先採用其他規格
提出的規格
下列關鍵字:「必須」、「不得」、「必要」、「應」、「不應」、「應該」、「應該」、 「不應該」、「建議」、「可能」和「選用」會被解讀為 如 IETF RFC 2119 中所述。
測試目的
Bazel 測試的目的是要確認來源檔案的某些屬性 登錄到存放區(在本頁中,「來源檔案」包括測試資料、黃金輸出內容,以及任何版本管控下的內容)。一位使用者編寫測試,以便斷言預期要保留的變數不變量。其他使用者稍後執行測試,以便檢查是否已違反不變量。如果 測試取決於來源檔案 (非密封) 以外的任何變數,其值 測試停止通過時。
因此,測試結果只能根據下列項目:
- 測試已宣告依附元件的來源檔案
- 測試中已宣告依附元件的建構系統產品
- 資源的行為由測試執行器保證為恆定
目前系統不會強制執行這類行為。不過,測試執行程式保留日後新增這類強制執行機制的權利。
建構系統的角色
測試規則與二進位規則相似,因為每個規則都必須產生可執行的程式。對於某些語言,這是一個 Stub 程式,可將特定語言的測試套件與測試程式碼結合。測試規則必須產生其他 輸出內容除了主要測試執行檔外,測試執行工具 就需要「runfiles」runfiles資訊清單,也就是應可供使用的輸入檔案 執行測試,而且可能需要類型、大小和 測試的標記。
建構系統可能會使用執行檔來提供程式碼和資料。(這 可用於最佳化作業,讓每個測試二進位檔 檔案進行追蹤,例如使用動態連結。建構系統應確保產生的可執行檔會透過測試執行程式提供的 runfiles 映像檔載入這些檔案,而非硬式編碼參照來源或輸出樹狀結構中的絕對位置。
測試執行工具的角色
從測試執行工具的角度來看,每項測試都是一個程式
透過 execve()
叫用。可能還有其他執行測試的方式。例如
IDE 可能會允許在過程中執行 Java 測試。不過,結果
以獨立程序執行測試,必須視為具有權威性。如果
測試程序會執行到完成,並正常終止,並顯示結束代碼
零,測試已通過任何其他結果均視為測試失敗。特別是,將任何 PASS
或 FAIL
字串寫入 stdout 對測試執行程式沒有任何意義。
如果測試執行時間過長、超出某些資源限制,或是測試執行程式偵測到禁止行為,則可能會選擇終止測試,並將執行作業視為失敗。在向測試程序或任何子項傳送信號後,執行程式不得將測試回報為通過。
整個測試目標 (而非個別方法或測試) 會獲得有限的時間來執行至完成。測試的時間限制取決於其 timeout
屬性,請參閱下表:
逾時 | 時間限制 (秒) |
---|---|
short | 60 |
中度 | 300 |
long | 900 |
永恆 | 3600 |
沒有明確指定逾時的測試,會根據
測試的 size
,如下所示:
大小 | 「默示逾時」標籤 |
---|---|
small | short |
媒介 | 中度 |
large | long |
巨大 | Eternal |
「大」沒有明確逾時設定的測試會分配到 900 秒。「中」將逾時設為「短」可獲得 60 分 秒內請求驗證碼。
與 timeout
不同,size
還會在本機執行測試時,判斷其他資源 (例如 RAM) 的假設峰值用量,如常見定義所述。
所有 size
和 timeout
標籤組合都是合法的,因此您可以宣告「enormous」測試的逾時時間為「short」。這麼一來,它就能快速執行一些非常可怕的動作。
無論逾時時間為何,測試可能會隨意快速傳回。測試不會受到懲罰 ,但您可能會收到警示: 一般而言,逾時設定會越嚴密,不會造成任何不亮。
在已知速度緩慢的情況下手動執行時,可以使用 --test_timeout
bazel 標記覆寫測試逾時時間。--test_timeout
值以秒為單位。例如:--test_timeout=120
將測試逾時設為兩分鐘。
建議的測試逾時下限值如下:
逾時 | 時間下限 (秒) |
---|---|
short | 0 |
中度 | 30 |
long | 300 |
Eternal | 900 |
舉例來說,如果「中等」測試在 5.5 秒內完成,建議您設定 timeout =
"short"
或 size = "small"
。使用邊框 --test_verbose_timeout_warnings
指令列選項會顯示指定大小過大的測試。
您可以根據這裡的規格,在 BUILD 檔案中指定測試大小和逾時時間。如果未指定,測試的大小預設為「medium」。
如果測試的主要程序已結束,但其中部分子項仍在執行,則測試執行程式應視為執行完成,並根據從主要程序觀察到的結束代碼,將其計為成功或失敗。測試執行工具 可能會終止任何不愉快的程序測試不應以這種方式洩漏程序。
測試分割
您可以透過測試區隔來並行執行測試。請參閱 --test_sharding_strategy
和 shard_count
,啟用測試分割功能。啟用分割功能後,每個分割區都會啟動一次測試執行程式。環境變數 TEST_TOTAL_SHARDS
是資料分割數量,而 TEST_SHARD_INDEX
則是
資料分割索引,從 0 開始。執行器會根據這項資訊來選取哪些測試
,例如採用循環制策略。並非所有測試執行程式都支援區隔。如果執行器支援資料分割,則必須建立或更新最後一個
指定的該檔案修改日期
TEST_SHARD_STATUS_FILE
。否則,如果
--incompatible_check_sharding_support
如果 Bazel 已設定分割,則 Bazel 將無法測試。
初始條件
執行測試時,測試執行器必須建立特定的初始值 條件。
測試執行器必須使用
argv[0]
。這個路徑必須是測試目前目錄的相對路徑
(在執行檔案樹狀結構中,如下所示)。測試執行工具不應傳遞任何
要測試的其他引數,除非使用者明確提出要求。
初始環境區塊應按以下方式組成:
變數 | 值 | 狀態 |
---|---|---|
HOME |
$TEST_TMPDIR 的值 |
建議 |
LANG |
未設定 | 必填 |
LANGUAGE |
未設定 | 必填 |
LC_ALL |
未設定 | 必填 |
LC_COLLATE |
未設定 | 必填 |
LC_CTYPE |
未設定 | 必填 |
LC_MESSAGES |
未設定 | 必填 |
LC_MONETARY |
未設定 | 必填 |
LC_NUMERIC |
未設定 | 必填 |
LC_TIME |
未設定 | 必填 |
LD_LIBRARY_PATH |
以冒號分隔的包含共用資料庫的目錄清單 | 選用 |
JAVA_RUNFILES |
$TEST_SRCDIR 的值 |
已淘汰 |
LOGNAME |
$USER 的值 |
必填 |
PATH |
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:. |
建議 |
PWD |
$TEST_SRCDIR/workspace-name |
建議 |
SHLVL |
2 |
建議 |
TEST_INFRASTRUCTURE_FAILURE_FILE |
可寫目錄中私人檔案的絕對路徑 (這個檔案僅應用於回報源自測試基礎架構的失敗情形,而非用於回報測試的輕微失敗情形的一般機制。在這種情況下,測試基礎架構的定義為 或非測試專用的程式庫,但可能導致測試失敗 發生故障第一行是導致失敗的測試基礎架構元件名稱,第二行是失敗的說明,可供人類閱讀。系統會忽略其他行)。 | 選用 |
TEST_LOGSPLITTER_OUTPUT_FILE |
可寫入目錄中私人檔案的絕對路徑 (用於寫入) LogSplitter protobuffer 記錄) | 選用 |
TEST_PREMATURE_EXIT_FILE |
可寫目錄中私密檔案的絕對路徑 (用於擷取對 exit() 的呼叫) |
選用 |
TEST_RANDOM_SEED |
如果使用 --runs_per_test 選項,
TEST_RANDOM_SEED 已設為 run number
每次測試執行時,從 1 開始。 |
選用 |
TEST_RUN_NUMBER |
如果使用 --runs_per_test 選項,
TEST_RUN_NUMBER 已設為 run number
每次測試執行時,從 1 開始。 |
選用 |
TEST_TARGET |
受測試目標的名稱 | 選用 |
TEST_SIZE |
測試 size |
選用 |
TEST_TIMEOUT |
測試 timeout 的時間長度 (以秒為單位) |
選用 |
TEST_SHARD_INDEX |
資料分割索引 (如果使用 sharding ) |
選用 |
TEST_SHARD_STATUS_FILE |
要輕觸的檔案路徑,用於表示支援 sharding |
選用 |
TEST_SRCDIR |
runfiles 樹狀結構根目錄的絕對路徑 | 必填 |
TEST_TOTAL_SHARDS |
總數
shard count 、
如果使用 sharding |
選用 |
TEST_TMPDIR |
私人可寫入目錄的絕對路徑 | 必填 |
TEST_WORKSPACE |
本機存放區的工作區名稱 | 選用 |
TEST_UNDECLARED_OUTPUTS_DIR |
可寫入私人目錄的絕對路徑 (用於寫入未宣告的測試輸出內容)。任何寫入 TEST_UNDECLARED_OUTPUTS_DIR 目錄的檔案都會壓縮,並新增至 bazel-testlogs 下的 outputs.zip 檔案。 |
選用 |
TEST_UNDECLARED_OUTPUTS_ANNOTATIONS_DIR |
私人可寫目錄的絕對路徑 (用於寫入未宣告的測試輸出註解 .part 和 .pb 檔案)。 |
選用 |
TEST_WARNINGS_OUTPUT_FILE |
可寫入目錄中私人檔案的絕對路徑 (用於寫入) 測試目標警告) | 選用 |
TESTBRIDGE_TEST_ONLY |
值
--test_filter 、
(如有指定) |
選用 |
TZ |
UTC |
必填 |
USER |
getpwuid(getuid())->pw_name 的值 |
必填 |
XML_OUTPUT_FILE |
測試動作應寫入測試結果 XML 輸出檔案的位置。否則 Bazel 會產生預設 XML 輸出檔案,並納入測試記錄 做為測試動作的一部分XML 架構是以 JUnit 測試結果結構定義。 | 選用 |
BAZEL_TEST |
表示測試可執行檔由 bazel test 驅動 |
必填 |
環境可能包含其他項目。測試不應仰賴上述未列出的任何環境變數是否存在、是否缺少或其值。
初始工作目錄應為 $TEST_SRCDIR/$TEST_WORKSPACE
。
目前的程序 ID、程序群組 ID、工作階段 ID 和父項程序 ID 未指定。這項程序不一定是程序組長或課程負責人 領先這個程序不一定有控制端。這項程序可能需要 沒有任何執行中或未重新啟動的子項程序。這項程序不應 當測試程式碼取得控制時,會有多個執行緒。
檔案描述元 0 (stdin
) 應開放供讀取,但未指定其附加至何處。測試不得讀取。檔案描述符 1 (stdout
) 和 2 (stderr
) 應開放供寫入,但不指定附加至哪個檔案。可以是終端機、管道、一般檔案,或任何可輸入字元的檔案。這些檔案可能會在開啟檔案表格中共用一個項目 (也就是說,它們無法獨立尋找)。測試不應沿用任何
其他開啟的檔案描述元
初始遮罩應為 022
或 027
。
不會顯示鬧鐘或間隔計時器。
已封鎖信號的初始遮罩為空白。所有信號應設為 他們的預設動作。
初始資源限制 (軟性和硬性) 應設為以下方式:
資源 | 限制 |
---|---|
RLIMIT_AS |
無限制 |
RLIMIT_CORE |
未指定 |
RLIMIT_CPU |
無限制 |
RLIMIT_DATA |
無限制 |
RLIMIT_FSIZE |
無限制 |
RLIMIT_LOCKS |
無限制 |
RLIMIT_MEMLOCK |
無限制 |
RLIMIT_MSGQUEUE |
未指定 |
RLIMIT_NICE |
未指定 |
RLIMIT_NOFILE |
至少 1024 年 |
RLIMIT_NPROC |
未指定 |
RLIMIT_RSS |
無限制 |
RLIMIT_RTPRIO |
未指定 |
RLIMIT_SIGPENDING |
未指定 |
RLIMIT_STACK |
無限制,或 2044 KB <= rlim <= 8192 KB |
初始處理時間 (由 times()
傳回) 和資源使用率
(由 getrusage()
傳回) 未指定。
未指定初始排程政策和優先順序。
主機系統的角色
除了由測試執行程式直接控管的使用者背景資訊外,執行測試的作業系統也必須符合特定屬性,才能讓測試執行作業有效。
檔案系統
測試觀察到的根目錄不一定是真正的根目錄。
應掛載 /proc
。
所有建構工具都應位於 /usr
下方的絕對路徑,以便由本機安裝程序使用。
可能無法提供以 /home
開頭的路徑。測試不得存取任何這類路徑。
/tmp
應可寫入,但測試應避免使用這些路徑。
測試不得假設任何常數路徑可用做為獨有 相關單位會如何運用資料,並讓他們覺得自己 獲得充分告知,且能夠針對該使用方式表示同意
測試不得假設任何已掛接的檔案系統已啟用時間。
使用者和群組
使用者的 root、無人和 unittest 必須存在。根群組、nobody 和 eng 群組必須存在。
測試必須以非超級使用者的身分執行。真正有效的使用者 ID 必須 等於;同樣適用於群組 ID除了這個值之外,目前的使用者 ID、群組 ID、使用者名稱和群組名稱都未指定。補充群組 ID 為 未指定。
目前使用者 ID 和群組 ID 必須有相應的名稱,可用於
使用 getpwuid()
和 getgrgid()
擷取。有些時間
其他補充群組 ID
目前的使用者必須擁有主目錄。可能無法寫入。測試必須 卻無法寫入資料
網路
未指定主機名稱。可含可不含半形句號。解析主機名稱時,必須提供目前主機的 IP 位址。解析主機名稱剪下 每個點後面也必須正常運作主機名稱 localhost 必須解析。
其他資源
測試至少會獲得一個 CPU 核心。但其他人可能也會使用,但我們無法保證。這個核心的其他效能方面未指定。您可以將標記「cpu:n」(其中 n 為正整數) 新增至測試規則,將保留數量提高至較高的 CPU 核心數。如果機器的規模 CPU 核心總數超過要求的 CPU 總數,Bazel 仍會執行測試如果測試使用區塊處理,每個區塊都會保留此處指定的 CPU 核心數量。
測試可能會建立子程序,但不會處理群組或工作階段。
測試可使用的輸入檔案數量有上限。這個上限可能會有所變動,但目前的上限範圍為數萬個輸入內容。
時間與日期
未指定目前的時間和日期。未指定系統時區。
可能會提供 X 視窗,也可能不會。需要 X 伺服器的測試應啟動 Xvfb。
測試與檔案系統的互動
除非另有指定,否則測試環境變數中指定的所有檔案路徑都會指向本機檔案系統的某處。
測試只能在
$TEST_TMPDIR
和 $TEST_UNDECLARED_OUTPUTS_DIR
(如有設定)。
這些目錄一開始會是空的。
測試不得嘗試移除、設定 chmod 或以其他方式變更這些目錄。
這些目錄可能是符號連結。
$TEST_TMPDIR/.
的檔案系統類型仍未指定。
測試也可能會將 .part 檔案寫入 $TEST_UNDECLARED_OUTPUTS_ANNOTATIONS_DIR
,以便為未宣告的輸出檔案加上註解。
在極少數情況下,測試可能會被迫在 /tmp
中建立檔案。例如:
Unix 網域通訊端的路徑長度限制
通常需要在 /tmp
下建立通訊端。Bazel 將無法
追蹤這類檔案;測試時必須注意保持美觀
避免彼此衝突,同時執行測試和非測試
處理及清理在 /tmp
中建立的檔案。
一些常用的測試架構,例如
JUnit4 TemporaryFolder
或 前往 TempDir
並自己的方法在 /tmp
下建立暫存目錄。這些測試架構包含清理 /tmp
中檔案的功能,因此即使這些架構會在 TEST_TMPDIR
以外建立檔案,您還是可以使用這些架構。
測試必須透過 runfiles 機制或執行環境的其他部分存取輸入內容,這些部分是專門用於提供輸入檔案。
測試不得存取以推斷出的路徑推斷的建構系統的其他輸出內容 自己執行檔的位置
未指定執行檔案樹狀結構是否包含一般檔案、符號連結或兩者混合。執行檔案樹狀結構可能包含目錄的符號連結。測試應避免在執行檔案中使用含有 ..
元件的路徑
。
在執行檔案樹狀結構中不得有目錄、檔案或符號連結 (包括
反向符號連結) 必須可寫入。(因此,初始工作目錄不應可寫入)。測試不得假設
執行檔可寫入,或由目前使用者擁有 (例如,chmod
和 chgrp
可能會
失敗)。
執行檔案樹狀結構 (包括週遊符號連結的路徑) 不得變更 測試執行期間父項目錄和檔案系統掛接點不得以任何方式變更,以免影響在 runfiles 樹狀結構中解析路徑的結果。
為了偵測提早結束,測試可能會在 TEST_PREMATURE_EXIT_FILE
指定的路徑中建立檔案,並在結束時移除該檔案。如果 Bazel 在測試完成時看到該檔案,就會假設測試提前結束,並將其標示為失敗。
代碼慣例
測試規則中的部分代碼具有特殊意義。另請參閱 Bazel 建構百科全書中的 tags
屬性。
標記 | 意義 |
---|---|
exclusive |
無法同時執行其他測試 |
external |
具有外部依附元件停用測試快取 |
large |
test_suite 慣例;大型語言測試套件 |
manual * |
不在萬用字元目標模式 (例如
:... 、:* 或:all |
medium |
test_suite 慣例;中等測試套件 |
small |
test_suite 慣例;一系列小型測試 |
smoke |
test_suite 慣例;表示應在將程式碼異動提交至版本管控系統前執行 |
執行檔
接下來,假設有一個 *_binary() 規則
//foo/bar:unittest
,且執行時間依附於已加上標籤的規則
//deps/server:server
。
位置
目標 //foo/bar:unittest
的 runfiles 目錄為 $(WORKSPACE)/$(BINDIR)/foo/bar/unittest.runfiles
目錄。這個路徑稱為
runfiles_dir
。
依附元件
runfiles 目錄會宣告為
*_binary()
規則。runfiles 目錄本身會依賴影響 *_binary()
規則或其任何編譯時間或執行時間依附元件的 BUILD 檔案組合。修改原始檔案不會影響 runfiles 目錄的結構,因此不會觸發任何重建作業。
目錄
runfiles 目錄包含下列項目:
- 執行階段依附元件的符號連結:每個 OutputFile 和 CommandRule 都是
*_binary()
規則的執行階段依附元件,並由 runfiles 目錄中的一個符號連結代表。符號連結的名稱是$(WORKSPACE)/package_name/rule_name
。舉例來說,伺服器的符號連結會命名為$(WORKSPACE)/deps/server/server
,完整路徑則為$(WORKSPACE)/foo/bar/unittest.runfiles/$(WORKSPACE)/deps/server/server
。符號連結的目的地是 OutputFile 的 OutputFileName() CommandRule,以絕對路徑表示。因此,目標運算的目的地 符號連結可能是$(WORKSPACE)/linux-dbg/deps/server/42/server
。 - 子執行檔案的連結:每個屬於執行階段的
*_binary()
Z*_binary()
C 的依附元件,執行檔案內包含第二個連結 C 的目錄套用至 Z 的執行檔案。符號連結的名稱是$(WORKSPACE)/package_name/rule_name.runfiles
。符號連結的目標是 runfiles 目錄。舉例來說,所有子程式會共用一個常見的執行檔 目錄。