2013-07-03 7 views
6

Come testare l'input dell'utente da fmt.Scan/Scanf/Scanln?Come scrivere test contro l'input dell'utente in Go

Ad esempio, come posso verificare che l'ingresso di funzione accetti "4 5 \ n" e "1 2 3 4 \ n" da STDIN e restituisca n == 5 e 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) 
} 

risposta

10

Ecco una bozza molto approssimativa per illustrare il principio.

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) 
    } 
} 

uscita:

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

Grazie, ho corretto i bug e inviato una modifica al tuo post. – dmikalova

-5

Non è possibile. Almeno non così facilmente, tale che, varrebbe la pena.

+2

Allora come potrei cambiare il mio codice in modo che sarebbe verificabile in qualche forma? – dmikalova

+0

Non puoi farlo. Fondamentalmente non è possibile (almeno non con una quantità ragionevole di codice) scrivere un test unitario contro fmt.Scanf. Dovresti dividere il tuo codice in: 1) Ottieni l'input. 2) Elabora l'input. Scrivi un test per 2. L'esempio sopra fa questo split con 1) lavorando su un file os.html (che potrebbe essere os.Stdin) e 2) su una funzione input(). Nota: la risposta di Peter è intelligente ma * NON * controlla che fmt.Scanf funzioni come l'input viene letto da fmt.Fscanf. (So ​​che è solo un involucro). Tengo ancora: non puoi scrivere test unitari contro l'input dell'utente. – Volker

+0

Ricevo quello che stai dicendo, ma la soluzione di peterSO è funzionalmente equivalente finché si presuppone che Go stesso funzioni come previsto. La soluzione di peterSO risolve anche il mio problema esattamente, e qualsiasi discrepanza deriva unicamente dalla mia incapacità di esprimere correttamente la mia domanda. – dmikalova

Problemi correlati