C++ 如何将Boost.Test输出记录到HRF格式的标准输出和XML格式的文件中?

C++ 如何将Boost.Test输出记录到HRF格式的标准输出和XML格式的文件中?,c++,unit-testing,jenkins,xunit,boost-test,C++,Unit Testing,Jenkins,Xunit,Boost Test,我想将Boost.Test输出记录到stdout/sterr和日志文件中 但是,我也希望标准日志是HumanReadableFormat,并且只有文件输出是XML格式 生成报告文件的问题似乎已解决。() 选择格式可以在中完成,但似乎一个人被HRF或XML卡住了 理由: 在或服务器上运行测试时,日志XML输出(与报表XML输出--日志级别与报表级别相反) 但是,当测试在服务器上运行时,进行中日志输出(在HRF中)对于检测挂起的测试或快速手动检查测试当前的位置非常有价值。因此,我需要一个测试进行中

我想将Boost.Test输出记录到stdout/sterr和日志文件中

但是,我也希望标准日志是HumanReadableFormat,并且只有文件输出是XML格式

生成报告文件的问题似乎已解决。()

选择格式可以在中完成,但似乎一个人被HRF或XML卡住了


理由:

在或服务器上运行测试时,日志XML输出(与报表XML输出--
日志级别
报表级别
相反)

但是,当测试在服务器上运行时,进行中日志输出(在HRF中)对于检测挂起的测试或快速手动检查测试当前的位置非常有价值。因此,我需要一个测试进行中的HRF日志,最后我需要一个XML文件,其中包含Boost.Test的
..
输出(而不是
输出)

请注意,我们通过Boost.Test运行单元测试和集成测试,因此其中一些测试运行时间相当长。

我已经完成了:-)经过大量的尝试和错误,我找到了一种体面的方法,让Boost.Test框架本身完成实际的输出工作,并且仍然将XML输出保存到文件中

关键是要了解在Boost中可以自定义什么以及如何自定义输出。测试:

  • 有两个日志区域,测试日志和测试结果,只有测试日志是有用的,因为测试结果,即使在最高的细节级别,也只是一个摘要
  • Test只支持一个输出流进行输出,因此替换该输出流并不能立即起到作用,尽管可以使用
    Boost::iostream
    tee_过滤器
    来写入stdout和文件
  • 上面的内容没有帮助,因为Boost.Test也只使用一个sinlge日志格式化程序(
    unit\u Test\u log\u formatter
    ),所以即使您可以将输出拆分为两个流,您仍然存在一个问题,即您只有一种格式
  • 但是,可以通过
    boost::unit\u test::unit\u test\u log.set\u formatter
    设置日志格式化程序,这正是我正在做的
我在HRF格式化程序和XML格式化程序上都提供了一个瘦包装器,其中HRF格式化程序只记录到默认流,XML格式化程序写入到自定义XML文件

它似乎工作得很好,但使用风险自负,因为这是非常新的,尚未在所有套件上运行

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

}
}
}
#pragma一次
//版权所有(c)2014
//该文件在
//Boost软件许可证-版本1.0-2003年8月17日
//(见http://www.boost.org/LICENSE_1_0.txt )
#包括
#包括
#包括
#包括
名称空间提升{
名称空间单元测试{
名称空间输出{
//!Boost的日志格式化程序。输出日志输出的测试**
//!到标准HRF格式化程序(正常输出流~cout)*和*
//!也会写入XML格式化程序,但XML会写入报表文件。
//!
//!用法:
//!//调用init\u unit\u test\u套件:(这将覆盖--log\u format参数)
//!boost::unit\u test::unit\u test\u log.set\u格式化程序(
//!new boost::unit_test::output::dual_log_格式化程序(L“filename.xml”)
//! );
//!
//!注意:调用'boost::unit\u test::unit\u test\u log.set\u stream(…)'将更改的流
//!此处使用的HRF格式化程序。
//!
//!注意:在boost::unit_test::output中实现,以便与现有格式化程序类对称
//!
类双日志格式化程序:公共单元测试日志格式化程序{
公众:
//格式化程序接口
无效日志开始(std::ostream&os、计数器测试用例和数量)覆盖{
hrf_logger.log_start(操作系统、测试案例数量);
logger.log\u start(xml\u文件、测试案例数量);
}
无效日志完成(标准::ostream&os)覆盖{
hrf_logger.log_finish(操作系统);
log\u finish(xml\u文件);
}
无效日志构建信息(std::ostream&os)覆盖{
hrf_logger.log_build_info(操作系统);
log\u build\u info(xml\u文件);
}
无效测试单元启动(标准::ostream&os,测试单元常数&tu)覆盖{
hrf记录器。测试装置启动(os、tu);
xml_logger.test_unit_start(xml_文件,tu);
}
无效测试单元完成(标准::ostream&os,测试单元常数&tu,无符号长时间运行)覆盖{
hrf\u记录器。测试单元完成(操作系统、tu、运行时间);
xml_logger.test_unit_finish(xml_文件,tu,已运行);
}
无效测试单元跳过(标准::ostream&os,测试单元常数&tu)覆盖{
hrf_记录器。跳过测试单元(os、tu);
跳过测试单元(xml文件,tu);
}
无效日志异常(std::ostream&os、日志检查点数据常量和检查点数据、执行异常常量和ex)覆盖{
hrf_logger.log_异常(操作系统,检查点数据,ex);
log_异常(xml_文件,检查点数据,ex);
}
无效日志条目开始(std::ostream&os、日志条目数据常量和条目数据、日志条目类型){
hrf_logger.log_entry_start(操作系统,输入数据,let);
log\u entry\u start(xml\u文件,entry\u数据,let);
}
使用unit_test_log_formatter::log_entry_value;//将基类函数引入重载集中
无效日志项值(std::ostream&os,常量字符串值)重写{
hrf_记录器。日志输入值(os,值);
log\u条目值(xml\u文件,值);
}
无效日志输入完成(标准::ostream&os)覆盖{
hrf_记录器。日志输入_完成(os);
log\u entry\u finish(xml\u文件);
}
双日志格式化程序(const wchar_t*xmlFilename){//注意:在非MSVC编译器上使用char*
xml_file.open(xmlFilename);
}
私人:
std::of流xml_文件;
编译器日志格式化程序hrf日志记录器;
xml_log_格式化程序xml_记录器;
};
}
}
}

在boost 1.62中实现,请参阅。@Raffi-为提醒干杯。现在我只需要从1.44升级到1.62:-d在升级之前,1.62有一个以前存在的错误