testing - stderr linux
Cómo probar la salida de una función(stdout/stderr) en pruebas de unidades Go (3)
Tengo una función simple que quiero probar:
func (t *Thing) print(min_verbosity int, message string) {
if t.verbosity >= minv {
fmt.Print(message)
}
}
Pero, ¿cómo puedo probar lo que la función realmente envía a la salida estándar? Test :: Output hace lo que quiero en Perl. Sé que podría escribir todo mi propio texto repetitivo para hacer lo mismo en Go (como se describe aquí ):
orig = os.Stdout
r,w,_ = os.Pipe()
thing.print("Some message")
var buf bytes.Buffer
io.Copy(&buf, r)
w.Close()
os.Stdout = orig
if(buf.String() != "Some message") {
t.Error("Failure!")
}
Pero eso es mucho trabajo adicional para cada prueba individual. Espero que haya una forma más estándar, o quizás una biblioteca de abstracción para manejar esto.
Podría considerar agregar una declaración de devolución a su función para devolver la cadena que realmente está impresa.
func (t *Thing) print(min_verbosity int, message string) string {
if t.verbosity >= minv {
fmt.Print(message)
return message
}
return ""
}
Ahora, su prueba podría simplemente verificar la cadena devuelta contra una cadena esperada (en lugar de la impresión). Tal vez un poco más en línea con Test Driven Development (TDD).
Y, en su código de producción, nada debería cambiar, ya que no tiene que asignar el valor de retorno de una función si no la necesita.
Puedes hacer una de las dos cosas. El primero es usar ejemplos .
El paquete también se ejecuta y verifica el código de ejemplo. Las funciones de ejemplo pueden incluir un comentario de línea final que comienza con "Salida:" y se compara con la salida estándar de la función cuando se ejecutan las pruebas. (La comparación ignora el espacio inicial y final.) Estos son ejemplos de un ejemplo:
func ExampleHello() {
fmt.Println("hello")
// Output: hello
}
El segundo (y más apropiado, IMO) es usar funciones falsas para su IO. En tu código, haces:
var myPrint = fmt.Print
func (t *Thing) print(min_verbosity int, message string) {
if t.verbosity >= minv {
myPrint(message) // N.B.
}
}
Y en tus pruebas:
func init() {
myPrint = fakePrint // fakePrint records everything it''s supposed to print.
}
func Test...
Otra opción es usar fmt.Fprintf
con un io.Writer
que es os.Stdout
en el código de producción, pero puede ser decir bytes.Buffer
en las pruebas.
Una cosa que también debe recordar, no hay nada que le impida escribir funciones para evitar la repetición.
Por ejemplo, tengo una aplicación de línea de comandos que usa el log
y escribí esta función:
func captureOutput(f func()) string {
var buf bytes.Buffer
log.SetOutput(&buf)
f()
log.SetOutput(os.Stderr)
return buf.String()
}
Luego lo usé así:
output := captureOutput(func() {
client.RemoveCertificate("www.example.com")
})
assert.Equal("removed certificate www.example.com/n", output)
Usando esta biblioteca afirmativa : http://godoc.org/github.com/stretchr/testify/assert .