2013-07-03 60 views
6

我將如何測試來自fmt.Scan/Scanf/Scanln的用戶輸入?如何在Go中編寫測試用戶輸入

例如我怎麼能測試功能輸入將接受來自STDIN的「4 5 \ n」和「1 2 3 4 \ n」並返回n == 5和數組== == [1,2,3,4, 4]。

package main 

import (
    "fmt" 
) 

// input gets an array from the user. 
func input() (m int, array []int) { 
    fmt.Print("Enter the size of the array, n, and the difference, m: ") 
    var n int 
    _, err := fmt.Scanf("%d %d", &n, &m) 
    if err != nil { 
     panic(err) 
    } 

    fmt.Print("Enter the array as a space seperated string: ") 
    array = make([]int, n) 
    for i := 0; i < n; i++ { 
     _, _ = fmt.Scan(&array[i]) 
    } 

    return m, array 
} 

func main() { 
    m, array := input() 
    fmt.Println(m, array) 
} 

回答

10

下面是一個非常粗略的草案來說明原則。

program.go

package main 

import (
    "fmt" 
    "os" 
) 

// input gets an array from the user. 
func input(in *os.File) (m int, array []int) { 
    if in == nil { 
     in = os.Stdin 
    } 

    fmt.Print("Enter the size of the array, n, and the difference, m: ") 
    var n int 
    _, err := fmt.Fscanf(in, "%d %d", &n, &m) 
    if err != nil { 
     panic(err) 
    } 

    fmt.Print("Enter the array as a space seperated string: ") 
    array = make([]int, n) 
    for i := 0; i < n; i++ { 
     _, _ = fmt.Fscan(in, &array[i]) 
    } 

    return m, array 
} 

func main() { 
    m, array := input(nil) 
    fmt.Println(m, array) 
} 

program_test.go

package main 

import (
    "fmt" 
    "io" 
    "io/ioutil" 
    "os" 
    "testing" 
) 

func TestInput(t *testing.T) { 
    var (
     n, m int 
     array []int 
    ) 

    in, err := ioutil.TempFile("", "") 
    if err != nil { 
     t.Fatal(err) 
    } 
    defer in.Close() 

    _, err = io.WriteString(in, "4 5\n"+"1 2 3 4\n") 
    if err != nil { 
     t.Fatal(err) 
    } 

    _, err = in.Seek(0, os.SEEK_SET) 
    if err != nil { 
     t.Fatal(err) 
    } 

    n, array = input(in) 
    if n != 5 || fmt.Sprintf("%v", array) != fmt.Sprintf("%v", []int{1, 2, 3, 4}) { 
     t.Error("unexpected results:", n, m, array) 
    } 
} 

輸出:

$ go test 
ok  command-line-arguments 0.010s 
+0

謝謝,我修復了這些錯誤,並將修改提交給了您的帖子。 – dmikalova

-5

你不能。至少不那麼容易,這樣做是值得的。

+2

話,怎麼可能改變我的代碼,以便它會以某種形式可測試? – dmikalova

+0

你不能那樣做。基本上你不能(至少沒有合理的代碼量)寫一個針對fmt.Scanf的單元測試。您應該將代碼分成:1)獲取輸入。 2)處理輸入。寫一個2的測試。上面的例子是這樣做的:1)在os.File(可能是os.Stdin)上工作,2)在這個上運行一個input()函數。但是請注意:彼得的答案很聰明,但不會*檢查fmt.Scanf是否工作,因爲輸入是由fmt.Fscanf讀取的。 (我知道這只是一個包裝)。我仍然認爲:您不能針對用戶輸入編寫單元測試。 – Volker

+0

我明白你的意思,但只要你認爲Go本身按預期工作,peterSO的解決方案在功能上就是等同的。 peterSO的解決方案也完全解決了我的問題,任何差異僅僅是因爲我無法正確地說出我的問題。 – dmikalova