#### Testing LOG()s {#TestingLogs} LOG()s are widely used in `google3` programs. They make it possible to diagnose a server crash when you don't have the luxury of reproducing the bug. They are also great as a [tool for refactoring](http://go/log-pin). Often we need to test how a piece of code calls LOG()s. Traditionally, this has been done using [golden files](http://go/log-pin), which is tedious to set up and brittle (what if a library you depend on starts to generate its own logs?). The [`ScopedMemoryLog`](http://go/gunit-faq-scoped-mock-log) class was created to allow writing robust LOG tests, but using it beyond the most basic scenario can be awkward. With gMock we have a better solution. `testing/base/public/mock-log.h` defines a mock log sink class `ScopedMockLog`. A `ScopedMockLog` object intercepts all LOG()s (except `LOG(FATAL)`) while it is alive. This object has a mock method of this signature: ```cpp void Log(LogSeverity severity, const string& path, const string& message); ``` This file comes with gUnit and gMock, so there is no need to add any dependency to your `BUILD` rule in order to use it. Here are some ideas on how to make use of it: To test that the code generates exactly one warning message (and nothing else): ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log(WARNING, _, "Expected warning.")); log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that a particular message is logged exactly once (but there can be other log messages with different contents): ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::AnyNumber; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log).Times(AnyNumber()); EXPECT_CALL(log, Log(INFO, _, "Expected message")); log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that no `ERROR` is logged (but there can be other log messages with different severities): ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::AnyNumber; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log).Times(AnyNumber()); EXPECT_CALL(log, Log(ERROR, _, _)) .Times(0); log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that a particular message is logged at least once (and there can be other log messages): ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::AnyNumber; using ::testing::AtLeast; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log).Times(AnyNumber()); EXPECT_CALL(log, Log(INFO, _, "Expected message")) .Times(AtLeast(1)); log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that three LOG()s occur sequentially: ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::InSequence; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); { InSequence s; EXPECT_CALL(log, Log(INFO, _, "Log #1")); EXPECT_CALL(log, Log(WARNING, _, "Log #2")); EXPECT_CALL(log, Log(INFO, _, "Log #3")); } log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that the log message contains a certain sub-string: ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::HasSubstr; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log(WARNING, _, HasSubstr("needle"))); log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that a given module generates a specific log: ```cpp using ::testing::kDoNotCaptureLogsYet; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log(WARNING, "path/to/my_module.cc", "Expected warning.")); log.StartCapturingLogs(); ... code that LOG()s ... ``` To test that code doesn't log anything at all: ```cpp using ::testing::_; using ::testing::kDoNotCaptureLogsYet; using ::testing::ScopedMockLog; ... ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log).Times(0); log.StartCapturingLogs(); ... code that does not LOG() ... ``` **Warning:** For robust tests, either ignore unexpected logs (loose), or ignore logs in other modules (tight), otherwise your test may break if their logging changes. ```cpp using ::testing::_; using ::testing::AnyNumber; using ::testing::kDoNotCaptureLogsYet; using ::testing::Not; using ::testing::ScopedMockLog; // ... // Simple robust setup, ignores unexpected logs. ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log).Times(AnyNumber()); // Ignore unexpected logs. EXPECT_CALL(log, Log(ERROR, "path/to/my_file.cc", _)) .Times(3); // Verifies logs from my_file.cc. log.StartCapturingLogs(); // ... code that LOG()s ... // ... // Tighter alternative. ScopedMockLog log(kDoNotCaptureLogsYet); EXPECT_CALL(log, Log(_, Not("path/to/my_file.cc"), _)) .Times(AnyNumber()); // Ignores other modules. EXPECT_CALL(log, Log(ERROR, "path/to/my_file.cc", _)) .Times(3); // Verifies logs from my_file.cc. log.StartCapturingLogs(); // ... code that LOG()s ... ``` To test `LOG(DFATAL)`, use [`EXPECT_DFATAL`](/third_party/googletest/googletest/docs/google3_faq#testing-death-in-debug-mode) instead.