gtest的输出结果,要么是输出到控制台,要么输出到文件,但是有时候我们需要直接从程序返回输出信息,而不是从文件里读,这里通过借助gtest留给我们的拓展可以实现。
首先看信息输出到xml文件是如何实现的:
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from %s\n", __FILE__);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
inline int RUN_ALL_TESTS() {
return ::testing::UnitTest::GetInstance()->Run();
}
return internal::HandleExceptionsInMethodIfSupported(
impl(),
&internal::UnitTestImpl::RunAllTests,
"auxiliary test code (environments or event listeners)") ? 0 : 1;
bool UnitTestImpl::RunAllTests() {
// True if and only if Google Test is initialized before RUN_ALL_TESTS() is
// called.
const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized();
// Do not run any test if the --help flag was specified.
if (g_help_flag)
return true;
// Repeats the call to the post-flag parsing initialization in case the
// user didn't call InitGoogleTest.
PostFlagParsingInit();
void UnitTestImpl::ConfigureXmlOutput() {
const std::string& output_format = UnitTestOptions::GetOutputFormat();
if (output_format == "xml") {
listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format == "json") {
listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format != "") {
GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \""
<< output_format << "\" ignored.";
}
}
在InitGoogleTest中,会解析用户命令行下输入的 --output 字段信息,放到 UnitTestOption中保存。运行用例函数的时候,在RUN_ALL_TESTS中,执行到函数ConfigureXmlOutput里面时,会读取UnitTestOption里刚才存的信息,判断如果是xml,则用XmlUnitTestResultPrinter来初始化 TestEventListener, XmlUnitTestResultPrinter是TestEventListener的子类,而这个TestEventListener,在测试用例程序运行的整个周期的不同时机,会调用各个不同的函数。
// Tells the unit test event listener that the tests have just finished.
repeater->OnTestIterationEnd(*parent_, i);
// Called after the unit test ends.
void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) {
FILE* xmlout = OpenFileForWriting(output_file_);
std::stringstream stream;
PrintXmlUnitTest(&stream, unit_test);
fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
fclose(xmlout);
}
直到调用OnTestIterationEnd的时候,这个时候测试用例运行结果的所有信息都包含在参数UnitTest中, 将这个信息转成xml格式即可。也就是说,我们只需要创建自己的类,同样继承TestEventListener,覆盖OnTestIterationEnd方法,让整个运行过程中的listener变成我们自定义的类,这样我们就可以在OnTestIterationEnd回调中,获取包含所有结果信息的UnitTest类。为了方便继承,可以继承EmptyTestEventListener类,这个类也是继承TestEventListener,只不过覆盖了所有抽象方法,按源码注释说明,这是为了方便用户只覆盖一两个接口。于是,实现我们要实现的功能的主要代码如下:
#include <iostream>
#include "gtest/gtest.h"
TEST(suiteA, 1)
{
int a = 0;
EXPECT_EQ(a, 1);
}
TEST(suiteA, 2) {
int a = 0;
EXPECT_EQ(a, 0);
}
TEST(suiteB, 1) {
int a = 0;
EXPECT_EQ(a, 0);
}
using namespace testing;
using namespace std;
class myclass : public EmptyTestEventListener{
void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override
{
cout << "suites- tests:" << unit_test.reportable_test_count()
<< "|failures:" << unit_test.failed_test_count()
<< "|disabled:" << unit_test.reportable_disabled_test_count()
<< "|random_speed:" << unit_test.random_seed()
<< "|timestamp:" << unit_test.start_timestamp()
<< "|time:" << unit_test.elapsed_time() << "|"
<< endl;
for (int i = 0; i < unit_test.ad_hoc_test_result().test_property_count();
++i) {
const TestProperty& property = unit_test.ad_hoc_test_result().GetTestProperty(i);
cout<< property.key() << "\": "
<< property.value() << "\"";
}
}
};
int main(int argc,char** argv)
{
InitGoogleTest(&argc, argv);
UnitTest* ut = UnitTest::GetInstance();
myclass* mc = new myclass;
ut->listeners().Append(mc);
ut->Run();
}
由于XmlUnitTestResultPrinter这个类对用户是不可见的,所以我们无法使用它的格式化方法,不过既然所有的结果信息我们都能拿到,自己来格式化也不是难事,可以按需要格式化为json,xml或者html.