檢視原始碼 入門指南

新手入門

本節的目的是讓新手能夠快速開始,透過「從範例中學習」的方式撰寫和執行一些簡單的測試。大部分的解釋將保留在後續章節。如果您不喜歡「從範例中學習」的方式,而偏好更技術性的細節,請直接跳到下一節。

本節示範了撰寫一個基本的(但對於許多模組測試目的來說,通常已足夠複雜)測試套件並執行其測試案例有多簡單。當您閱讀本使用者指南的其餘章節時,可能不會覺得如此明顯。

注意

為了理解這裡討論和舉例的內容,我們建議您先閱讀Common Test 基礎知識一節。

測試案例執行

測試案例的執行方式如下

Successful and Unsuccessful Test Case Execution

對於每個被指示執行的測試案例,Common Test 會產生一個專屬的進程,測試案例函數會在該進程上開始執行。(與測試案例進程並行,會啟動一個閒置等待計時器進程,該進程會連結到測試案例進程。如果計時器進程的等待時間耗盡,它會發送一個終止訊號來終止測試案例進程。這稱為時間陷阱)。

在情境 1 中,測試案例進程在 case A 完成執行其測試程式碼且未偵測到任何錯誤後正常終止。測試案例函數會傳回一個值,且 Common Test 會將該測試案例記錄為成功。

在情境 2 中,在執行測試 case B 時偵測到錯誤。這會導致測試 case B 函數產生一個例外,並導致測試案例進程以非正常的原因退出。Common Test 會將此記錄為不成功(失敗)的測試案例。

正如您可以從圖示中理解的那樣,Common Test 需要測試案例產生執行階段錯誤來指示失敗(例如,通過導致錯誤的匹配錯誤或呼叫 exit/1,最好是透過輔助函數 ct:fail/1,2)。成功執行則由測試案例函數的正常傳回指示。

一個簡單的測試套件

Common Test 基礎知識一節所示,測試套件模組實作了用於各種目的的回呼函數(強制或選用),例如

  • 測試套件的初始化/結束配置函數
  • 測試案例的初始化/結束配置函數
  • 測試案例群組的初始化/結束配置函數
  • 測試案例

配置函數是選用的。以下範例是一個沒有配置函數的測試套件,包括一個簡單的測試案例,以檢查模組 mymod 是否存在(即,是否可以被程式碼伺服器成功載入)

-module(my1st_SUITE).
-compile(export_all).

all() ->
    [mod_exists].

mod_exists(_) ->
    {module,mymod} = code:load_file(mymod).

如果操作失敗,則會發生錯誤的匹配錯誤,導致測試案例終止。

具有配置函數的測試套件

如果您需要執行配置操作來執行測試,您可以在套件中實作配置函數。配置函數的結果是配置資料,或 Config。這是一個鍵值組成的元組列表,會從配置函數傳遞到測試案例(可能會透過「較低層級」的配置函數)。資料流程如下所示

Configuration Data Flow in a Suite

以下範例顯示了一個測試套件,該套件使用配置函數來開啟和關閉測試案例的日誌檔(每個測試案例執行此操作是不必要且不相關的)

-module(check_log_SUITE).
-export([all/0, init_per_suite/1, end_per_suite/1]).
-export([check_restart_result/1, check_no_errors/1]).

-define(value(Key,Config), proplists:get_value(Key,Config)).

all() -> [check_restart_result, check_no_errors].

init_per_suite(InitConfigData) ->
    [{logref,open_log()} | InitConfigData].

end_per_suite(ConfigData) ->
    close_log(?value(logref, ConfigData)).

check_restart_result(ConfigData) ->
    TestData = read_log(restart, ?value(logref, ConfigData)),
    {match,_Line} = search_for("restart successful", TestData).

check_no_errors(ConfigData) ->
    TestData = read_log(all, ?value(logref, ConfigData)),
    case search_for("error", TestData) of
        {match,Line} -> ct:fail({error_found_in_log,Line});
        nomatch -> ok
    end.

測試案例通過解析日誌檔來驗證我們的受測系統已成功重新啟動,並且沒有印出任何意外的錯誤。

若要在最近的測試套件中執行測試案例,請在 UNIX/Linux 命令列中輸入以下內容(假設套件模組位於目前的工作目錄中)

$ ct_run -dir .

或者

$ ct_run -suite check_log_SUITE

若要使用 Erlang shell 執行我們的測試,您可以評估以下呼叫

1> ct:run_test([{dir, "."}]).

或者

1> ct:run_test([{suite, "check_log_SUITE"}]).

執行測試的結果會以 HTML 格式列印在日誌檔中(儲存在不同層級上的唯一日誌目錄中)。下圖顯示了日誌檔的結構

HTML Log File Structure

問題與解答

以下是一些您在閱讀本節後可能產生的問題,以及相應的提示和答案連結

  • 問題:「我如何以及在哪裡可以指定測試的變數資料,這些資料不應硬編碼在測試套件中(例如主機名稱、位址和使用者登入資料)?」

    答案:請參閱外部配置資料一節。

  • 問題:「是否有辦法宣告不同的測試,並在一個會期中執行它們,而無需撰寫自己的腳本?此外,此類宣告是否可以用於回歸測試?」

    答案:請參閱執行測試和分析結果一節中的測試規範一節。

  • 問題:「測試案例和/或測試執行是否可以自動重複?」

    答案:請深入了解測試案例群組,並閱讀執行測試一節和參考手冊中的啟動標誌/選項。

  • 問題:Common Test 是依序還是並行執行我的測試案例?」

    答案:請參閱撰寫測試套件一節中的測試案例群組

  • 問題:「時間陷阱(前面提到)的語法是什麼,我該如何設定它們?」

    答案:這在撰寫測試套件一節的時間陷阱逾時部分中說明。

  • 問題:「有哪些函數可用於記錄和列印?」

    答案:請參閱撰寫測試套件一節中的記錄

  • 問題:「我的測試需要資料檔。我最好將它們儲存在哪裡?」

    答案:請參閱資料和私有目錄

  • 問題:「我可以從一個測試套件範例開始嗎?」

    答案:歡迎!

您現在可能想開始撰寫自己的第一個測試套件,同時深入研究Common Test 使用者指南和參考手冊。還有很多關於本節中介紹的事項需要學習。還有許多其他有用的功能需要學習,所以請繼續閱讀其他章節並享受樂趣。