0
0
mirror of https://github.com/google/googletest.git synced 2025-03-28 09:13:57 +00:00
googletest/googlemock/g3doc/includes/g3_testing_LOGs.md
2021-01-13 20:58:40 -05:00

186 lines
5.3 KiB
Markdown

#### 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.