2013-07-03 1 views
6

Как я могу протестировать пользовательский ввод из fmt.Scan/Scanf/Scanln?Как написать тесты против ввода пользователя в Go

Например, как я могу проверить, что вход функции примет «4 5 \ n» и «1 2 3 4 \ n» из STDIN и возвращает n == 5 и array == [1, 2, 3, 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) функция ввода(), действующая на этом. Но обратите внимание: ответ Петра - умный, но он НЕ проверяет, что fmt.Scanf работает, так как вход считывается fmt.Fscanf. (Я знаю, что это всего лишь обертка). Я все еще придерживаюсь: вы не можете писать модульные тесты против ввода пользователя. – Volker

+0

Я получаю то, что вы говорите, но решение peterSO функционально эквивалентно, если вы предполагаете, что Go сам работает так, как ожидалось. Решение peterSO также точно решает мою проблему, и любое несоответствие происходит исключительно из-за моей неспособности правильно сформулировать мой вопрос. – dmikalova

Смежные вопросы