3

I know by default report is directed to standard-error, and so one has to redirect it to a file. My question is shall we do this inside a global fixture? Which isn't seem to be working for me some how.

This is what i tried -

struct MyConfig
{
 MyConfig()
  : testReport("fileName.log")
  {
    if(!testReport.fail())
     original = std::cerr.rdbuf(testReport.rdbuf());
  }
  ~MyConfig()
    {        
        cerr.rdbuf(original);        
        testReport.close();
    }
    ofstream testReport;
    streambuf* original;

 };

 BOOST_GLOBAL_FIXTURE(MyConfig);

After running the test, report outputs on console only, though a 0kb file is created with the given name.

Hemant
  • 726
  • 6
  • 17

3 Answers3

5

For Completeness:

You don't have to redirect the input yourself if you don't want to. You can also specify a logfile via command line arguments:

C:\MyTest.exe --log_sink=fileName.log

Took me a while to find. Hope this helps!

Wracky
  • 581
  • 6
  • 5
  • for someone starting out using the Boost unit testing framework, this is a easy to set up simple crude test report method, without needing to understand the specifics of the logging commands. +1 – midnightBlue May 12 '20 at 22:12
5

With Boost 1.44.0 (and maybe later versions) you need the following code to create a global fixture which redirects the output of the test program to a file named after the master testsuite in which the test is included (see Boost Documentation)

#include <boost/test/unit_test.hpp>
#include <string>
#include <fstream>

struct LogToFile
{
    LogToFile()
    {
        std::string logFileName(boost::unit_test::framework::master_test_suite().p_name);
        logFileName.append(".xml");
        logFile.open(logFileName.c_str());
        boost::unit_test::unit_test_log.set_stream(logFile);
    }
    ~LogToFile()
    {
        boost::unit_test::unit_test_log.test_finish();
        logFile.close();
        boost::unit_test::unit_test_log.set_stream(std::cout);
    }
    std::ofstream logFile;
};

BOOST_GLOBAL_FIXTURE(LogToFile);

In this example logFile is not a static member like in the answer provided by Steve Townsend because declaring logFile as static member resulted in wrongly generated XML and accessing the fixture struct is not thread-safe this way.

However, there seems to be a bug in Boost 1.44.0 which also results in incorrect XML output getting generated if logFile is not a static member of the fixture struct (probably the same bug I mentioned before). To fix this the line logFile << "</TestLog>" << std::flush; is needed before closing the filestream in the destructor to generate valid XML.
Thanks to @Wracky (comment below) I replaced the line logFile << "</TestLog>" << std::flush; with boost::unit_test::unit_test_log.test_finish(); which is a much cleaner solution than writing the tag manually.

NOTE: the tests are run with the following parameters: --output_format=XML --log_level=all --report_level=no. This enables the usage of the resulting XML files with the xUnit plugin for the continuous integration server Jenkins.

Community
  • 1
  • 1
MKroehnert
  • 3,637
  • 2
  • 34
  • 43
  • This doesn't work with reports unfortunately. I require the command line "--report_format=XML --report_level=detailed" to work with QuickBuild but none of the output appears in the xml file. – Cthutu Nov 12 '13 at 15:27
  • 1
    I had the same problem with the last tag not being there. I figured, since it's my own output stream, I have to tell boost that the test is over some how. And it appears there is such a function. If I add this: `unit_test_log.test_finish();` to the code, just before I close the logfile, I do get the tag in my output. Hope this helps. – Wracky Apr 07 '14 at 13:07
  • Thanks for the hint @Wracky. I'll definitly try this and update the answer if it works for me. – MKroehnert Apr 07 '14 at 15:47
4

You could try this alternative, adapted from here and alleged to work on Boost 1.34.1. This seems to be more as Boost intends - see the usage of a results stream overrider.

//
// run_tests.cc
//

#define BOOST_AUTO_TEST_MAIN

#include <iostream>
#include <fstream>
#include <cassert>
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/results_reporter.hpp>

std::ofstream ReportRedirector::out;

struct ReportRedirector
{
    ReportRedirector()
    {
        out.open("fileName.log");
        assert( out.is_open() );
        boost::unit_test::results_reporter::set_stream(out);
    }
private:
    static std::ofstream out;
};

BOOST_GLOBAL_FIXTURE(ReportRedirector)
Steve Townsend
  • 53,498
  • 9
  • 91
  • 140