0
0
mirror of https://github.com/google/googletest.git synced 2025-04-02 19:08:12 +00:00

Output to the test warning file if no tests are linked.

Bazel sets the environment variable TEST_WARNINGS_OUTPUT_FILE
https://bazel.build/reference/test-encyclopedia#initial-conditions

If no tests are linked and the new flag --gtest_fail_if_no_test_linked
is not true (which is the current default), we can still warn the user
as this may be a programming error without failing the test (which would
break existing users).

PiperOrigin-RevId: 731402363
Change-Id: Ia481689efd4bd18889feaaa38bc56049a3f651cd
This commit is contained in:
Derek Mauro 2025-02-26 11:56:21 -08:00 committed by Copybara-Service
parent 54501746a6
commit e5669fdffc
2 changed files with 103 additions and 12 deletions

View File

@ -192,12 +192,17 @@ static const char kDefaultOutputFormat[] = "xml";
// The default output file.
static const char kDefaultOutputFile[] = "test_detail";
// These environment variables are set by Bazel.
// https://bazel.build/reference/test-encyclopedia#initial-conditions
//
// The environment variable name for the test shard index.
static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
// The environment variable name for the total number of test shards.
static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
// The environment variable name for the test shard status file.
static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
// The environment variable name for the test output warnings file.
static const char kTestWarningsOutputFile[] = "TEST_WARNINGS_OUTPUT_FILE";
namespace internal {
@ -5875,6 +5880,23 @@ TestSuite* UnitTestImpl::GetTestSuite(
static void SetUpEnvironment(Environment* env) { env->SetUp(); }
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
// If the environment variable TEST_WARNINGS_OUTPUT_FILE was provided, appends
// `str` to the file, creating the file if necessary.
#if GTEST_HAS_FILE_SYSTEM
static void AppendToTestWarningsOutputFile(const std::string& str) {
const char* const filename = posix::GetEnv(kTestWarningsOutputFile);
if (filename == nullptr) {
return;
}
auto* const file = posix::FOpen(filename, "a");
if (file == nullptr) {
return;
}
GTEST_CHECK_(fwrite(str.data(), 1, str.size(), file) == str.size());
GTEST_CHECK_(posix::FClose(file) == 0);
}
#endif // GTEST_HAS_FILE_SYSTEM
// Runs all tests in this UnitTest object, prints the result, and
// returns true if all tests are successful. If any exception is
// thrown during a test, the test is considered to be failed, but the
@ -5896,12 +5918,26 @@ bool UnitTestImpl::RunAllTests() {
// user didn't call InitGoogleTest.
PostFlagParsingInit();
if (GTEST_FLAG_GET(fail_if_no_test_linked) && total_test_count() == 0) {
// Handle the case where the program has no tests linked.
// Sometimes this is a programmer mistake, but sometimes it is intended.
if (total_test_count() == 0) {
constexpr char kNoTestLinkedMessage[] =
"This test program does NOT link in any test case.";
constexpr char kNoTestLinkedFatal[] =
"This is INVALID. Please make sure to link in at least one test case.";
constexpr char kNoTestLinkedWarning[] =
"Please make sure this is intended.";
const bool fail_if_no_test_linked = GTEST_FLAG_GET(fail_if_no_test_linked);
ColoredPrintf(
GTestColor::kRed,
"This test program does NOT link in any test case. This is INVALID. "
"Please make sure to link in at least one test case.\n");
return false;
GTestColor::kRed, "%s %s\n", kNoTestLinkedMessage,
fail_if_no_test_linked ? kNoTestLinkedFatal : kNoTestLinkedWarning);
if (fail_if_no_test_linked) {
return false;
}
#if GTEST_HAS_FILE_SYSTEM
AppendToTestWarningsOutputFile(std::string(kNoTestLinkedMessage) + ' ' +
kNoTestLinkedWarning + '\n');
#endif // GTEST_HAS_FILE_SYSTEM
}
#if GTEST_HAS_FILE_SYSTEM

View File

@ -31,21 +31,26 @@
"""Tests for Google Test's --gtest_fail_if_no_test_linked flag."""
import os
from googletest.test import gtest_test_utils
# The command line flag for enabling the fail-if-no-test-linked behavior.
FAIL_IF_NO_TEST_LINKED_FLAG = "gtest_fail_if_no_test_linked"
# The environment variable for the test output warnings file.
TEST_WARNINGS_OUTPUT_FILE = "TEST_WARNINGS_OUTPUT_FILE"
class GTestFailIfNoTestLinkedTest(gtest_test_utils.TestCase):
"""Tests the --gtest_fail_if_no_test_linked flag."""
def Run(self, program_name, flag=None):
def Run(self, program_name, flag=None, env=None):
"""Run the given program with the given flag.
Args:
program_name: Name of the program to run.
flag: The command line flag to pass to the program, or None.
env: Dictionary with environment to pass to the subprocess.
Returns:
True if the program exits with code 0, false otherwise.
@ -55,59 +60,109 @@ class GTestFailIfNoTestLinkedTest(gtest_test_utils.TestCase):
args = [exe_path]
if flag is not None:
args += [flag]
process = gtest_test_utils.Subprocess(args, capture_stderr=False)
process = gtest_test_utils.Subprocess(args, capture_stderr=False, env=env)
return process.exited and process.exit_code == 0
def testSucceedsIfNoTestLinkedAndFlagNotSpecified(self):
"""Tests the behavior of no test linked and flag not specified."""
self.assertTrue(
self.Run("googletest-fail-if-no-test-linked-test-without-test_")
)
def testSucceedsIfNoTestLinkedAndFlagNotSpecifiedWithWarningFile(self):
"""Tests that no test linked results in warning file output."""
warning_file = os.path.join(gtest_test_utils.GetTempDir(), "NO_TEST_LINKED")
self.assertTrue(
self.Run(
"googletest-fail-if-no-test-linked-test-without-test_",
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
)
)
warning_file_contents = open(warning_file, "r").read()
self.assertEqual(
warning_file_contents,
"This test program does NOT link in any test case. Please make sure"
" this is intended.\n",
)
def testFailsIfNoTestLinkedAndFlagSpecified(self):
"""Tests the behavior of no test linked and flag specified."""
warning_file = os.path.join(
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
)
self.assertFalse(
self.Run(
"googletest-fail-if-no-test-linked-test-without-test_",
f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
)
)
with self.assertRaises(FileNotFoundError):
open(warning_file, "r")
def testSucceedsIfEnabledTestLinkedAndFlagNotSpecified(self):
"""Tests the behavior of enabled test linked and flag not specified."""
self.assertTrue(
self.Run("googletest-fail-if-no-test-linked-test-with-enabled-test_")
warning_file = os.path.join(
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
)
self.assertTrue(
self.Run(
"googletest-fail-if-no-test-linked-test-with-enabled-test_",
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
)
)
with self.assertRaises(FileNotFoundError):
open(warning_file, "r")
def testSucceedsIfEnabledTestLinkedAndFlagSpecified(self):
"""Tests the behavior of enabled test linked and flag specified."""
warning_file = os.path.join(
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
)
self.assertTrue(
self.Run(
"googletest-fail-if-no-test-linked-test-with-enabled-test_",
f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
)
)
with self.assertRaises(FileNotFoundError):
open(warning_file, "r")
def testSucceedsIfDisabledTestLinkedAndFlagNotSpecified(self):
"""Tests the behavior of disabled test linked and flag not specified."""
self.assertTrue(
self.Run("googletest-fail-if-no-test-linked-test-with-disabled-test_")
warning_file = os.path.join(
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
)
self.assertTrue(
self.Run(
"googletest-fail-if-no-test-linked-test-with-disabled-test_",
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
)
)
with self.assertRaises(FileNotFoundError):
open(warning_file, "r")
def testSucceedsIfDisabledTestLinkedAndFlagSpecified(self):
"""Tests the behavior of disabled test linked and flag specified."""
warning_file = os.path.join(
gtest_test_utils.GetTempDir(), "SHOULD_NOT_EXIST"
)
self.assertTrue(
self.Run(
"googletest-fail-if-no-test-linked-test-with-disabled-test_",
f"--{FAIL_IF_NO_TEST_LINKED_FLAG}",
env={TEST_WARNINGS_OUTPUT_FILE: warning_file},
)
)
with self.assertRaises(FileNotFoundError):
open(warning_file, "r")
if __name__ == "__main__":