2010-09-27 10 views
31

¿Es posible capturar stdout y stderr cuando se utiliza el marco googletest?Cómo capturar stdout/stderr con googletest?

Por ejemplo, me gustaría llamar a una función que escribe errores en la consola (stderr). Ahora, cuando llame a la función en las pruebas, quiero afirmar que no aparece ningún resultado allí.

O, tal vez, quiero probar el comportamiento del error y quiero afirmar que una cierta cadena se imprime cuando yo (deliberadamente) produce un error.

+4

Desde el punto de vista del diseño, sugeriría la modificación de la aplicación, de manera que el cambio a los archivos de registro sea menos doloroso. Usar la interfaz 'ostream' lo haría más fácil, por ejemplo. –

Respuesta

24

He utilizado este fragmento antes para redirigir llamadas cout a una secuencia de cadenas al probar la salida. Con suerte, podría generar algunas ideas. Nunca antes había usado Googletest.

// This can be an ofstream as well or any other ostream 
std::stringstream buffer; 

// Save cout's buffer here 
std::streambuf *sbuf = std::cout.rdbuf(); 

// Redirect cout to our stringstream buffer or any other ostream 
std::cout.rdbuf(buffer.rdbuf()); 

// Use cout as usual 
std::cout << "Hello World"; 

// When done redirect cout to its old self 
std::cout.rdbuf(sbuf); 

Antes de redireccionar a la salida original, use su prueba de google para verificar la salida en la memoria intermedia.

2

Evitar tener que hacer esto siempre es una buena idea de diseño. Si realmente desea hacerlo de las siguientes obras:

#include <cstdio> 
#include <cassert> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <iostream> 

int main() { 
    int fd = open("my_file.log", O_WRONLY|O_CREAT|O_TRUNC, 0660); 
    assert(fd >= 0); 
    int ret = dup2(fd, 1); 
    assert(ret >= 0); 
    printf("This is stdout now!\n"); 
    std::cout << "This is C++ iostream cout now!" << std::endl; 
    close(fd); 
} 

Para utilizar stderr en lugar de la salida estándar cambiar el segundo argumento de dup2 ser 2. Para capturar sin tener que pasar a través de un archivo se puede utilizar un par de tubo en su lugar.

+4

Por supuesto, esto tampoco es portátil para sistemas sin dup2 ... – Flexo

49

Googletest ofrece funciones para esto:

testing::internal::CaptureStdout(); 
std::cout << "My test" 
std::string output = testing::internal::GetCapturedStdout(); 
+0

probablemente la solución más simple posible –

+0

Esto solo está disponible para 'stdout', no' stderr'? Hay pruebas de muerte que capturan 'stderr', pero en muchos casos es posible que no esté probando la finalización del proceso. – meowsqueak

+1

testing :: internal :: CaptureStderr() también existe. Se usa aquí, por ejemplo: https://googletest.googlecode.com/svn/trunk/test/gtest-death-test_test.cc – Heinzi

1

En lugar de ello, utiliza la inyección de dependencias para eliminar el uso directo de std::cout. En el código de prueba, utilice un objeto simulado de la clase std:ostringstream como objeto simulado en lugar del std::cout real.

Así que en lugar de esto:

void func() { 
    ... 
    std::cout << "message"; 
    ... 
} 

int main (int argc, char **argv) { 
    ... 
    func(); 
    ... 
} 

tienen esto:

void func(std::ostream &out) { 
    ... 
    out << "message"; 
    ... 
} 

int main(int argc, char **argv) { 
    ... 
    func(std::cout); 
    ... 
} 
Cuestiones relacionadas