summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--googletest/src/gtest.cc210
-rw-r--r--googletest/test/gtest_list_output_unittest.py141
-rw-r--r--googletest/test/gtest_list_output_unittest_.cc51
-rw-r--r--googletest/test/gtest_unittest.cc4
4 files changed, 333 insertions, 73 deletions
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index e9127a1..f476044 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -194,6 +194,21 @@ const char kStackTraceMarker[] = "\nStack trace:\n";
// specified on the command line.
bool g_help_flag = false;
+// Utilty function to Open File for Writing
+static FILE* OpenFileForWriting(const std::string& output_file) {
+ FILE* fileout = NULL;
+ FilePath output_file_path(output_file);
+ FilePath output_dir(output_file_path.RemoveFileName());
+
+ if (output_dir.CreateDirectoriesRecursively()) {
+ fileout = posix::FOpen(output_file.c_str(), "w");
+ }
+ if (fileout == NULL) {
+ GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\"";
+ }
+ return fileout;
+}
+
} // namespace internal
// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY
@@ -454,6 +469,7 @@ std::string UnitTestOptions::GetOutputFormat() {
// Returns the name of the requested output file, or the default if none
// was explicitly specified.
+// FIXME Remove GetAbsolutePathToOutputFile checking gtest_output_flag == NULL
std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
if (gtest_output_flag == NULL)
@@ -2130,13 +2146,8 @@ static const char* const kReservedTestSuiteAttributes[] = {
// The list of reserved attributes used in the <testcase> element of XML output.
static const char* const kReservedTestCaseAttributes[] = {
- "classname",
- "name",
- "status",
- "time",
- "type_param",
- "value_param"
-};
+ "classname", "name", "status", "time",
+ "type_param", "value_param", "file", "line"};
template <int kSize>
std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
@@ -3414,6 +3425,11 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
explicit XmlUnitTestResultPrinter(const char* output_file);
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ void ListTestsMatchingFilter(const std::vector<TestCase*>& test_cases);
+
+ // Prints an XML summary of all unit tests.
+ static void PrintXmlTestsList(std::ostream* stream,
+ const std::vector<TestCase*>& test_cases);
private:
// Is c a whitespace character that is normalized to a space character
@@ -3497,33 +3513,22 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
// Called after the unit test ends.
void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) {
- FILE* xmlout = NULL;
- FilePath output_file(output_file_);
- FilePath output_dir(output_file.RemoveFileName());
-
- if (output_dir.CreateDirectoriesRecursively()) {
- xmlout = posix::FOpen(output_file_.c_str(), "w");
- }
- if (xmlout == NULL) {
- // FIXME: report the reason of the failure.
- //
- // We don't do it for now as:
- //
- // 1. There is no urgent need for it.
- // 2. It's a bit involved to make the errno variable thread-safe on
- // all three operating systems (Linux, Windows, and Mac OS).
- // 3. To interpret the meaning of errno in a thread-safe way,
- // we need the strerror_r() function, which is not available on
- // Windows.
-
- GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file_ << "\"";
- }
+ FILE* xmlout = OpenFileForWriting(output_file_);
std::stringstream stream;
PrintXmlUnitTest(&stream, unit_test);
fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
fclose(xmlout);
}
+void XmlUnitTestResultPrinter::ListTestsMatchingFilter(
+ const std::vector<TestCase*>& test_cases) {
+ FILE* xmlout = OpenFileForWriting(output_file_);
+ std::stringstream stream;
+ PrintXmlTestsList(&stream, test_cases);
+ fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+ fclose(xmlout);
+}
+
// Returns an XML-escaped copy of the input string str. If is_attribute
// is true, the text is meant to appear as an attribute value, and
// normalizable whitespace is preserved by replacing it with character
@@ -3706,6 +3711,13 @@ void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
if (test_info.type_param() != NULL) {
OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param());
}
+ if (GTEST_FLAG(list_tests)) {
+ OutputXmlAttribute(stream, kTestcase, "file", test_info.file());
+ OutputXmlAttribute(stream, kTestcase, "line",
+ StreamableToString(test_info.line()));
+ *stream << " />\n";
+ return;
+ }
OutputXmlAttribute(stream, kTestcase, "status",
test_info.should_run() ? "run" : "notrun");
@@ -3752,17 +3764,18 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
OutputXmlAttribute(stream, kTestsuite, "name", test_case.name());
OutputXmlAttribute(stream, kTestsuite, "tests",
StreamableToString(test_case.reportable_test_count()));
- OutputXmlAttribute(stream, kTestsuite, "failures",
- StreamableToString(test_case.failed_test_count()));
- OutputXmlAttribute(
- stream, kTestsuite, "disabled",
- StreamableToString(test_case.reportable_disabled_test_count()));
- OutputXmlAttribute(stream, kTestsuite, "errors", "0");
- OutputXmlAttribute(stream, kTestsuite, "time",
- FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
- *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result())
- << ">\n";
-
+ if (!GTEST_FLAG(list_tests)) {
+ OutputXmlAttribute(stream, kTestsuite, "failures",
+ StreamableToString(test_case.failed_test_count()));
+ OutputXmlAttribute(
+ stream, kTestsuite, "disabled",
+ StreamableToString(test_case.reportable_disabled_test_count()));
+ OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+ OutputXmlAttribute(stream, kTestsuite, "time",
+ FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
+ *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result());
+ }
+ *stream << ">\n";
for (int i = 0; i < test_case.total_test_count(); ++i) {
if (test_case.GetTestInfo(i)->is_reportable())
OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
@@ -3808,6 +3821,28 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
*stream << "</" << kTestsuites << ">\n";
}
+void XmlUnitTestResultPrinter::PrintXmlTestsList(
+ std::ostream* stream, const std::vector<TestCase*>& test_cases) {
+ const std::string kTestsuites = "testsuites";
+
+ *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ *stream << "<" << kTestsuites;
+
+ int total_tests = 0;
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ total_tests += test_cases[i]->total_test_count();
+ }
+ OutputXmlAttribute(stream, kTestsuites, "tests",
+ StreamableToString(total_tests));
+ OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+ *stream << ">\n";
+
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ PrintXmlTestCase(stream, *test_cases[i]);
+ }
+ *stream << "</" << kTestsuites << ">\n";
+}
+
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
@@ -3843,7 +3878,6 @@ void XmlUnitTestResultPrinter::OutputXmlTestProperties(
// End XmlUnitTestResultPrinter
-
// This class generates an JSON output file.
class JsonUnitTestResultPrinter : public EmptyTestEventListener {
public:
@@ -3851,6 +3885,10 @@ class JsonUnitTestResultPrinter : public EmptyTestEventListener {
virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+ // Prints an JSON summary of all unit tests.
+ static void PrintJsonTestList(::std::ostream* stream,
+ const std::vector<TestCase*>& test_cases);
+
private:
// Returns an JSON-escaped copy of the input string str.
static std::string EscapeJson(const std::string& str);
@@ -3904,27 +3942,7 @@ JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file)
void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
int /*iteration*/) {
- FILE* jsonout = NULL;
- FilePath output_file(output_file_);
- FilePath output_dir(output_file.RemoveFileName());
-
- if (output_dir.CreateDirectoriesRecursively()) {
- jsonout = posix::FOpen(output_file_.c_str(), "w");
- }
- if (jsonout == NULL) {
- // FIXME: report the reason of the failure.
- //
- // We don't do it for now as:
- //
- // 1. There is no urgent need for it.
- // 2. It's a bit involved to make the errno variable thread-safe on
- // all three operating systems (Linux, Windows, and Mac OS).
- // 3. To interpret the meaning of errno in a thread-safe way,
- // we need the strerror_r() function, which is not available on
- // Windows.
- GTEST_LOG_(FATAL) << "Unable to open file \""
- << output_file_ << "\"";
- }
+ FILE* jsonout = OpenFileForWriting(output_file_);
std::stringstream stream;
PrintJsonUnitTest(&stream, unit_test);
fprintf(jsonout, "%s", StringStreamToString(&stream).c_str());
@@ -4059,6 +4077,12 @@ void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
OutputJsonKey(stream, kTestcase, "type_param", test_info.type_param(),
kIndent);
}
+ if (GTEST_FLAG(list_tests)) {
+ OutputJsonKey(stream, kTestcase, "file", test_info.file(), kIndent);
+ OutputJsonKey(stream, kTestcase, "line", test_info.line(), kIndent, false);
+ *stream << "\n" << Indent(8) << "}";
+ return;
+ }
OutputJsonKey(stream, kTestcase, "status",
test_info.should_run() ? "RUN" : "NOTRUN", kIndent);
@@ -4101,16 +4125,18 @@ void JsonUnitTestResultPrinter::PrintJsonTestCase(std::ostream* stream,
OutputJsonKey(stream, kTestsuite, "name", test_case.name(), kIndent);
OutputJsonKey(stream, kTestsuite, "tests", test_case.reportable_test_count(),
kIndent);
- OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(),
- kIndent);
- OutputJsonKey(stream, kTestsuite, "disabled",
- test_case.reportable_disabled_test_count(), kIndent);
- OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
- OutputJsonKey(stream, kTestsuite, "time",
- FormatTimeInMillisAsDuration(test_case.elapsed_time()), kIndent,
- false);
- *stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent)
- << ",\n";
+ if (!GTEST_FLAG(list_tests)) {
+ OutputJsonKey(stream, kTestsuite, "failures", test_case.failed_test_count(),
+ kIndent);
+ OutputJsonKey(stream, kTestsuite, "disabled",
+ test_case.reportable_disabled_test_count(), kIndent);
+ OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
+ OutputJsonKey(stream, kTestsuite, "time",
+ FormatTimeInMillisAsDuration(test_case.elapsed_time()),
+ kIndent, false);
+ *stream << TestPropertiesAsJson(test_case.ad_hoc_test_result(), kIndent)
+ << ",\n";
+ }
*stream << kIndent << "\"" << kTestsuite << "\": [\n";
@@ -4174,6 +4200,31 @@ void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,
*stream << "\n" << kIndent << "]\n" << "}\n";
}
+void JsonUnitTestResultPrinter::PrintJsonTestList(
+ std::ostream* stream, const std::vector<TestCase*>& test_cases) {
+ const std::string kTestsuites = "testsuites";
+ const std::string kIndent = Indent(2);
+ *stream << "{\n";
+ int total_tests = 0;
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ total_tests += test_cases[i]->total_test_count();
+ }
+ OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent);
+
+ OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
+ *stream << kIndent << "\"" << kTestsuites << "\": [\n";
+
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ if (i != 0) {
+ *stream << ",\n";
+ }
+ PrintJsonTestCase(stream, *test_cases[i]);
+ }
+
+ *stream << "\n"
+ << kIndent << "]\n"
+ << "}\n";
+}
// Produces a string representing the test properties in a result as
// a JSON dictionary.
std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
@@ -5394,6 +5445,23 @@ void UnitTestImpl::ListTestsMatchingFilter() {
}
}
fflush(stdout);
+ const std::string& output_format = UnitTestOptions::GetOutputFormat();
+ if (output_format == "xml" || output_format == "json") {
+ FILE* fileout = OpenFileForWriting(
+ UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
+ std::stringstream stream;
+ if (output_format == "xml") {
+ XmlUnitTestResultPrinter(
+ UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
+ .PrintXmlTestsList(&stream, test_cases_);
+ } else if (output_format == "json") {
+ JsonUnitTestResultPrinter(
+ UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
+ .PrintJsonTestList(&stream, test_cases_);
+ }
+ fprintf(fileout, "%s", StringStreamToString(&stream).c_str());
+ fclose(fileout);
+ }
}
// Sets the OS stack trace getter.
diff --git a/googletest/test/gtest_list_output_unittest.py b/googletest/test/gtest_list_output_unittest.py
new file mode 100644
index 0000000..3bba7ea
--- /dev/null
+++ b/googletest/test/gtest_list_output_unittest.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+#
+# Copyright 2006, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Unit test for Google Test's --gtest_list_tests flag.
+
+A user can ask Google Test to list all tests by specifying the
+--gtest_list_tests flag. If output is requested, via --gtest_output=xml
+or --gtest_output=json, the tests are listed, with extra information in the
+output file.
+This script tests such functionality by invoking gtest_list_output_unittest_
+ (a program written with Google Test) the command line flags.
+"""
+
+import os
+import re
+import gtest_test_utils
+
+GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
+GTEST_OUTPUT_FLAG = '--gtest_output'
+
+EXPECTED_XML = """<\?xml version="1.0" encoding="UTF-8"\?>
+<testsuites tests="2" name="AllTests">
+ <testsuite name="FooTest" tests="2">
+ <testcase name="Test1" file=".*gtest_list_output_unittest_.cc" line="43" />
+ <testcase name="Test2" file=".*gtest_list_output_unittest_.cc" line="45" />
+ </testsuite>
+</testsuites>
+"""
+
+EXPECTED_JSON = """{
+ "tests": 2,
+ "name": "AllTests",
+ "testsuites": \[
+ {
+ "name": "FooTest",
+ "tests": 2,
+ "testsuite": \[
+ {
+ "name": "Test1",
+ "file": ".*gtest_list_output_unittest_.cc",
+ "line": 43
+ },
+ {
+ "name": "Test2",
+ "file": ".*gtest_list_output_unittest_.cc",
+ "line": 45
+ }
+ \]
+ }
+ \]
+}
+"""
+
+
+class GTestListTestsOutputUnitTest(gtest_test_utils.TestCase):
+ """Unit test for Google Test's list tests with output to file functionality.
+ """
+
+ def testXml(self):
+ """Verifies XML output for listing tests in a Google Test binary.
+
+ Runs a test program that generates an empty XML output, and
+ tests that the XML output is expected.
+ """
+ self._TestOutput('xml', EXPECTED_XML)
+
+ def testJSON(self):
+ """Verifies XML output for listing tests in a Google Test binary.
+
+ Runs a test program that generates an empty XML output, and
+ tests that the XML output is expected.
+ """
+ self._TestOutput('json', EXPECTED_JSON)
+
+ def _GetOutput(self, out_format):
+ file_path = os.path.join(gtest_test_utils.GetTempDir(),
+ 'test_out.' + out_format)
+ gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
+ 'gtest_list_output_unittest_')
+
+ command = ([
+ gtest_prog_path,
+ '%s=%s:%s' % (GTEST_OUTPUT_FLAG, out_format, file_path),
+ '--gtest_list_tests'
+ ])
+ environ_copy = os.environ.copy()
+ p = gtest_test_utils.Subprocess(
+ command, env=environ_copy, working_dir=gtest_test_utils.GetTempDir())
+
+ self.assert_(p.exited)
+ self.assertEquals(0, p.exit_code)
+ with open(file_path) as f:
+ result = f.read()
+ return result
+
+ def _TestOutput(self, test_format, expected_output):
+ actual = self._GetOutput(test_format)
+ actual_lines = actual.splitlines()
+ expected_lines = expected_output.splitlines()
+ line_count = 0
+ for actual_line in actual_lines:
+ expected_line = expected_lines[line_count]
+ expected_line_re = re.compile(expected_line.strip())
+ self.assert_(
+ expected_line_re.match(actual_line.strip()),
+ ('actual output of "%s",\n'
+ 'which does not match expected regex of "%s"\n'
+ 'on line %d' % (actual, expected_output, line_count)))
+ line_count = line_count + 1
+
+
+if __name__ == '__main__':
+ os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
+ gtest_test_utils.Main()
diff --git a/googletest/test/gtest_list_output_unittest_.cc b/googletest/test/gtest_list_output_unittest_.cc
new file mode 100644
index 0000000..b1c7b4d
--- /dev/null
+++ b/googletest/test/gtest_list_output_unittest_.cc
@@ -0,0 +1,51 @@
+// Copyright 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: david.schuldenfrei@gmail.com (David Schuldenfrei)
+
+// Unit test for Google Test's --gtest_list_tests and --gtest_output flag.
+//
+// A user can ask Google Test to list all tests that will run,
+// and have the output saved in a Json/Xml file.
+// The tests will not be run after listing.
+//
+// This program will be invoked from a Python unit test.
+// Don't run it directly.
+
+#include "gtest/gtest.h"
+
+TEST(FooTest, Test1) {}
+
+TEST(FooTest, Test2) {}
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc
index e1c30f3..f7213fb 100644
--- a/googletest/test/gtest_unittest.cc
+++ b/googletest/test/gtest_unittest.cc
@@ -2090,8 +2090,8 @@ TEST_F(UnitTestRecordPropertyTest,
AddRecordWithReservedKeysGeneratesCorrectPropertyList) {
EXPECT_NONFATAL_FAILURE(
Test::RecordProperty("name", "1"),
- "'classname', 'name', 'status', 'time', 'type_param', and 'value_param'"
- " are reserved");
+ "'classname', 'name', 'status', 'time', 'type_param', 'value_param',"
+ " 'file', and 'line' are reserved");
}
class UnitTestRecordPropertyTestEnvironment : public Environment {