[Test] How to log output to both stdout in HRF and to a file in XML?
As asked on SO: http://stackoverflow.com/questions/26505229/how-to-log-boost-test-output-to-... I would like to enable logging of Boost.Test output to *both* the stdout/sterr and to a logfile. However, I would also like to have the stdout logging be in HumanReadableFormat and only the file output be in XML format. Generating a report file seems to be addressed [here][1]. ([official docs][2]) Choosing the format can be done in [various ways][3], but it seems one is stuck with either HRF or XML? ----------- Rationale: When running tests on or [Jenkins][4] server, the [xUnit plugin][5] [requires][6] the **log** XML output (as opposed to the *report* XML output -- `log_level` vs. `report_level`). However, the in-progress log output (in HRF) is highly valuable *while* the tests are running on the server, to detect hanging tests or to a quick manual check of where the tests currently are. So I want an in-progress HRF log for the tests and at the end I need an XML file containing the `<TestLog>...</TestLog>` output of Boost.Test (not the `<TestResult>` output). Do note that we run both unit as well as integration tests via Boost.Test, so some of them are quite long-running. [1]: http://stackoverflow.com/questions/3786639/what-is-the-better-way-to-generat... [2]: http://www.boost.org/doc/libs/1_44_0/libs/test/doc/html/utf/user-guide/test-... [3]: http://www.boost.org/doc/libs/1_44_0/libs/test/doc/html/utf/user-guide/runti... [4]: http://jenkins-ci.org/ [5]: https://wiki.jenkins-ci.org/display/JENKINS/xUnit+Plugin [6]: https://issues.jenkins-ci.org/browse/JENKINS-13686
On 22.10.2014 12:23, Martin Ba wrote:
As asked on SO: http://stackoverflow.com/questions/26505229/how-to-log-boost-test-output-to-...
I would like to enable logging of Boost.Test output to *both* the stdout/sterr and to a logfile.
However, I would also like to have the stdout logging be in HumanReadableFormat and only the file output be in XML format.
Generating a report file seems to be addressed [here][1]. ([official docs][2])
Choosing the format can be done in [various ways][3], but it seems one is stuck with either HRF or XML?
I managed to get this working. See my answer on so: http://stackoverflow.com/a/26718189/321013 br, Martin + + + code + + + #pragma once // Copyright (c) 2014 // This file is distributed under the // Boost Software License - Version 1.0 - August 17th, 2003 // (See http://www.boost.org/LICENSE_1_0.txt ) #include <boost/test/unit_test_log_formatter.hpp> #include <boost/test/output/compiler_log_formatter.hpp> #include <boost/test/output/xml_log_formatter.hpp> #include <fstream> namespace boost { namespace unit_test { namespace output { //! Log formatter for Boost.Test that outputs the logging output *both* //! to the standard HRF formatter (normal output stream ~ cout) *and* //! also to the XML formatter, but the XML is written to a report file. //! //! Usage: //! // Call in init_unit_test_suite: (this will override the --log_format parameter) //! boost::unit_test::unit_test_log.set_formatter( //! new boost::unit_test::output::dual_log_formatter(L"filename.xml") //! ); //! //! Note: Calling `boost::unit_test::unit_test_log.set_stream(...)` will change the stream for //! the HRF formatter used here. //! //! Note: Implemented in boost::unit_test::output for symmetry with existing formatter classes //! class dual_log_formatter : public unit_test_log_formatter { public: // Formatter interface void log_start(std::ostream& os, counter_t test_cases_amount) override { hrf_logger.log_start(os, test_cases_amount); xml_logger.log_start(xml_file, test_cases_amount); } void log_finish(std::ostream& os) override { hrf_logger.log_finish(os); xml_logger.log_finish(xml_file); } void log_build_info(std::ostream& os) override { hrf_logger.log_build_info(os); xml_logger.log_build_info(xml_file); } void test_unit_start(std::ostream& os, test_unit const& tu) override { hrf_logger.test_unit_start(os, tu); xml_logger.test_unit_start(xml_file, tu); } void test_unit_finish(std::ostream& os, test_unit const& tu, unsigned long elapsed) override { hrf_logger.test_unit_finish(os, tu, elapsed); xml_logger.test_unit_finish(xml_file, tu, elapsed); } void test_unit_skipped(std::ostream& os, test_unit const& tu) override { hrf_logger.test_unit_skipped(os, tu); xml_logger.test_unit_skipped(xml_file, tu); } void log_exception(std::ostream& os, log_checkpoint_data const& checkpoint_data, execution_exception const& ex) override { hrf_logger.log_exception(os, checkpoint_data, ex); xml_logger.log_exception(xml_file, checkpoint_data, ex); } void log_entry_start(std::ostream& os, log_entry_data const& entry_data, log_entry_types let) override { hrf_logger.log_entry_start(os, entry_data, let); xml_logger.log_entry_start(xml_file, entry_data, let); } using unit_test_log_formatter::log_entry_value; // bring base class functions into overload set void log_entry_value(std::ostream& os, const_string value) override { hrf_logger.log_entry_value(os, value); xml_logger.log_entry_value(xml_file, value); } void log_entry_finish(std::ostream& os) override { hrf_logger.log_entry_finish(os); xml_logger.log_entry_finish(xml_file); } dual_log_formatter(const wchar_t* xmlFilename) { // Note: Use char* on non-MSVC compilers xml_file.open(xmlFilename); } private: std::ofstream xml_file; compiler_log_formatter hrf_logger; xml_log_formatter xml_logger; }; } } }
participants (2)
-
Martin B.
-
Martin Ba