檢視原始碼 執行測試與分析結果
使用 Common Test 框架
Common Test
框架提供了一個高階的操作者介面用於測試,提供以下功能:
- 自動編譯測試套件(與輔助模組)
- 建立額外的 HTML 頁面以改善概觀。
- 用於執行所有可用測試的單一命令介面
- 處理設定檔,指定與受測系統 (SUT) 相關的資料(與任何其他可變資料)
- 以平行方式執行多個獨立測試會期,並具有中央控制與組態的模式
自動編譯測試套件與輔助模組
當 Common Test
啟動時,它會自動嘗試編譯指定測試中包含的任何套件。如果指定了特定的套件,則只會編譯這些套件。如果指定了特定的測試物件目錄(表示此目錄中的所有套件都將是測試的一部分),Common Test
會在該目錄中執行函數 make:all/1
以編譯這些套件。
如果一個或多個套件的編譯失敗,編譯錯誤會列印到 tty,並詢問操作者是否要在沒有遺失套件的情況下繼續測試執行,或中止。如果操作者選擇繼續,則 HTML 日誌中會記錄缺少套件的測試。如果 Common Test
在編譯失敗後無法提示使用者(如果 Common Test
不控制 stdin
),則會自動在沒有遺失套件的情況下繼續測試執行。然而,可以使用 ct_run
旗標 -abort_if_missing_suites
或 ct:run_test/1
選項 {abort_if_missing_suites,TrueOrFalse}
來修改此行為。如果 abort_if_missing_suites
設定為 true
,則如果某些套件編譯失敗,測試執行會立即停止。
與測試套件位於相同測試物件目錄中的任何輔助模組(也就是,名稱不是以 "_SUITE" 結尾的常規 Erlang 模組)也會自動編譯。輔助模組不會被誤認為是測試套件(除非它的名稱為 "_SUITE")。特定測試物件目錄中的所有輔助模組都會被編譯,無論目錄中的所有或只有特定套件是否是測試的一部分。
如果測試套件或輔助模組包含儲存在測試目錄以外位置的標頭檔,則可以使用 ct_run
的旗標 -include
或 ct:run_test/1
的選項 include
來指定這些包含目錄。此外,可以使用 OS 環境變數 CT_INCLUDE_PATH
來指定包含路徑。
範例 (bash)
$ export CT_INCLUDE_PATH=~testuser/common_suite_files/include:~testuser/common_lib_files/include
Common Test
會將所有包含目錄(使用旗標/選項 include
或變數 CT_INCLUDE_PATH
或兩者指定)傳遞給編譯器。
也可以在測試規格中指定包含目錄,請參閱測試規格。
如果使用者想要只指定頂層目錄(例如,使用啟動旗標/選項 dir
)來執行測試物件(或 OTP 應用程式)的所有測試套件,Common Test
主要會在名為 test
的子目錄中尋找測試套件模組。如果此子目錄不存在,則假設指定的頂層目錄是測試目錄,並從那裡讀取測試套件。
若要停用自動編譯功能,請使用 ct_run
的旗標 -no_auto_compile
或 ct:run_test/1
的選項 {auto_compile,false}
。在停用自動編譯的情況下,使用者負責在測試執行之前編譯測試套件模組(與任何輔助模組)。如果在 Common Test
啟動期間無法從本機檔案系統載入模組,則使用者必須在開始測試之前預先載入模組。Common Test
只會驗證指定的測試套件是否存在(也就是,它們是否已載入或可以載入)。例如,如果測試套件透過 RPC 從遠端節點傳輸並載入為二進位檔,這很有用。
從 OS 命令列執行測試
ct_run
程式可用於從 OS 命令列執行測試,例如,如下所示:
ct_run -config <設定檔名> -dir <目錄>
ct_run -config <設定檔名> -suite <具有完整路徑的套件>
ct_run -userconfig <回呼模組名稱> <設定檔名> -suite <具有完整路徑的套件>
ct_run -config <設定檔名> -suite <具有完整路徑的套件> -group <群組> -case <案例名稱>
範例
$ ct_run -config $CFGS/sys1.cfg $CFGS/sys2.cfg -dir $SYS1_TEST $SYS2_TEST
$ ct_run -userconfig ct_config_xml $CFGS/sys1.xml $CFGS/sys2.xml -dir $SYS1_TEST $SYS2_TEST
$ ct_run -suite $SYS1_TEST/setup_SUITE $SYS2_TEST/config_SUITE
$ ct_run -suite $SYS1_TEST/setup_SUITE -case start stop
$ ct_run -suite $SYS1_TEST/setup_SUITE -group installation -case start stop
可以組合旗標 dir
、suite
與 group/case
。例如,在目錄 testdir
中執行 x_SUITE
與 y_SUITE
,如下所示:
$ ct_run -dir ./testdir -suite x_SUITE y_SUITE
這與下列具有相同效果:
$ ct_run -suite ./testdir/x_SUITE ./testdir/y_SUITE
如需詳細資料,請參閱測試案例群組執行。
下列旗標也可以與 ct_run
搭配使用:
-help
- 列出所有可用的啟動旗標。-logdir <dir>
- 指定要寫入 HTML 日誌檔的位置。-label <測試執行名稱>
- 將測試執行與一個名稱關聯,該名稱會列印在概觀 HTML 日誌檔中。-refresh_logs
- 重新整理頂層 HTML 索引檔。-shell
- 啟動互動式 shell 模式(稍後說明)。-step [step_opts]
- 使用 Erlang 除錯器逐步執行測試案例(稍後說明)。-spec <測試規格>
- 使用測試規格作為輸入(稍後說明)。-allow_user_terms
- 允許在測試規格中使用使用者特定的術語(稍後說明)。-silent_connections [連線類型]
- 告訴Common Test
抑制指定連線的列印輸出(稍後說明)。-stylesheet <css_file>
- 指出使用者 HTML 樣式表(稍後說明)。-cover <cover_cfg_file>
- 執行程式碼涵蓋率測試(請參閱程式碼涵蓋率分析)。-cover_stop <bool>
- 指定是否要在測試完成後停止cover
工具(請參閱程式碼涵蓋率分析)。-event_handler <事件處理常式>
- 安裝事件處理常式。-event_handler_init <事件處理常式>
- 安裝事件處理常式,包括啟動引數。-ct_hooks <ct_hooks>
- 安裝Common Test 勾點,包括啟動引數。-ct_hooks_order [test|config]
- 修改Common Test 勾點的執行順序。-enable_builtin_hooks <bool>
- 啟用或停用內建的 Common Test 勾點。預設值為true
。-include
- 指定包含目錄(稍早說明)。-no_auto_compile
- 停用自動測試套件編譯功能(稍早說明)。-abort_if_missing_suites
- 如果一個或多個套件編譯失敗,則中止測試執行(稍早說明)。-multiply_timetraps <n>
- 延伸時間陷阱逾時值。-scale_timetraps <bool>
- 啟用自動時間陷阱逾時縮放。-repeat <n>
- 告訴Common Test
重複測試n
次(稍後說明)。-duration <時間>
- 告訴Common Test
重複測試一段時間(稍後說明)。-until <停止時間>
- 告訴Common Test
重複測試直到停止時間
(稍後說明)。-force_stop [skip_rest]
- 在逾時時,當目前測試工作完成時,中止測試執行。如果提供skip_rest
,則會跳過目前測試工作中的其餘測試案例(稍後說明)。-decrypt_key <金鑰>
- 為加密的設定檔提供解密金鑰。-decrypt_file <金鑰檔>
- 指出包含加密設定檔解密金鑰的檔案。-basic_html
- 關閉可能與舊版瀏覽器不相容的 HTML 增強功能。-logopts <opts>
- 啟用修改記錄行為,請參閱記錄選項。-verbosity <層級>
- 設定列印輸出的詳細程度。-no_esc_chars
- 停用特殊 HTML 字元的自動跳脫。請參閱記錄章節。
注意
傳遞至
Common Test
的目錄可以具有相對或絕對路徑。
注意
也可以將 Erlang 執行階段系統 (應用程式 ERTS) 的任何啟動旗標作為參數傳遞給
ct_run
。例如,能夠使用旗標-pa
或-pz
將目錄傳遞到 Erlang 程式碼伺服器搜尋路徑中,這會很有用。如果您有測試套件的通用輔助或程式庫模組(單獨編譯),儲存在測試套件目錄以外的其他目錄中,則最好以這種方式將這些help/lib
目錄新增至程式碼路徑。範例
$ ct_run -dir ./chat_server -logdir ./chat_server/testlogs -pa $PWD/chat_server/ebin
在此處,目錄
chat_server/ebin
的絕對路徑會傳遞給程式碼伺服器。這至關重要,因為相對路徑由程式碼伺服器儲存為相對路徑,並且Common Test
會在測試執行期間變更 ERTS 的目前工作目錄。
ct_run
程式會在關閉之前設定結束狀態。定義了下列值:
0
表示測試執行成功,也就是說,沒有失敗或自動跳過的測試案例。1
表示一個或多個測試案例已失敗,或已自動跳過。2
表示測試執行失敗,原因可能是編譯錯誤,或資訊函數傳回不合法的數值。
自動跳過的測試案例不會影響結束狀態。可以使用啟動標誌來變更預設行為。
-exit_status ignore_config
注意
執行不帶啟動標誌的
ct_run
等同於命令:ct_run -dir ./
有關 ct_run
程式的詳細資訊,請參閱模組 ct_run
和章節 安裝。
從 Erlang Shell 或 Erlang 程式執行測試
Common Test
提供了一個 Erlang API 來執行測試。指定和執行測試的主要(也是最靈活的)函數是 ct:run_test/1
。它接受與 ct_run
相同的啟動參數,但這些標誌改為在鍵值元組列表中指定為選項。例如,使用 ct_run
指定的測試如下所示:
$ ct_run -suite ./my_SUITE -logdir ./results
使用 ct:run_test/1
指定則如下所示:
1> ct:run_test([{suite,"./my_SUITE"},{logdir,"./results"}]).
該函數會傳回測試結果,以元組 {Ok,Failed,{UserSkipped,AutoSkipped}}
表示,其中每個元素都是整數。如果測試執行失敗,該函數會傳回元組 {error,Reason}
,其中詞彙 Reason
解釋失敗原因。
如果該函數使用空的選項列表呼叫,則會使用預設啟動選項 {dir,Cwd}
(執行目前工作目錄中的所有套件)。
釋放 Erlang Shell
在使用 ct:run_test/1
啟動的測試執行期間,控制 stdin
的 Erlang Shell 處理序,仍是 Common Test
系統中處理序的最上層處理序。因此,在測試執行期間無法與 Erlang Shell 互動。如果這不盡理想,例如,因為 shell 需要用於偵錯目的,或在測試執行期間與 SUT 互動,請將啟動選項 release_shell
設定為 true
(在呼叫 ct:run_test/1
時,或使用稍後描述的對應測試規格術語)。這會讓 Common Test
在測試套件編譯階段之後立即釋放 shell。為了達成此目的,會產生一個測試執行程式處理序來接管測試執行。效果是 ct:run_test/1
會傳回這個處理序的 pid,而不是測試結果,而測試結果會在測試執行結束時列印到 tty。
注意
若要使用函數
ct:break/1,2
和ct:continue/0,1
,必須將release_shell
設定為true
。
詳細資訊,請參閱 ct:run_test/1
手冊頁面。
測試案例群組執行
使用 ct_run
標誌或 ct:run_test/1
選項 group
,可以指定一個或多個測試案例群組,選擇性地與特定測試案例組合使用。在命令列上指定群組的語法如下:
$ ct_run -group <group_names_or_paths> [-case <cases>]
Erlang Shell 中的語法如下:
1> ct:run_test([{group,GroupsNamesOrPaths}, {case,Cases}]).
參數 group_names_or_paths
指定一個或多個群組名稱和/或一個或多個群組路徑。在啟動時,Common Test
會在群組定義樹狀結構中搜尋相符的群組(也就是從 Suite:groups/0
傳回的清單);如需詳細資訊,請參閱章節 測試案例群組。
假設有一個群組名稱,例如 g
,Common Test
會搜尋通往 g
的所有路徑。路徑是指巢狀群組的序列,必須遵循這個序列才能從最上層群組到達 g
。若要在群組 g
中執行測試案例,Common Test
必須為通往 g
的路徑中的每個群組呼叫 init_per_group/2
函數,然後呼叫所有對應的 end_per_group/2
函數。這是因為 g
中的測試案例組態(及其 Config
輸入資料)取決於 init_per_testcase(TestCase, Config)
和其傳回值,這反過來取決於 init_per_group(g, Config)
和其傳回值,而這反過來又取決於 g
上方群組的 init_per_group/2
,依此類推,直到最上層群組。
這表示如果在路徑中有不只一種方法可以找到群組(及其測試案例),則群組搜尋操作的結果是許多測試,這些測試都將執行。Common Test
將由單一群組名稱組成的群組規格解讀如下:
「搜尋並尋找群組定義樹狀結構中通往指定群組的所有路徑,並且針對每個路徑建立一個測試,該測試會依序執行下列動作:
- 執行通往指定群組的路徑中的所有組態函數。
- 執行這個群組中的所有或所有相符的測試案例。
- 執行群組的所有子群組中的所有或所有相符的測試案例。」
使用者可以使用參數 group_names_or_paths
指定特定群組路徑。使用這種規格類型,可以避免執行不需要的群組(在其他相符路徑中)和/或子群組的執行。群組路徑的命令列語法是路徑中的群組名稱清單,例如:
$ ct_run -suite "./x_SUITE" -group [g1,g3,g4] -case tc1 tc5
Erlang Shell 中的語法如下(需要在群組清單中建立清單):
1> ct:run_test([{suite,"./x_SUITE"}, {group,[[g1,g3,g4]]}, {testcase,[tc1,tc5]}]).
指定路徑中的最後一個群組是測試中的終端群組,也就是說,不會執行此群組之後的子群組。在上一個範例中,g4
是終端群組。因此,Common Test
會執行一個測試,該測試會呼叫通往 g4
路徑中的所有 init
組態函數,也就是 g1..g3..g4
。然後,它會呼叫 g4
中的測試案例 tc1
和 tc5
,最後呼叫所有依序排列的 g4..g3..g1
中的 end
組態函數。
注意
群組路徑規格不一定需要包含通往終端群組路徑中的所有群組。如果指定不完整的群組路徑,
Common Test
會搜尋所有相符的路徑。
注意
群組名稱和群組路徑可以與參數
group_names_or_paths
結合使用。每個元素都會被視為與參數cases
組合的個別規格。以下範例說明了這一點。
範例
-module(x_SUITE).
...
%% The group definitions:
groups() ->
[{top1,[],[tc11,tc12,
{sub11,[],[tc12,tc13]},
{sub12,[],[tc14,tc15,
{sub121,[],[tc12,tc16]}]}]},
{top2,[],[{group,sub21},{group,sub22}]},
{sub21,[],[tc21,{group,sub2X2}]},
{sub22,[],[{group,sub221},tc21,tc22,{group,sub2X2}]},
{sub221,[],[tc21,tc23]},
{sub2X2,[],[tc21,tc24]}].
以下會執行兩個測試,一個用於 top1
下的所有案例和所有子群組,另一個用於 top2
下的所有案例和所有子群組:
$ ct_run -suite "x_SUITE" -group all
1> ct:run_test([{suite,"x_SUITE"}, {group,all}]).
使用 -group top1 top2
或 {group,[top1,top2]}
會得到相同的結果。
以下會針對 top1
下的所有案例和所有子群組執行一個測試:
$ ct_run -suite "x_SUITE" -group top1
1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}]).
以下會執行一個測試,該測試會執行 top1
和任何可在其中找到的 top1
子群組(sub11
和 sub121
)中的 tc12
:
$ ct_run -suite "x_SUITE" -group top1 -case tc12
1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc12]}]).
以下只會在群組 top1
中執行 tc12
:
$ ct_run -suite "x_SUITE" -group [top1] -case tc12
1> ct:run_test([{suite,"x_SUITE"}, {group,[[top1]]}, {testcase,[tc12]}]).
以下會在 top1
及其所有子群組中搜尋 tc16
,導致這個測試案例在群組 sub121
中執行:
$ ct_run -suite "x_SUITE" -group top1 -case tc16
1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc16]}]).
在這個範例中,使用特定路徑 -group [sub121]
或 {group,[[sub121]]}
會得到相同的結果。
以下會執行兩個測試,一個包含 sub12
下的所有案例和所有子群組,另一個只有 sub12
中的測試案例:
$ ct_run -suite "x_SUITE" -group sub12 [sub12]
1> ct:run_test([{suite,"x_SUITE"}, {group,[sub12,[sub12]]}]).
在以下範例中,Common Test
會找到並執行兩個測試,一個用於從 top2
透過 sub21
通往 sub2X2
的路徑,另一個用於從 top2
透過 sub22
通往 sub2X2
的路徑:
$ ct_run -suite "x_SUITE" -group sub2X2
1> ct:run_test([{suite,"x_SUITE"}, {group,[sub2X2]}]).
在以下範例中,透過指定唯一路徑 top2 -> sub21 -> sub2X2
,只會執行一個測試。第二個可能路徑,從 top2
到 sub2X2
(從先前的範例)會被捨棄:
$ ct_run -suite "x_SUITE" -group [sub21,sub2X2]
1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub21,sub2X2]]}]).
以下只會執行 sub22
的測試案例,並且順序與群組定義相反:
$ ct_run -suite "x_SUITE" -group [sub22] -case tc22 tc21
1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub22]]}, {testcase,[tc22,tc21]}]).
如果屬於群組的測試案例(根據群組定義)在沒有群組規格的情況下執行,也就是單純透過(使用命令列):
$ ct_run -suite "my_SUITE" -case my_tc
或(使用 Erlang Shell):
1> ct:run_test([{suite,"my_SUITE"}, {testcase,my_tc}]).
則 Common Test
會忽略群組定義,並且僅在測試套件的範圍內執行測試案例(不會呼叫任何群組組態函數)。
本節中介紹的群組規格功能也可以在 測試規格 中使用(新增了一些額外功能)。
執行互動式 Shell 模式
您可以在互動式 Shell 模式下啟動 Common Test
,其中不會執行任何自動測試。相反地,Common Test
會啟動其公用程式處理序、安裝組態資料(如果有的話),並等待使用者從 Erlang Shell 呼叫函數(通常是測試案例支援函數)。
Shell 模式很有用,例如,用於偵錯測試套件、分析和偵錯「模擬」測試案例執行期間的 SUT,以及在測試套件開發期間嘗試各種操作。
要啟動互動式 Shell 模式,請手動啟動 Erlang Shell,並呼叫 ct:install/1
來安裝您可能需要的任何組態資料 (否則請使用 []
作為引數)。接著呼叫 ct:start_interactive/0
來啟動 Common Test
。
如果您使用 ct_run
程式,您可以使用 -shell
旗標,並選擇性地搭配 -config
和/或 -userconfig
旗標,一次啟動 Erlang Shell 和 Common Test
。
範例
ct_run -shell
ct_run -shell -config cfg/db.cfg
ct_run -shell -userconfig db_login testuser x523qZ
如果沒有使用 ct_run
指令指定組態檔案,則會顯示警告。如果 Common Test
先前已從相同的目錄執行過,則會再次使用相同的組態檔案。如果 Common Test
先前未從此目錄執行過,則沒有可用的組態檔案。
如果任何使用「必要組態資料」的函式 (例如,函式 ct_telnet
或 ct_ftp
) 要從 Erlang Shell 呼叫,請先使用 ct:require/1,2
要求組態資料。這等同於 測試套件資訊函式 或 測試案例資訊函式 中的 require
陳述式。
範例
1> ct:require(unix_telnet, unix).
ok
2> ct_telnet:open(unix_telnet).
{ok,<0.105.0>}
4> ct_telnet:cmd(unix_telnet, "ls .").
{ok,["ls .","file1 ...",...]}
Common Test
通常在測試案例記錄中列印的所有內容,在互動模式下都會寫入目錄 ct_run.<timestamp>
中名為 ctlog.html
的記錄檔中。此檔案的連結在您執行 ct_run
的目錄中名為 last_interactive.html
的檔案中提供。不支援為記錄檔指定與目前工作目錄不同的根目錄。
如果您想要退出互動模式 (例如,使用 ct:run_test/1
啟動自動化測試執行),請呼叫函式 ct:stop_interactive/0
。這會關閉正在執行的 ct
應用程式。因此,使用 require
建立的組態名稱與資料之間的關聯也會被刪除。函式 ct:start_interactive/0
會將您帶回互動模式,但先前的狀態不會復原。
使用 Erlang 偵錯器逐步執行測試案例
使用 ct_run -step [opts]
,或將選項 {step,Opts}
傳遞給 ct:run_test/1
,可以執行以下操作:
- 自動啟動 Erlang 偵錯器。
- 使用其圖形介面來調查目前測試案例的狀態。
- 逐步執行測試案例和/或設定執行中斷點。
如果沒有使用旗標/選項 step
指定額外選項,則會在要由 Common Test
執行的測試案例以及這些函式上自動設定中斷點。如果指定了 step 選項 config
,則也會在套件中的組態函式上初始設定中斷點,也就是 init_per_suite/1
、end_per_suite/1
、init_per_group/2
、end_per_group/2
、init_per_testcase/2
和 end_per_testcase/2
。
Common Test
啟用偵錯器的自動附加功能,這表示對於每個開始執行的新的直譯測試案例函式,都會自動彈出新的追蹤視窗 (因為每個測試案例都會在專用的 Erlang 處理程序上執行)。每當新的測試案例開始時,Common Test
會嘗試關閉先前測試案例的不活動追蹤視窗。但是,如果您偏好 Common Test
保留不活動的追蹤視窗,請使用選項 keep_inactive
。
step 功能可以與旗標/選項 suite
和 suite
+ case/testcase
一起使用,但不能與 dir
一起使用。
測試規格
一般描述
指定要測試內容最彈性的方式是使用測試規格,測試規格是一連串的 Erlang 詞彙。這些詞彙通常會在一個或多個文字檔案中宣告 (請參閱 ct:run_test/1
),但也可以以清單形式傳遞給 Common Test
(請參閱 ct:run_testspec/1
)。詞彙有兩種一般類型:組態詞彙和測試規格詞彙。
透過組態詞彙,例如,可以執行以下操作:
- 標記測試執行 (類似於
ct_run -label
)。 - 在開始測試之前評估任何運算式。
- 匯入組態資料 (類似於
ct_run -config/-userconfig
)。 - 指定最上層的 HTML 記錄目錄 (類似於
ct_run -logdir
)。 - 啟用程式碼涵蓋率分析 (類似於
ct_run -cover
)。 - 安裝
Common Test Hooks
(類似於ct_run -ch_hooks
)。 - 安裝
event_handler
外掛程式 (類似於ct_run -event_handler
)。 - 指定要傳遞給編譯器的 include 目錄以進行自動編譯 (類似於
ct_run -include
)。 - 停用自動編譯功能 (類似於
ct_run -no_auto_compile
)。 - 設定詳細程度 (類似於
ct_run -verbosity
)。
組態詞彙可以與 ct_run
啟動旗標或 ct:run_test/1
選項組合。對於某些旗標/選項和詞彙,結果是值會合併 (例如,組態檔案、include 目錄、詳細程度和靜音連線),而對於其他旗標/選項和詞彙,啟動旗標/選項會覆寫測試規格詞彙 (例如,記錄目錄、標籤、樣式表和自動編譯)。
透過測試規格詞彙,可以準確陳述要執行的測試以及執行順序。測試詞彙指定一個或多個套件、一個或多個測試案例群組 (可能巢狀),或是一個群組 (或多個群組) 或套件中的一個或多個測試案例。
可以依序宣告任意數量的測試詞彙。Common Test
預設會將詞彙編譯成一個或多個要在一個最終測試執行中執行的測試。指定一組測試案例的詞彙會「吞噬」僅指定這些案例子集的詞彙。例如,合併一個指定要執行套件 S 中所有案例的詞彙,與另一個僅指定 S 中測試案例 X 和 Y 的詞彙,結果是對 S 中所有案例進行測試。但是,如果指定 S 中測試案例 X 和 Y 的詞彙與指定 S 中案例 Z 的詞彙合併,則結果是對 S 中 X、Y 和 Z 進行測試。若要停用此行為,也就是改為以「類似指令碼」的方式循序執行每個測試,請在測試規格中將詞彙 merge_tests
設定為 false
。
測試詞彙也可以指定要略過的一個或多個測試套件、群組或測試案例。略過的套件、群組和案例不會執行,並且會在 HTML 記錄檔中顯示為 SKIPPED
。
使用多個測試規格檔案
當在啟動時指定多個測試規格檔案 (使用 ct_run -spec file1 file2 ...
或 ct:run_test([{spec, [File1,File2,...]}])
) 時,Common Test
會執行每個規格檔案一次測試執行,或是聯結檔案並在單一測試執行中執行所有測試。第一個行為是預設行為。後者需要提供啟動旗標/選項 join_specs
,例如 run_test -spec ./my_tests1.ts ./my_tests2.ts -join_specs
。
聯結多個規格或分別執行它們,也可以使用 (並可以與) 測試規格檔案包含一起完成。
測試規格檔案包含
透過詞彙 specs
,測試規格可以包含其他規格。包含的規格可以與來源規格聯結,或用於產生個別的測試執行 (如上述的啟動旗標/選項 join_specs
)。
範例
%% In specification file "a.spec"
{specs, join, ["b.spec", "c.spec"]}.
{specs, separate, ["d.spec", "e.spec"]}.
%% Config and test terms follow
...
在此範例中,檔案「b.spec」和「c.spec」中定義的測試詞彙會與來源規格「a.spec」中的詞彙聯結 (如果有的話)。包含規格「d.spec」和「e.spec」會導致兩個獨立的測試執行 (每個包含的規格各一個)。
選項 join
並不表示測試詞彙會合併,只表示所有測試都會在單一測試執行中執行。
聯結的規格會共用通用組態設定,例如 config
檔案或 include
目錄的清單。對於無法組合的組態,例如 logdir
或 verbosity
的設定,使用者必須確保在聯結測試規格時沒有衝突。使用選項 separate
包含的規格不會與來源規格共用組態設定。這很有用,例如,如果包含的規格中有衝突的組態設定,導致它們無法聯結。
如果 {merge_tests,true}
設定在來源規格中 (這是預設設定),則聯結規格中的詞彙會與來源規格中的詞彙合併 (根據先前 merge_tests
的說明)。
請注意,當與其他規格合併時,始終使用來源規格中的 merge_tests
設定。舉例來說,如果來源規格 A 包含測試 TA1 和 TA2,並且設定了 {merge_tests,false}
,而它又包含了另一個規格 B,其中包含測試 TB1 和 TB2,並且設定了 {merge_tests,true}
。那麼結果會執行測試序列 TA1,TA2,merge(TB1,TB2)
。相反的 merge_tests
設定會導致測試序列 merge(merge(TA1,TA2),TB1,TB2)
。
術語 specs
可用於巢狀規格,也就是說,一個規格可以包含其他規格,而其他規格又可以包含其他規格,依此類推。
測試案例群組
當指定測試案例群組時,產生的測試會先執行函式 init_per_group
,接著執行所有測試案例和子群組(包括它們的配置函式),最後執行函式 end_per_group
。此外,如果指定群組中的特定測試案例,則會呼叫該群組的 init_per_group
和 end_per_group
。如果一個群組(在 Suite:groups/0
中定義)是另一個群組的子群組,並且指定了該子群組(或者如果指定了子群組的特定測試案例),則 Common Test
會呼叫最上層群組和該子群組的配置函式(使其能夠將配置資料從 init_per_suite
一路傳遞到子群組中的測試案例)。
測試規格使用相同的機制,透過名稱和路徑來指定測試案例群組,如同 測試案例群組執行 章節中所述,並加入了 GroupSpec
元素。
GroupSpec
元素允許指定覆蓋群組定義中(即 groups/0
中)的群組執行屬性。子群組的執行屬性也可能被覆蓋。此功能允許在執行時變更群組的屬性,而無需編輯測試套件。相同的特性也適用於 Suite:all/0
列表中的 group
元素。有關詳細資訊和範例,請參閱 測試案例群組 章節。
測試規格語法
測試規格可用於在單一測試主機環境和分散式的 Common Test
環境(大規模測試)中執行測試。術語 init
中的節點參數僅在後者中相關(請參閱大規模測試中的 測試規格 章節)。有關各種術語的詳細資訊,請參閱使用者指南中的相應章節,例如以下內容:
- 請參閱
ct_run
程式 以瞭解可用的啟動標誌概觀(因為大多數標誌都有對應的配置術語)。 - 記錄(關於術語
verbosity
、stylesheet
、basic_html
和esc_chars
)。 - 外部配置資料(關於術語
config
和userconfig
)。 - 事件處理(關於
event_handler
術語)。 - Common Test 勾點(關於術語
ct_hooks
)。
配置術語
{merge_tests, Bool}.
{define, Constant, Value}.
{specs, InclSpecsOption, TestSpecs}.
{node, NodeAlias, Node}.
{init, InitOptions}.
{init, [NodeAlias], InitOptions}.
{label, Label}.
{label, NodeRefs, Label}.
{verbosity, VerbosityLevels}.
{verbosity, NodeRefs, VerbosityLevels}.
{stylesheet, CSSFile}.
{stylesheet, NodeRefs, CSSFile}.
{silent_connections, ConnTypes}.
{silent_connections, NodeRefs, ConnTypes}.
{multiply_timetraps, N}.
{multiply_timetraps, NodeRefs, N}.
{scale_timetraps, Bool}.
{scale_timetraps, NodeRefs, Bool}.
{cover, CoverSpecFile}.
{cover, NodeRefs, CoverSpecFile}.
{cover_stop, Bool}.
{cover_stop, NodeRefs, Bool}.
{include, IncludeDirs}.
{include, NodeRefs, IncludeDirs}.
{auto_compile, Bool},
{auto_compile, NodeRefs, Bool},
{abort_if_missing_suites, Bool},
{abort_if_missing_suites, NodeRefs, Bool},
{config, ConfigFiles}.
{config, ConfigDir, ConfigBaseNames}.
{config, NodeRefs, ConfigFiles}.
{config, NodeRefs, ConfigDir, ConfigBaseNames}.
{userconfig, {CallbackModule, ConfigStrings}}.
{userconfig, NodeRefs, {CallbackModule, ConfigStrings}}.
{logdir, LogDir}.
{logdir, NodeRefs, LogDir}.
{logopts, LogOpts}.
{logopts, NodeRefs, LogOpts}.
{create_priv_dir, PrivDirOption}.
{create_priv_dir, NodeRefs, PrivDirOption}.
{event_handler, EventHandlers}.
{event_handler, NodeRefs, EventHandlers}.
{event_handler, EventHandlers, InitArgs}.
{event_handler, NodeRefs, EventHandlers, InitArgs}.
{ct_hooks, CTHModules}.
{ct_hooks, NodeRefs, CTHModules}.
{ct_hooks_order, CTHOrder}.
{enable_builtin_hooks, Bool}.
{basic_html, Bool}.
{basic_html, NodeRefs, Bool}.
{esc_chars, Bool}.
{esc_chars, NodeRefs, Bool}.
{release_shell, Bool}.
測試術語
{suites, Dir, Suites}.
{suites, NodeRefs, Dir, Suites}.
{groups, Dir, Suite, Groups}.
{groups, NodeRefs, Dir, Suite, Groups}.
{groups, Dir, Suite, Groups, {cases,Cases}}.
{groups, NodeRefs, Dir, Suite, Groups, {cases,Cases}}.
{cases, Dir, Suite, Cases}.
{cases, NodeRefs, Dir, Suite, Cases}.
{skip_suites, Dir, Suites, Comment}.
{skip_suites, NodeRefs, Dir, Suites, Comment}.
{skip_groups, Dir, Suite, GroupNames, Comment}.
{skip_groups, NodeRefs, Dir, Suite, GroupNames, Comment}.
{skip_cases, Dir, Suite, Cases, Comment}.
{skip_cases, NodeRefs, Dir, Suite, Cases, Comment}.
Bool = true | false
Constant = atom()
Value = term()
InclSpecsOption = join | separate
TestSpecs = string() | [string()]
NodeAlias = atom()
Node = node()
NodeRef = NodeAlias | Node | master
NodeRefs = all_nodes | [NodeRef] | NodeRef
InitOptions = term()
Label = atom() | string()
VerbosityLevels = integer() | [{Category,integer()}]
Category = atom()
CSSFile = string()
ConnTypes = all | [atom()]
N = integer()
CoverSpecFile = string()
IncludeDirs = string() | [string()]
ConfigFiles = string() | [string()]
ConfigDir = string()
ConfigBaseNames = string() | [string()]
CallbackModule = atom()
ConfigStrings = string() | [string()]
LogDir = string()
LogOpts = [term()]
PrivDirOption = auto_per_run | auto_per_tc | manual_per_tc
EventHandlers = atom() | [atom()]
InitArgs = [term()]
CTHModules = [CTHModule |
{CTHModule, CTHInitArgs} |
{CTHModule, CTHInitArgs, CTHPriority}]
CTHModule = atom()
CTHInitArgs = term()
CTHOrder = test | config
Dir = string()
Suites = atom() | [atom()] | all
Suite = atom()
Groups = GroupPath | GroupSpec | [GroupSpec] | all
GroupPath = [[GroupSpec]]
GroupSpec = GroupName | {GroupName,Properties} | {GroupName,Properties,[GroupSpec]}
GroupName = atom()
GroupNames = GroupName | [GroupName]
Cases = atom() | [atom()] | all
Comment = string() | ""
上述 config
術語之間的差異在於,使用 ConfigDir
時,ConfigBaseNames
是基本名稱的列表,也就是說,不包含目錄路徑。ConfigFiles
必須是完整名稱,包括路徑。例如,以下兩個術語具有相同的含義:
{config, ["/home/testuser/tests/config/nodeA.cfg",
"/home/testuser/tests/config/nodeB.cfg"]}.
{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.
注意
如果在執行測試時使用
ct_run -spec TestSpecFile ...
或ct:run:test([{spec,TestSpecFile},...])
,則在測試規格中指定的任何相對路徑都是相對於包含測試規格檔案的目錄。如果在執行測試時使用
ct:run:testspec(TestSpec)
,則路徑是相對於最上層記錄目錄。
常數
術語 define
引入一個常數,該常數用於將名稱 Constant
替換為 Value
,無論在測試規格的何處找到它。這種替換發生在初始迭代遍歷測試規格期間。常數可用於測試規格中的任何位置,例如任何列表和元組中,甚至在字串中和其他常數定義的值部分中。常數也可以是節點名稱的一部分,但這是常數可以是原子一部分的唯一位置。
注意
為了提高可讀性,常數的名稱必須始終以大寫字母或
$
、?
或_
開頭。這表示它必須始終用單引號括起來(因為常數名稱是原子,而不是文字)。
常數的主要優點是它們可以用於減小長字串(例如檔案路徑)的大小(並避免重複)。
範例
%% 1a. no constant
{config, "/home/testuser/tests/config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, "/home/testuser/tests/suites", all}.
%% 1b. with constant
{define, 'TESTDIR', "/home/testuser/tests"}.
{config, "'TESTDIR'/config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, "'TESTDIR'/suites", all}.
%% 2a. no constants
{config, [testnode@host1, testnode@host2], "../config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, [testnode@host1, testnode@host2], "../suites", [x_SUITE, y_SUITE]}.
%% 2b. with constants
{define, 'NODE', testnode}.
{define, 'NODES', ['NODE'@host1, 'NODE'@host2]}.
{config, 'NODES', "../config", ["nodeA.cfg","nodeB.cfg"]}.
{suites, 'NODES', "../suites", [x_SUITE, y_SUITE]}.
常數使得先前版本的 Common Test
中的測試規格術語 alias
變得多餘。此術語已被棄用,但在即將發佈的 Common Test
版本中仍然支援。但強烈建議將 alias
術語替換為 define
。以下是一個此類替換的範例:
%% using the old alias term
{config, "/home/testuser/tests/config/nodeA.cfg"}.
{alias, suite_dir, "/home/testuser/tests/suites"}.
{groups, suite_dir, x_SUITE, group1}.
%% replacing with constants
{define, 'TestDir', "/home/testuser/tests"}.
{define, 'CfgDir', "'TestDir'/config"}.
{define, 'SuiteDir', "'TestDir'/suites"}.
{config, 'CfgDir', "nodeA.cfg"}.
{groups, 'SuiteDir', x_SUITE, group1}.
常數也可以很好地替換術語 node
,但它仍然具有宣告值,尤其是在與 NodeRefs == all_nodes
結合使用時(請參閱類型)。
範例
以下是一個簡單的測試規格範例:
{define, 'Top', "/home/test"}.
{define, 'T1', "'Top'/t1"}.
{define, 'T2', "'Top'/t2"}.
{define, 'T3', "'Top'/t3"}.
{define, 'CfgFile', "config.cfg"}.
{logdir, "'Top'/logs"}.
{config, ["'T1'/'CfgFile'", "'T2'/'CfgFile'", "'T3'/'CfgFile'"]}.
{suites, 'T1', all}.
{skip_suites, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
{skip_cases, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
{skip_cases, 'T1', t1C_SUITE, [test1], "Ignore"}.
{suites, 'T2', [t2B_SUITE,t2C_SUITE]}.
{cases, 'T2', t2A_SUITE, [test4,test1,test7]}.
{skip_suites, 'T3', all, "Not implemented"}.
範例指定了以下內容:
- 指定的
logdir
目錄用於儲存 HTML 記錄檔(在以節點名稱、日期和時間標記的子目錄中)。 - 導入指定的測試系統設定檔中的變數以進行測試。
- 要執行的第一個測試包括系統
t1
的所有套件。套件t1B
和t1D
從測試中排除。套件t1A
中的測試案例test3
和test4
,以及t1C
中的test1
案例也從測試中排除。 - 要執行的第二個測試是針對系統
t2
。包含的套件是t2B
和t2C
。套件t2A
中的測試案例test4
、test1
和test7
也包含在內。測試案例會按照指定的順序執行。 - 要執行的最後一個測試是針對系統
t3
。在這裡,所有套件都會被略過,並在記錄檔中明確註明。
init 術語
使用術語 init
,可以為測試規格中定義的節點指定初始化選項。可以使用選項來啟動節點並評估節點上的任何函式。有關詳細資訊,請參閱使用 Common Test 進行大規模測試章節中的 自動啟動測試目標節點 章節。
使用者特定術語
使用者可以提供測試規格,其中包括 (對於 Common Test
) 無法識別的術語。如果需要這樣做,請在使用 ct_run
啟動測試時使用標誌 -allow_user_terms
。這會強制 Common Test
忽略無法識別的術語。在此模式下,Common Test
無法像掃描器在預設模式下執行時一樣有效地檢查規格中的錯誤。如果使用 ct:run_test/1
來啟動測試,則透過元組 {allow_user_terms,true}
啟用寬鬆掃描器模式。
讀取測試規格術語
可以查詢目前測試規格(也就是用於配置和執行目前測試的規格)中的術語。函式 get_testspec_terms()
會傳回所有測試規格術語(包括配置術語和測試術語)的列表,而 get_testspec_terms(Tags)
會傳回符合 Tags
中標籤(或多個標籤)的術語(或術語列表)。
例如,在測試規格中:
...
{label, my_server_smoke_test}.
{config, "../../my_server_setup.cfg"}.
{config, "../../my_server_interface.cfg"}.
...
例如,在測試套件或 Common Test Hook
函式中:
...
[{label,[{_Node,TestType}]}, {config,CfgFiles}] =
ct:get_testspec_terms([label,config]),
[verify_my_server_cfg(TestType, CfgFile) || {Node,CfgFile} <- CfgFiles,
Node == node()];
...
記錄檔
隨著測試套件的執行,事件會以以下四種不同的方式記錄:
- 文字輸出到操作員主控台。
- 套件相關資訊會傳送到主要記錄檔。
- 案例相關資訊會傳送到次要記錄檔。
- HTML 總覽記錄檔會更新測試結果。
- 從特定目錄執行的所有執行檔的連結會寫入名為
all_runs.html
的記錄檔中,而所有測試的直接連結(最新的結果)會寫入最上層的index.html
中。
通常,操作員可能會執行數百甚至數千個測試案例,因此不希望主控台充滿特定測試案例的詳細資訊或列印輸出。依預設,操作員只會看到以下內容:
- 確認測試已啟動以及有關總共執行多少測試案例的資訊。
- 關於每個失敗的測試案例的小註解。
- 所有已執行測試案例的摘要。
- 確認測試執行已完成。
- 一些特殊資訊,例如錯誤報告、進度報告以及使用
erlang:display/1
或io:format/3
寫入,且特別指定給standard_io
以外的接收者(例如,預設群組領導者程序user
)。
若要深入探討整體結果,或特定測試案例的結果,操作員可以點擊 HTML 呈現中的連結,並閱讀主要或次要的日誌檔。「all_runs.html」頁面是一個很好的起點。它位於 logdir
中,並包含指向每個測試執行的連結,其中包含快速概覽(包含日期和時間、節點名稱、測試數量、測試名稱和測試結果總計)。
每個測試執行都會寫入一個「index.html」頁面(也就是儲存在標記有節點名稱、日期和時間的 ct_run
目錄中)。這個檔案提供在同一個測試執行中執行的所有個別測試的概覽。測試名稱遵循以下慣例:
TopLevelDir.TestDir
(執行TestDir
中的所有套件)TopLevelDir.TestDir:suites
(執行特定的套件)TopLevelDir.TestDir.Suite
(執行Suite
中的所有案例)TopLevelDir.TestDir.Suite:cases
(執行特定的測試案例)TopLevelDir.TestDir.Suite.Case
(僅執行Case
)
「測試執行索引」頁面包含一個指向 Common Test
框架日誌檔的連結,其中寫入了有關匯入組態資料和一般測試進度的資訊。這個日誌檔對於在執行期間取得測試執行的快照資訊非常有用。它在分析測試結果或偵錯測試套件時也很有幫助。
「測試執行索引」頁面會指出測試是否有遺失的套件(也就是 Common Test
編譯失敗的套件)。遺失的套件名稱可以在 Common Test
框架日誌檔中找到。
主要的日誌檔會顯示測試執行的詳細報告。它包括測試套件和測試案例名稱、執行時間、失敗的確切原因等等。這些資訊可以透過文字檔案和 HTML 檔案兩種格式取得。HTML 檔案顯示摘要,提供測試執行的良好概觀。它還有指向每個個別測試案例日誌檔的連結,方便使用 HTML 瀏覽器快速檢視。
次要的日誌檔包含每個單獨測試案例的完整詳細資訊,每個測試案例都有一個單獨的檔案。這樣,即使測試案例的集合發生變化,也可以直接比較最新結果與先前測試執行的結果。如果應用程式 SASL 正在運行,它的日誌也會透過 cth_log_redirect 內建勾點 列印到目前的次要日誌檔中。
次要日誌檔的完整名稱(也就是包含絕對目錄路徑的檔案名稱)可以在測試案例執行期間讀取。它以 {tc_logfile,LogFileName}
元組值的形式出現在 Config
列表中(這表示它也可以由前置或後置 Common Test Hook
函式讀取)。此外,在測試案例開始時,此資料會隨著事件傳送給任何已安裝的事件處理程式。如需詳細資訊,請參閱 事件處理 章節。
日誌檔在測試執行期間會持續寫入,並且連結總是在測試開始時建立。因此,只需重新整理 HTML 瀏覽器中的頁面,即可追蹤測試進度。但是,在測試完成之前,不會顯示統計總計。
日誌選項
透過啟動旗標 logopts
,可以指定修改日誌記錄行為某些方面的選項。以下選項可用:
no_src
- 測試執行期間不會產生測試套件原始碼的 HTML 版本(因此在日誌檔案系統中無法使用)。no_nl
-Common Test
不會將換行字元(\n)
添加到從呼叫(例如io:format/2
)接收並列印到測試案例日誌的輸出字串末尾。
例如,如果使用以下命令啟動測試:
$ ct_run -suite my_SUITE -logopts no_nl
那麼在測試期間,連續呼叫 io:format("x")
所產生的列印輸出,將在測試案例日誌中顯示為
xxx
而不是像預設行為那樣,每個 x
都列印在新的一行中。
排序 HTML 表格欄
透過點擊任何表格的欄標題中的名稱(例如「Ok」、「Case」、「Time」等),表格行將按照對於值類型有意義的任何順序排序(例如,「Ok」或「Time」使用數值排序,「Case」使用字母排序)。排序是透過 JavaScript 程式碼執行的,該程式碼會自動插入到 HTML 日誌檔中。Common Test
使用 jQuery 函式庫和 tablesorter 外掛程式,以及自訂的排序函式,來進行此實作。
非預期的 I/O 日誌
測試套件概觀頁面包含指向「非預期的 I/O 日誌」的連結。在這個日誌中,Common Test
會儲存使用 ct:log/1,2,3,4,5
和 ct:pal/1,2,3,4,5
進行的列印輸出,以及擷取的系統錯誤和進度報告,這些無法與特定測試案例相關聯,因此無法寫入個別的測試案例日誌檔中。例如,如果從外部程序(非測試案例程序)進行日誌列印,或在 Common Test
未執行測試案例或組態函式時的短暫間隔內,收到錯誤或進度報告,或在 Common Test
目前正在執行並行測試案例群組時,就會發生這種情況。
測試前和測試後 I/O 日誌
Common Test
框架日誌頁面包含指向「測試前和測試後 I/O 日誌」的連結。在這個日誌中,Common Test
會儲存使用 ct:log/1,2,3,4,5
和 ct:pal/1,2,3,4,5
進行的列印輸出,以及擷取的系統錯誤和進度報告,這些發生在測試執行之前和之後。例如,來自 CT 勾點初始化或終止函式的列印輸出,或是從 CT 勾點初始化函式啟動 OTP 應用程式時產生的進度報告。另一個例子是,由於從 CT 勾點終止函式停止外部應用程式時發生失敗而產生的錯誤報告。這些範例中的所有資訊最終都會出現在「測試前和測試後 I/O 日誌」中。如需有關如何將測試執行與外部使用者應用程式同步的詳細資訊,請參閱 Common Test Hooks 章節中的 同步 章節。
注意
僅當
Common Test
正在執行時,使用ct:log/1,2,3,4,5
或ct:pal/1,2,3,4,5
記錄到檔案才會生效。但是,使用ct:pal/1,2,3,4,5
進行的列印輸出總是會顯示在螢幕上。
刪除舊日誌
Common Test
可以自動刪除舊日誌。這是使用 keep_logs
選項指定的。此選項的預設值為 all
,這表示不會刪除任何日誌。如果將該值設定為整數 N
,Common Test
會刪除所有 ct_run.<timestamp>
目錄,但最新的 N
個除外。
HTML 樣式表
Common Test
使用 HTML 樣式表 (CSS 檔案) 來控制測試執行期間產生的 HTML 日誌檔的外觀。如果您的瀏覽器中日誌檔顯示不正確,或者您偏好更原始的日誌外觀(「pre Common Test
v1.6」),請使用啟動旗標/選項
basic_html
這會停用樣式表和 JavaScript 的使用(請參閱 排序 HTML 表格欄)。
Common Test
包含一個可選功能,允許使用者使用 HTML 樣式表來自訂列印輸出。ct
中列印到測試案例 HTML 日誌檔的函式(log/3,4,5
和 pal/3,4,5
)接受 Category
作為第一個引數。使用此引數,可以指定一個類別,該類別可以對應到 CSS 規則集中命名為 div
的選取器。這很有用,特別是對於根據列印輸出的類型(或原因)來不同地著色文字。假設您想要針對測試系統組態資訊使用一個特定的背景顏色、針對測試系統狀態資訊使用不同的背景顏色,最後針對測試案例函式偵測到的錯誤使用一個背景顏色。對應的樣式表可以如下所示:
div.sys_config { background:blue }
div.sys_state { background:yellow }
div.error { background:red }
Common Test 會將來自 ct:log/3,4,5
或 ct:pal/3,4,5
的文字列印在名為 div
元素的巢狀 pre
元素中。由於 pre
選取器在檔案 ct_default.css
中具有針對 color
、font-family
和 font-size
屬性的預先定義 CSS 規則,如果使用者想要變更任何預先定義的屬性設定,則必須將 pre
的新規則添加到使用者樣式表中。範例:
div.error pre { color:white }
這裡,針對 div.error
列印輸出使用白色文字,而不是預設的黑色(並且 pre
的其他屬性設定不會受到影響)。
若要安裝 CSS 檔案(Common Test
會將定義內嵌到 HTML 程式碼中),可以在執行 ct_run
時提供檔案名稱。
範例
$ ct_run -dir $TEST/prog -stylesheet $TEST/styles/test_categories.css
使用旗標 -stylesheet
安裝的 CSS 檔案中的類別位於全域測試層級,因為它們可以在屬於測試執行的任何套件中使用。
也可以在每個套件和每個測試案例的基礎上安裝樣式表。
範例
-module(my_SUITE).
...
suite() -> [..., {stylesheet,"suite_categories.css"}, ...].
...
my_testcase(_) ->
...
ct:log(sys_config, "Test node version: ~p", [VersionInfo]),
...
ct:log(sys_state, "Connections: ~p", [ConnectionInfo]),
...
ct:pal(error, "Error ~p detected! Info: ~p", [SomeFault,ErrorInfo]),
ct:fail(SomeFault).
如果樣式表像此範例中安裝,則這些類別為該套件私有。它們可以被套件中的所有測試案例使用,但不能被其他套件使用。套件私有樣式表(如果指定)會優先使用於全域樣式表(使用旗標 -stylesheet
指定的樣式表)。樣式表元組(如上面的 suite/0
所返回)也可以從測試案例資訊函式返回。在這種情況下,樣式表中指定的類別只能在該特定測試案例中使用。測試案例私有樣式表會優先使用於套件或全域層級的樣式表。
在元組 {stylesheet,CSSFile}
中,如果 CSSFile
指定了路徑,例如 "$TEST/styles/categories.css"
,則會使用這個完整名稱來尋找檔案。但是,如果只指定檔案名稱,例如 categories.css
,則會假設 CSS 檔案位於套件的資料目錄 data_dir
中。建議使用後者,因為它比在套件中硬式編碼路徑名稱更具可攜性。
前一個範例中的引數 Category
可以具有值(原子)sys_config
(藍色背景)、sys_state
(黃色背景)或 error
(紅色背景上的白色文字)。
重複測試
您可以命令 Common Test
重複執行您指定的測試。您可以選擇重複測試一定的次數、在特定時間段內重複測試,或重複測試直到達到特定的停止時間。如果重複由時間控制,則可以指定 Common Test
在逾時時採取的動作。Common Test
要麼在停止前執行目前執行中的所有測試,要麼在目前的測試作業完成時停止。可以透過 ct_run
啟動旗標或 ct:run:test/1
選項列表引數中的元組來啟用重複。旗標(括號中的選項)如下:
-repeat N ({repeat,N})
,其中N
是一個正整數-duration DurTime ({duration,DurTime})
,其中DurTime
是持續時間-until StopTime ({until,StopTime})
,其中StopTime
是結束時間-force_stop ({force_stop,true})
-force_stop skip_rest ({force_stop,skip_rest})
DurTime
- 持續時間指定為HHMMSS
,例如-duration 012030
或{duration,"012030"}
,這表示執行測試,並(如果時間允許)重複執行測試,直到在 1 小時 20 分 30 秒後發生逾時。
StopTime
- 結束時間可以指定為HHMMSS
,然後將其解釋為今天的時間(或可能是明天),但也可以指定為YYMoMoDDHHMMSS
,例如-until 071001120000
或{until,"071001120000"}
。這表示執行測試,並(如果時間允許)重複執行測試,直到 2007 年 10 月 1 日 12 點整。
發生逾時時,Common Test
永遠不會中止正在進行的測試案例,因為這可能會使 SUT 處於未定義且可能不好的狀態。相反地,Common Test
預設會在停止前完成目前的測試執行。如果指定了旗標 force_stop
,Common Test
會在目前的測試作業完成時停止。如果 force_stop
旗標指定了 skip_rest
,Common Test
只會完成目前的測試案例,並跳過測試作業中的其餘測試。
注意
由於
Common Test
總是至少完成目前的測試案例,因此以duration
或until
指定的時間永遠不是確定的。
來自每個重複測試執行的日誌檔案會以正常的 Common Test
方式儲存(如先前所述)。
Common Test
稍後可能會支援一個可選的功能,只儲存重複測試執行的最後一組(以及可能的第一組)日誌,但目前使用者必須小心,如果在長時間內重複測試,不要耗盡磁碟空間。
對於屬於重複階段一部分的每個測試執行,特定測試執行的相關資訊會印在 Common Test
框架日誌中。資訊包括重複次數、剩餘時間等等。
範例 1
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -duration 001000 -force_stop
在此,測試目錄 to1
中的套件,接著是 to2
中的套件,會在一個測試執行中執行。在 10 分鐘後發生逾時事件。只要還有剩餘時間,Common Test
就會重複測試執行(也就是,從測試 to1
重新開始)。逾時後,Common Test
會在目前的作業完成時停止(因為旗標 force_stop
)。因此,指定的測試執行可以在測試 to1
之後和測試 to2
之前中止。
範例 2
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -duration 001000 -forces_stop skip_rest
在此,會執行與範例 1 中相同的測試,但將旗標 force_stop
設定為 skip_rest
。如果在執行目錄 to1
中的測試時發生逾時,則會跳過 to1
中的其餘測試案例,並中止測試,而不會再次執行 to2
中的測試。如果在執行目錄 to2
中的測試時發生逾時,則會跳過 to2
中的其餘測試案例,並中止測試。
範例 3
$ date
Fri Sep 28 15:00:00 MEST 2007
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -until 160000
在此,會執行與先前範例中相同的測試執行(並可能重複執行)。但是,當在 1 小時後發生逾時時,Common Test
會在停止前完成整個測試執行(也就是說,to1
和 to2
總是會在同一個測試執行中執行)。
範例 4
$ ct_run -dir $TEST_ROOT/to1 $TEST_ROOT/to2 -repeat 5
在此,測試執行(包括 to1
和 to2
測試)會重複五次。
注意
請勿將此功能與測試案例群組的
repeat
屬性混淆。這裡描述的選項用於重複執行整個測試執行,而測試案例群組的repeat
屬性則可以重複執行套件內的一組測試案例。如需更多關於後者的資訊,請參閱撰寫測試套件章節中的 測試案例群組 一節。
靜默連線
由 ct_telnet
、ct_ssh
、ct_ftp
等實作的 Common Test
中的通訊協定處理程序會將詳細輸出印至測試案例日誌。可以使用旗標 -silent_connections
來關閉此功能
ct_run -silent_connections [conn_types]
在此,conn_types
指定 SSH、Telnet、FTP、RPC 和/或 SNMP。
範例 1
ct_run ... -silent_connections ssh telnet
這會關閉 SSH 和 Telnet 連線的記錄。
範例 2
ct_run ... -silent_connections
這會關閉所有連線類型的記錄。
即使已針對相關的連線類型關閉記錄,仍會始終印出嚴重的通訊錯誤和重新連線嘗試。但是,傳送和接收資料等操作會以靜默方式執行。
silent_connections
也可以在測試套件中指定。這是透過在 suite/0
或測試案例資訊列表中返回元組 {silent_connections,ConnTypes}
來完成的。如果 ConnTypes
是原子列表(SSH、Telnet、FTP、RPC 和/或 SNMP),則會隱藏任何對應連線的輸出。預設會針對 ConnTypes
中未指定的任何類型連線啟用完整記錄。因此,如果 ConnTypes
是空列表,則會針對所有連線啟用記錄。
範例 3
-module(my_SUITE).
suite() -> [..., {silent_connections,[telnet,ssh]}, ...].
...
my_testcase1() ->
[{silent_connections,[ssh]}].
my_testcase1(_) ->
...
my_testcase2(_) ->
...
在此範例中,suite/0
會告知 Common Test
隱藏來自 Telnet 和 SSH 連線的輸出。這對所有測試案例都有效。但是,my_testcase1/0
指定對於此測試案例,只應靜默 SSH。結果是 my_testcase1
會在日誌中印出 Telnet 資訊(如果有的話),但不會印出 SSH 資訊。my_testcase2
不會印出任何來自這兩個連線的資訊。
silent_connections
也可以使用測試規格中的術語來指定(請參閱執行測試和分析結果章節中的 測試規格 一節)。使用啟動旗標/選項 silent_connections
提供的連線會與測試規格中列出的任何連線合併。
啟動旗標/選項 silent_connections
和測試規格術語會覆寫測試套件內資訊函式所做的任何設定。
注意
在目前的
Common Test
版本中,silent_connections
功能僅適用於 Telnet 和 SSH 連線。未來Common Test
版本可以加入對其他連線類型的支援。