Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions tests/cpp/test_testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ namespace {
return false;
}
};

class TestableBufferedTestEventListener: public BufferedTestEventListener {
public:
using BufferedTestEventListener::clearBufferedTestOutput;
using BufferedTestEventListener::logTestEvent;

[[nodiscard]] std::string output() const {
return bufferedTestOutput();
}
};
} // namespace

TEST(TestingSupportTest, DefaultTestMacroUsesBaseFixture) {
Expand Down Expand Up @@ -107,6 +117,17 @@ TEST_F(TestableBaseTest, HelpersAreAvailableOnDerivedFixtures) {
EXPECT_FALSE(isSystemTest());
}

TEST(TestingSupportTest, BufferedEventListenerOutputCanBeCustomized) {
TestableBufferedTestEventListener listener;

listener.logTestEvent("first line");
listener.logTestEvent("second line");
EXPECT_EQ(listener.output(), "first line\nsecond line\n");

listener.clearBufferedTestOutput();
EXPECT_TRUE(listener.output().empty());
}

TEST_F(LinuxTest, SkipsOrRunsLinuxFixture) {
#if defined(__linux__)
SUCCEED();
Expand Down
50 changes: 50 additions & 0 deletions tests/support/include/lizardbyte/common/testing.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,51 @@ namespace lizardbyte::common::testing {
*/
void SetUp() override;
};

/**
* @brief GoogleTest event listener that buffers test log output until a test fails.
*/
class BufferedTestEventListener: public ::testing::EmptyTestEventListener {
public:
/**
* @brief Handle the start of a test.
* @param test_info GoogleTest test information.
*/
void OnTestStart(const ::testing::TestInfo &test_info) override;

/**
* @brief Handle a test assertion result.
* @param test_part_result GoogleTest assertion result.
*/
void OnTestPartResult(const ::testing::TestPartResult &test_part_result) override;

/**
* @brief Handle the end of a test.
* @param test_info GoogleTest test information.
*/
void OnTestEnd(const ::testing::TestInfo &test_info) override;

protected:
/**
* @brief Add a test event line to the buffer.
* @param message Message to buffer.
*/
virtual void logTestEvent(const std::string &message);

/**
* @brief Get buffered test output.
* @return Buffered output.
*/
[[nodiscard]] virtual std::string bufferedTestOutput() const;

/**
* @brief Clear buffered test output.
*/
virtual void clearBufferedTestOutput();

private:
std::stringstream event_buffer_; /**< Stores event log output while tests run. */
};
} // namespace lizardbyte::common::testing

#if !defined(LIZARDBYTE_COMMON_TESTING_NO_GLOBAL_ALIASES)
Expand All @@ -154,6 +199,11 @@ using MacOSTest = ::lizardbyte::common::testing::MacOSTest;
* @brief Global compatibility alias for the shared Windows-only test fixture.
*/
using WindowsTest = ::lizardbyte::common::testing::WindowsTest;

/**
* @brief Global compatibility alias for the shared buffered test event listener.
*/
using BufferedTestEventListener = ::lizardbyte::common::testing::BufferedTestEventListener;
#endif

#if !defined(LIZARDBYTE_COMMON_TESTING_KEEP_GTEST_TEST)
Expand Down
51 changes: 51 additions & 0 deletions tests/support/testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,55 @@ namespace lizardbyte::common::testing {
BaseTest::SetUp();
#endif
}

void BufferedTestEventListener::OnTestStart(const ::testing::TestInfo &test_info) {
const std::string file {test_info.file() == nullptr ? "" : test_info.file()};
logTestEvent("From " + file + ":" + std::to_string(test_info.line()));
logTestEvent(" " + std::string {test_info.test_suite_name()} + "/" + test_info.name() + " started");
}

void BufferedTestEventListener::OnTestPartResult(const ::testing::TestPartResult &test_part_result) {
const std::string file {test_part_result.file_name() == nullptr ? "" : test_part_result.file_name()};
logTestEvent("At " + file + ":" + std::to_string(test_part_result.line_number()));

const std::string result_text {
test_part_result.passed() ? "Success" :
test_part_result.nonfatally_failed() ? "Non-fatal failure" :
test_part_result.fatally_failed() ? "Failure" :
"Skip"
};

const std::string summary {test_part_result.summary()};
const std::string message {test_part_result.message()};
logTestEvent(" " + result_text + ": " + summary);
if (message != summary) {
logTestEvent(" " + message);
}
}

void BufferedTestEventListener::OnTestEnd(const ::testing::TestInfo &test_info) {
const auto &result {*test_info.result()};
const std::string result_text {result.Passed() ? "passed" : result.Skipped() ? "skipped" :
"failed"};
logTestEvent(std::string {test_info.test_suite_name()} + "/" + test_info.name() + " " + result_text);

if (result.Failed()) {
std::cout << bufferedTestOutput();
}

clearBufferedTestOutput();
}

void BufferedTestEventListener::logTestEvent(const std::string &message) {
event_buffer_ << message << std::endl;
}

std::string BufferedTestEventListener::bufferedTestOutput() const {
return event_buffer_.str();
}

void BufferedTestEventListener::clearBufferedTestOutput() {
event_buffer_.str({});
event_buffer_.clear();
}
} // namespace lizardbyte::common::testing
Loading