2010-09-27 9 views
31

È possibile acquisire lo stdout e lo stderr quando si utilizza il framework googletest?Come acquisire stdout/stderr con googletest?

Ad esempio, desidero chiamare una funzione che scrive errori nella console (stderr). Ora, quando si chiama la funzione nei test, voglio affermare che nessun output appare lì.

Oppure, forse voglio testare il comportamento dell'errore e voglio affermare che una determinata stringa viene stampata quando (deliberatamente) produco un errore.

+4

Da un punto di vista del design, vorrei suggerire di modificare l'applicazione in modo che il passaggio ai file di log essere meno doloroso. L'uso dell'interfaccia 'ostream' renderà più semplice l'esempio. –

risposta

24

Ho usato questo snippet prima di reindirizzare le chiamate di cout a un stringstream quando si verifica l'output. Spero che possa suscitare qualche idea. Non ho mai usato googletest prima.

// 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); 

prima di reindirizzare torna all'uscita originale utilizzare il test di Google per controllare l'output di buffer.

2

Evitare di doverlo fare è sempre una buona idea di design. Se si vuole veramente farlo le seguenti opere:

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

Per utilizzare stderr invece di stdout modificare il secondo argomento di dup2 essere 2. Per catturare senza passare attraverso un file è possibile utilizzare un paio pipe invece.

+4

Ovviamente anche questo non è portatile per i sistemi senza dup2 ... – Flexo

49

Googletest offre funzioni per questo:

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

probabilmente la soluzione più semplice possibile –

+0

Questo è disponibile solo per 'stdout', non' stderr'? Esistono test di morte che catturano 'stderr', ma in molti casi potrebbe non essere necessario testare la terminazione del processo. – meowsqueak

+1

test :: internal :: CaptureStderr() esiste anche. Viene qui utilizzato ad esempio: https://googletest.googlecode.com/svn/trunk/test/gtest-death-test_test.cc – Heinzi

1

Piuttosto che fare questo, utilizzare l'iniezione di dipendenza per rimuovere l'uso diretto di std::cout. Nel codice di prova utilizzare un oggetto fittizio della classe std:ostringstream come oggetto fittizio invece del reale std::cout.

Così, invece di questo:

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

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

hanno questo:

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

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