Skip to content

Instantly share code, notes, and snippets.

@elliotchance
Last active November 2, 2021 06:20
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save elliotchance/8215283 to your computer and use it in GitHub Desktop.
Save elliotchance/8215283 to your computer and use it in GitHub Desktop.
Easily customise how verbose googletest is with unit test results.
#include "gtest/gtest.h"
using namespace testing;
class ConfigurableEventListener : public TestEventListener
{
protected:
TestEventListener* eventListener;
public:
/**
* Show the names of each test case.
*/
bool showTestCases;
/**
* Show the names of each test.
*/
bool showTestNames;
/**
* Show each success.
*/
bool showSuccesses;
/**
* Show each failure as it occurs. You will also see it at the bottom after the full suite is run.
*/
bool showInlineFailures;
/**
* Show the setup of the global environment.
*/
bool showEnvironment;
explicit ConfigurableEventListener(TestEventListener* theEventListener) : eventListener(theEventListener)
{
showTestCases = true;
showTestNames = true;
showSuccesses = true;
showInlineFailures = true;
showEnvironment = true;
}
virtual ~ConfigurableEventListener()
{
delete eventListener;
}
virtual void OnTestProgramStart(const UnitTest& unit_test)
{
eventListener->OnTestProgramStart(unit_test);
}
virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration)
{
eventListener->OnTestIterationStart(unit_test, iteration);
}
virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test)
{
if(showEnvironment) {
eventListener->OnEnvironmentsSetUpStart(unit_test);
}
}
virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test)
{
if(showEnvironment) {
eventListener->OnEnvironmentsSetUpEnd(unit_test);
}
}
virtual void OnTestCaseStart(const TestCase& test_case)
{
if(showTestCases) {
eventListener->OnTestCaseStart(test_case);
}
}
virtual void OnTestStart(const TestInfo& test_info)
{
if(showTestNames) {
eventListener->OnTestStart(test_info);
}
}
virtual void OnTestPartResult(const TestPartResult& result)
{
eventListener->OnTestPartResult(result);
}
virtual void OnTestEnd(const TestInfo& test_info)
{
if((showInlineFailures && test_info.result()->Failed()) || (showSuccesses && !test_info.result()->Failed())) {
eventListener->OnTestEnd(test_info);
}
}
virtual void OnTestCaseEnd(const TestCase& test_case)
{
if(showTestCases) {
eventListener->OnTestCaseEnd(test_case);
}
}
virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test)
{
if(showEnvironment) {
eventListener->OnEnvironmentsTearDownStart(unit_test);
}
}
virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test)
{
if(showEnvironment) {
eventListener->OnEnvironmentsTearDownEnd(unit_test);
}
}
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration)
{
eventListener->OnTestIterationEnd(unit_test, iteration);
}
virtual void OnTestProgramEnd(const UnitTest& unit_test)
{
eventListener->OnTestProgramEnd(unit_test);
}
};
int main(int argc, char **argv)
{
// initialize
::testing::InitGoogleTest(&argc, argv);
// remove the default listener
testing::TestEventListeners& listeners = testing::UnitTest::GetInstance()->listeners();
auto default_printer = listeners.Release(listeners.default_result_printer());
// add our listener, by default everything is on (the same as using the default listener)
// here I am turning everything off so I only see the 3 lines for the result
// (plus any failures at the end), like:
// [==========] Running 149 tests from 53 test cases.
// [==========] 149 tests from 53 test cases ran. (1 ms total)
// [ PASSED ] 149 tests.
ConfigurableEventListener *listener = new ConfigurableEventListener(default_printer);
listener->showEnvironment = false;
listener->showTestCases = false;
listener->showTestNames = false;
listener->showSuccesses = false;
listener->showInlineFailures = false;
listeners.Append(listener);
// run
return RUN_ALL_TESTS();
}
@JohnStratoudakis
Copy link

This was great - I used it in my code and now only errors are displayed in stdout!

@wtfleming
Copy link

Thank you for sharing this!

@shreyasbharath
Copy link

Thanks, this is very handy!

@shreyasbharath
Copy link

After running this on Valgrind, I noticed a memory leak. To fix it, you just need to make the destructor like so -

virtual ~ConfigurableEventListener()
{
    delete eventListener;
}

@JohnStratoudakis
Copy link

Anybody know how to get this to compile using gcc 5.3? (Having problems with the auto keyword, and yes I have added -std=c++11x)

@jaredsburrows
Copy link

jaredsburrows commented Jul 6, 2016

Thanks for posting this!

Source: https://github.com/jaredsburrows/cs-interview-questions/blob/master/src/test/cpp/include/test/configurable_event_listener.h

If you like builders:

    auto *listener = ConfigurableEventListener::Builder(default_printer)
        .showEnvironment()
        .showTestCases()
        .showTestNames()
        .showSuccesses()
        .showInlineFailures()
        .build();

Code:

#include "gtest/gtest.h"

using namespace testing;

class ConfigurableEventListener : public TestEventListener {

    private:
        TestEventListener* eventListener;

        /**
         * Show test program start/end.
         */
        const bool showProgramStartEnd = false;

        /**
         * Show test iterations start/end.
         */
        const bool showIterationsStartEnd = false;

        /**
         * Show the names of each test case.
         */
        const bool showTestCases = false;

        /**
         * Show the names of each test.
         */
        const bool showTestNames = false;

        /**
         * Show each success.
         */
        const bool showSuccesses = false;

        /**
         * Show each failure.
         */
        const bool showFailures = false;

        /**
         * Show each failure as it occurs. You will also see it at the bottom after the full suite is run.
         */
        const bool showInlineFailures = false;

        /**
         * Show the setup of the global environment.
         */
        const bool showEnvironment = false;

        ConfigurableEventListener(TestEventListener* eventListener, const bool showProgramStartEnd,
                                  const bool showIterationsStartEnd, const bool showTestCases,
                                  const bool showTestNames, const bool showSuccesses,
                                  const bool showFailures, const bool showInlineFailures,
                                  const bool showEnvironment)
                                  : eventListener(eventListener), showProgramStartEnd(showProgramStartEnd),
                                  showIterationsStartEnd(showIterationsStartEnd), showTestCases(showTestCases),
                                  showTestNames(showTestNames), showSuccesses(showSuccesses),
                                  showFailures(showFailures), showInlineFailures(showInlineFailures),
                                  showEnvironment(showEnvironment) { }

    public:
        class Builder;

        virtual ~ConfigurableEventListener() override {
            delete this->eventListener;
        }

        // Fired before any test activity starts.
        virtual void OnTestProgramStart(const UnitTest& unit_test) override {
            if (this->showProgramStartEnd) {
                this->eventListener->OnTestProgramStart(unit_test);
            }
        }

        // Fired before each iteration of tests starts.  There may be more than
        // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
        // index, starting from 0.
        virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration) override {
            if (this->showIterationsStartEnd) {
                this->eventListener->OnTestIterationStart(unit_test, iteration);
            }
        }

        // Fired before environment set-up for each iteration of tests starts.
        virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override {
            if (this->showEnvironment) {
                this->eventListener->OnEnvironmentsSetUpStart(unit_test);
            }
        }

        // Fired after environment set-up for each iteration of tests ends.
        virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override {
            if (this->showEnvironment) {
                this->eventListener->OnEnvironmentsSetUpEnd(unit_test);
            }
        }

        // Fired before the test case starts.
        virtual void OnTestCaseStart(const TestCase& test_case) override {
            if (this->showTestCases) {
                this->eventListener->OnTestCaseStart(test_case);
            }
        }

        // Fired before the test starts.
        virtual void OnTestStart(const TestInfo& test_info) override {
            if (this->showTestNames) {
                this->eventListener->OnTestStart(test_info);
            }
        }

        // Fired after a failed assertion or a SUCCEED() invocation.
        virtual void OnTestPartResult(const TestPartResult& result) override {
            if (this->showSuccesses && result.passed()) {
                this->eventListener->OnTestPartResult(result);
            }

            if (this->showFailures && result.failed()) {
                this->eventListener->OnTestPartResult(result);
            }
        }

        // Fired after the test ends.
        virtual void OnTestEnd(const TestInfo& test_info) override {
            if ((this->showInlineFailures && test_info.result()->Failed())
                    || (this->showSuccesses && !test_info.result()->Failed())) {
                this->eventListener->OnTestEnd(test_info);
            }
        }

        // Fired after the test case ends.
        virtual void OnTestCaseEnd(const TestCase& test_case) override {
            if (this->showTestCases) {
                this->eventListener->OnTestCaseEnd(test_case);
            }
        }

        // Fired before environment tear-down for each iteration of tests starts.
        virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override {
            if (this->showEnvironment) {
                this->eventListener->OnEnvironmentsTearDownStart(unit_test);
            }
        }

        // Fired after environment tear-down for each iteration of tests ends.
        virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override {
            if (this->showEnvironment) {
                this->eventListener->OnEnvironmentsTearDownEnd(unit_test);
            }
        }

        // Fired after each iteration of tests finishes.
        virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override {
            if (this->showIterationsStartEnd) {
                this->eventListener->OnTestIterationEnd(unit_test, iteration);
            }
        }

        // Fired after all test activities have ended.
        virtual void OnTestProgramEnd(const UnitTest& unit_test) override {
            if (this->showProgramStartEnd) {
                this->eventListener->OnTestProgramEnd(unit_test);
            }
        }
};

class ConfigurableEventListener::Builder {
    private:
        TestEventListener* eventListener;
        bool programStartEnd = false;
        bool iterationsStartEnd = false;
        bool testCases = false;
        bool testNames = false;
        bool successes = false;
        bool failures = false;
        bool inlineFailures = false;
        bool environment = false;

    public:
        Builder(TestEventListener* eventListener) {
            this->eventListener = eventListener;
        }

        Builder showProgramStartEnd() {
            this->programStartEnd = true;
            return *this;
        }

        Builder showIterationsStartEnd() {
            this->iterationsStartEnd = true;
            return *this;
        }

        Builder showTestCases() {
            this->testCases = true;
            return *this;
        }

        Builder showTestNames() {
            this->testNames = true;
            return *this;
        }

        Builder showSuccesses() {
            this->successes = true;
            return *this;
        }

        Builder showFailures() {
            this->failures = true;
            return *this;
        }

        Builder showInlineFailures() {
            this->inlineFailures = true;
            return *this;
        }

        Builder showEnvironment() {
            this->environment = true;
            return *this;
        }

        ConfigurableEventListener* build() {
            return new ConfigurableEventListener(this->eventListener, this->programStartEnd, this->iterationsStartEnd,
                        this->testCases, this->testNames, this->successes, this->failures, this->inlineFailures,
                        this->environment);
        }
};

@SimonZimmer
Copy link

SimonZimmer commented Mar 4, 2020

Hey there and thanks so much for posting this!

It really helped me out with my current project.
I have one very tiny suggestion concerning the OnTestEnd:

If you use the GTEST_SKIP() Macro in your test cases to skip tests during run time, a third state "Skipped()" will be returned by test_info.result() which is neither Passed() or Failed().

In this case it might be useful to introduce a new boolean showSkips and to extend the OnTestEnd from

if((showInlineFailures && test_info.result()->Failed()) || (showSuccesses && !test_info.result()->Failed())) { eventListener->OnTestEnd(test_info); }

to
if((showInlineFailures && test_info.result()->Failed()) || (showSuccesses && test_info.result()->Passed()) || (showSkips && test_info.result()->Skipped())){ eventListener->OnTestEnd(test_info); }

That way, every three possible states are defined and can be toggled on/off separately.
Just thought I put this in here, in case someone is looking for this.

cheers,
Simon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment