testing go command-line automated-tests user-input

testing - Rellene os.Stdin para la función que lee de él



go command-line (1)

Burlándose de os.Stdin

Está en el camino correcto de que os.Stdin es una variable (de tipo *os.File ) que puede modificar, puede asignarle un nuevo valor en las pruebas.

Lo más simple es crear un archivo temporal con el contenido que desea simular como entrada en os.Stdin . Para crear un archivo temporal, use ioutil.TempFile() . Luego escriba el contenido en él y busque de nuevo el comienzo del archivo. Ahora puede configurarlo como os.Stdin y realizar sus pruebas. No olvides limpiar el archivo temporal.

userInput() su userInput() a esto:

func userInput() error { scanner := bufio.NewScanner(os.Stdin) fmt.Println("What is your name?") var username string if scanner.Scan() { username = scanner.Text() } if err := scanner.Err(); err != nil { return err } fmt.Println("Entered:", username) return nil }

Y así es como puedes probarlo:

func TestUserInput(t *testing.T) { content := []byte("Tom") tmpfile, err := ioutil.TempFile("", "example") if err != nil { log.Fatal(err) } defer os.Remove(tmpfile.Name()) // clean up if _, err := tmpfile.Write(content); err != nil { log.Fatal(err) } if _, err := tmpfile.Seek(0, 0); err != nil { log.Fatal(err) } oldStdin := os.Stdin defer func() { os.Stdin = oldStdin }() // Restore original Stdin os.Stdin = tmpfile if err := userInput(); err != nil { t.Errorf("userInput failed: %v", err) } if err := tmpfile.Close(); err != nil { log.Fatal(err) } }

Al ejecutar la prueba, vemos una salida:

What is your name? Entered: Tom PASS

Vea también la pregunta relacionada sobre burlarse del sistema de archivos: Código de ejemplo para probar el sistema de archivos en Golang

La manera fácil y preferida

También tenga en cuenta que puede refactorizar userInput() para que no lea desde os.Stdin , sino que podría recibir un io.Reader para leer. Esto lo haría más robusto y mucho más fácil de probar.

En su aplicación, simplemente puede pasarle os.Stdin , y en las pruebas puede pasar cualquier io.Reader creado / preparado en las pruebas, por ejemplo, usando strings.NewReader() , bytes.NewBuffer() o bytes.NewBufferString()

¿Cómo lleno os.Stdin en mi prueba para una función que se lee usando un escáner?

Solicito una entrada de línea de comando de usuario a través de un escáner usando la siguiente función:

func userInput() error { scanner := bufio.NewScanner(os.Stdin) println("What is your name?") scanner.Scan() username = scanner.Text() /* ... */ }

Ahora, ¿cómo pruebo este caso y simulo una entrada del usuario? El siguiente ejemplo no funciona. Stdin todavía está vacío.

func TestUserInput(t *testing.T) { var file *os.File file.Write([]byte("Tom")) os.Stdin = file err := userInput() /* ... */ }