新增測試

現在您已將程式碼取得一個穩定的位置(順便一提,做得很好),請新增一個測試。在開發期間測試程式碼可以揭露在您進行變更時所發現的錯誤。在這個主題中,您將為 Hello 函式新增一個測試。

Go 內建的單元測試支援讓您在進行時更容易進行測試。特別是,使用命名慣例、Go 的 testing 套件和 go test 指令,您可以快速撰寫和執行測試。

  1. 在 greetings 目錄中,建立一個稱為 greetings_test.go 的檔案。

    以 _test.go 結尾的檔案名稱會告訴 go test 指令這個檔案包含測試函式。

  2. 在 greetings_test.go 中,貼上以下程式碼並儲存檔案。
    package greetings
    
    import (
        "testing"
        "regexp"
    )
    
    // TestHelloName calls greetings.Hello with a name, checking
    // for a valid return value.
    func TestHelloName(t *testing.T) {
        name := "Gladys"
        want := regexp.MustCompile(`\b`+name+`\b`)
        msg, err := Hello("Gladys")
        if !want.MatchString(msg) || err != nil {
            t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
        }
    }
    
    // TestHelloEmpty calls greetings.Hello with an empty string,
    // checking for an error.
    func TestHelloEmpty(t *testing.T) {
        msg, err := Hello("")
        if msg != "" || err == nil {
            t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
        }
    }
    

    在此程式碼中,您

    • 在與您要測試的程式碼相同的套件中實作測試函式。
    • 建立兩個測試函式來測試 greetings.Hello 函式。測試函式名稱的形式為 Test名稱,其中 名稱 說明特定測試的內容。此外,測試函式會將指標傳遞給 testing 套件的 testing.T 類型 作為參數。您會使用這個參數的方法來報告和記錄測試。
    • 實作兩個測試
      • TestHelloName 呼叫 Hello 函數,傳遞一個 name 值,函數應該能夠使用它傳回一個有效的回應訊息。如果呼叫傳回一個錯誤或一個意外的回應訊息(一個不包含你傳入的名稱),你可以使用 t 參數的 Fatalf 方法 來印出一個訊息到主控台並結束執行。
      • TestHelloEmpty 呼叫 Hello 函數,並傳入一個空字串。這個測試用來確認你的錯誤處理是否運作正常。如果呼叫傳回一個非空的字串或沒有錯誤,你可以使用 t 參數的 Fatalf 方法來印出一個訊息到主控台並結束執行。
  3. 在 greetings 目錄的命令列中,執行 go test 命令 來執行測試。

    go test 命令會執行測試函數(名稱以 Test 開頭)在測試檔案中(名稱以 _test.go 結尾)。你可以加入 -v 旗標來取得詳細的輸出,列出所有測試及其結果。

    測試應該會通過。

    $ go test
    PASS
    ok      example.com/greetings   0.364s
    
    $ go test -v
    === RUN   TestHelloName
    --- PASS: TestHelloName (0.00s)
    === RUN   TestHelloEmpty
    --- PASS: TestHelloEmpty (0.00s)
    PASS
    ok      example.com/greetings   0.372s
    
  4. 中斷 greetings.Hello 函數來檢視一個失敗的測試。

    TestHelloName 測試函數會檢查你指定為 Hello 函數參數的名稱的傳回值。要檢視一個失敗的測試結果,請變更 greetings.Hello 函數,使其不再包含名稱。

    在 greetings/greetings.go 中,貼上以下程式碼取代 Hello 函數。請注意,突出的行會變更函數傳回的值,就像 name 參數被意外移除一樣。

    // Hello returns a greeting for the named person.
    func Hello(name string) (string, error) {
        // If no name was given, return an error with a message.
        if name == "" {
            return name, errors.New("empty name")
        }
        // Create a message using a random format.
        // message := fmt.Sprintf(randomFormat(), name)
        message := fmt.Sprint(randomFormat())
        return message, nil
    }
    
  5. 在 greetings 目錄的命令列中,執行 go test 來執行測試。

    這次,執行 go test 而不要 -v 旗標。輸出只會包含失敗測試的結果,當你有很多測試時,這會很有用。TestHelloName 測試應該會失敗 -- TestHelloEmpty 仍然通過。

    $ go test
    --- FAIL: TestHelloName (0.00s)
        greetings_test.go:15: Hello("Gladys") = "Hail, %v! Well met!", <nil>, want match for `\bGladys\b`, nil
    FAIL
    exit status 1
    FAIL    example.com/greetings   0.182s
    

在下一節(也是最後一節)主題中,你將會看到如何編譯並安裝你的程式碼以在本地執行。