Log path changes in `BaseTestClass`. (#650)
* Add a new level of output directoy specific to test classes.
* Direct `log_path` to class-specific.
* Add a `root_output_path` pointing to the test run path
(what `log_path` used to point to)
diff --git a/mobly/base_test.py b/mobly/base_test.py
index 2d386b1..90ff75a 100644
--- a/mobly/base_test.py
+++ b/mobly/base_test.py
@@ -18,6 +18,7 @@
import functools
import inspect
import logging
+import os
from future.utils import raise_with_traceback
@@ -71,8 +72,11 @@
test bed config.
current_test_info: RuntimeTestInfo, runtime information on the test
currently being executed.
- log_path: string, specifies the root directory for all logs written
- by a test run.
+ root_output_path: string, storage path for output files associated with
+ the entire test run. A test run can have multiple test class
+ executions. This includes the test summary and Mobly log files.
+ log_path: string, storage path for files specific to a single test
+ class execution.
test_bed_name: [Deprecated, use 'testbed_name' instead]
string, the name of the test bed used by a test run.
testbed_name: string, the name of the test bed used by a test run.
@@ -94,14 +98,16 @@
configs: A config_parser.TestRunConfig object.
"""
self.tests = []
- self._class_name = self.__class__.__name__
- if configs.test_class_name_suffix and self.TAG is None:
- self.TAG = '%s_%s' % (self._class_name,
- configs.test_class_name_suffix)
- elif self.TAG is None:
- self.TAG = self._class_name
+ class_identifier = self.__class__.__name__
+ if configs.test_class_name_suffix:
+ class_identifier = '%s_%s' % (class_identifier,
+ configs.test_class_name_suffix)
+ if self.TAG is None:
+ self.TAG = class_identifier
# Set params.
- self.log_path = configs.log_path
+ self.root_output_path = configs.log_path
+ self.log_path = os.path.join(self.root_output_path, class_identifier)
+ utils.create_dir(self.log_path)
# Deprecated, use 'testbed_name'
self.test_bed_name = configs.test_bed_name
self.testbed_name = configs.testbed_name
@@ -809,6 +815,7 @@
Returns:
The test results object of this class.
"""
+ logging.log_path = self.log_path
# Executes pre-setup procedures, like generating test methods.
if not self._setup_generated_tests():
return self.results
diff --git a/mobly/logger.py b/mobly/logger.py
index b3a0fb7..74f76fe 100644
--- a/mobly/logger.py
+++ b/mobly/logger.py
@@ -211,6 +211,7 @@
log.addHandler(fh_debug)
log.log_path = log_path
logging.log_path = log_path
+ logging.root_output_path = log_path
def kill_test_logger(logger):
@@ -241,6 +242,14 @@
def setup_test_logger(log_path, prefix=None, alias='latest'):
"""Customizes the root logger for a test run.
+ In addition to configuring the Mobly logging handlers, this also sets two
+ attributes on the `logging` module for the output directories:
+
+ root_output_path: path to the directory for the entire test run.
+ log_path: same as `root_output_path` outside of a test class run. In the
+ context of a test class run, this is the output directory for files
+ specific to a test class.
+
Args:
log_path: string, the location of the report file.
prefix: optional string, a prefix for each log line in terminal.
diff --git a/mobly/test_runner.py b/mobly/test_runner.py
index 269a6e4..05cd36b 100644
--- a/mobly/test_runner.py
+++ b/mobly/test_runner.py
@@ -189,10 +189,12 @@
self.results: The test result object used to record the results of
this test run.
"""
+
class _TestRunInfo(object):
"""Identifies one test class to run, which tests to run, and config to
run it with.
"""
+
def __init__(self,
config,
test_class,
@@ -223,8 +225,9 @@
def _update_log_path(self):
"""Updates the logging values with the current timestamp."""
self._start_time = logger.get_log_file_timestamp()
- self._log_path = os.path.join(self._log_dir, self._testbed_name,
- self._start_time)
+ self._root_output_path = os.path.join(self._log_dir,
+ self._testbed_name,
+ self._start_time)
@contextlib.contextmanager
def mobly_logger(self, alias='latest'):
@@ -239,11 +242,11 @@
The host file path where the logs for the test run are stored.
"""
self._update_log_path()
- logger.setup_test_logger(self._log_path,
+ logger.setup_test_logger(self._root_output_path,
self._testbed_name,
alias=alias)
try:
- yield self._log_path
+ yield self._root_output_path
finally:
logger.kill_test_logger(logging.getLogger())
@@ -318,15 +321,15 @@
# Ensure the log path exists. Necessary if `run` is used outside of the
# `mobly_logger` context.
- utils.create_dir(self._log_path)
+ utils.create_dir(self._root_output_path)
summary_writer = records.TestSummaryWriter(
- os.path.join(self._log_path, records.OUTPUT_FILE_SUMMARY))
+ os.path.join(self._root_output_path, records.OUTPUT_FILE_SUMMARY))
try:
for test_run_info in self._test_run_infos:
# Set up the test-specific config
test_config = test_run_info.config.copy()
- test_config.log_path = self._log_path
+ test_config.log_path = self._root_output_path
test_config.summary_writer = summary_writer
test_config.test_class_name_suffix = test_run_info.test_class_name_suffix
try:
diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py
index 03c929c..6eb7149 100755
--- a/tests/mobly/base_test_test.py
+++ b/tests/mobly/base_test_test.py
@@ -65,6 +65,23 @@
def tearDown(self):
shutil.rmtree(self.tmp_dir)
+ def test_paths(self):
+ '''Checks the output paths set in `BaseTestClass`.'''
+ path_checker = mock.MagicMock()
+
+ class MockBaseTest(base_test.BaseTestClass):
+ def test_func(self):
+ path_checker.log_path = self.log_path
+ path_checker.root_output_path = self.root_output_path
+
+ bt_cls = MockBaseTest(self.mock_test_cls_configs)
+ bt_cls.run(test_names=["test_func"])
+ self.assertEqual(path_checker.root_output_path, self.tmp_dir)
+ self.assertTrue(os.path.exists(path_checker.root_output_path))
+ expected_log_path = os.path.join(self.tmp_dir, 'MockBaseTest')
+ self.assertEqual(path_checker.log_path, expected_log_path)
+ self.assertTrue(os.path.exists(path_checker.log_path))
+
def test_current_test_name(self):
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -2176,7 +2193,7 @@
pass
def test_log_stage_always_logs_end_statement(self):
- instance = base_test.BaseTestClass(mock.Mock())
+ instance = base_test.BaseTestClass(self.mock_test_cls_configs)
instance.current_test_info = mock.Mock()
instance.current_test_info.name = 'TestClass'
diff --git a/tests/mobly/output_test.py b/tests/mobly/output_test.py
index 28a9808..6a8facb 100755
--- a/tests/mobly/output_test.py
+++ b/tests/mobly/output_test.py
@@ -40,6 +40,7 @@
"""This test class has unit tests for the implementation of Mobly's output
files.
"""
+
def setUp(self):
self.tmp_dir = tempfile.mkdtemp()
self.base_mock_test_config = config_parser.TestRunConfig()
@@ -195,7 +196,7 @@
tr.add_test_class(mock_test_config,
integration_test.IntegrationTest)
tr.run()
- output_dir = logging.log_path
+ output_dir = logging.root_output_path
(summary_file_path, debug_log_path,
info_log_path) = self.assert_output_logs_exist(output_dir)
self.assert_log_contents(debug_log_path,
@@ -218,10 +219,10 @@
tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
with tr.mobly_logger():
tr.run()
- output_dir1 = logging.log_path
+ output_dir1 = logging.root_output_path
with tr.mobly_logger():
tr.run()
- output_dir2 = logging.log_path
+ output_dir2 = logging.root_output_path
self.assertNotEqual(output_dir1, output_dir2)
self.assert_output_logs_exist(output_dir1)
self.assert_output_logs_exist(output_dir2)
@@ -279,7 +280,11 @@
tr.add_test_class(mock_test_config,
integration_test.IntegrationTest)
tr.run()
- output_dir = logging.log_path
+ expected_class_path = os.path.join(logging.root_output_path,
+ 'IntegrationTest')
+ self.assertEqual(expected_class_path, logging.log_path)
+ os.path.exists(logging.log_path)
+ output_dir = logging.root_output_path
(summary_file_path, debug_log_path,
info_log_path) = self.assert_output_logs_exist(output_dir)
summary_entries = []
@@ -303,7 +308,7 @@
mock_test_config,
teardown_class_failure_test.TearDownClassFailureTest)
tr.run()
- output_dir = logging.log_path
+ output_dir = logging.root_output_path
summary_file_path = os.path.join(output_dir,
records.OUTPUT_FILE_SUMMARY)
found = False
diff --git a/tests/mobly/test_runner_test.py b/tests/mobly/test_runner_test.py
index fafdbe1..8d65336 100755
--- a/tests/mobly/test_runner_test.py
+++ b/tests/mobly/test_runner_test.py
@@ -39,6 +39,7 @@
"""This test class has unit tests for the implementation of everything
under mobly.test_runner.
"""
+
def setUp(self):
self.tmp_dir = tempfile.mkdtemp()
self.base_mock_test_config = config_parser.TestRunConfig()
@@ -134,7 +135,7 @@
tr.add_test_class(mock_test_config,
integration_test.IntegrationTest)
tr.run()
- summary_path = os.path.join(logging.log_path,
+ summary_path = os.path.join(logging.root_output_path,
records.OUTPUT_FILE_SUMMARY)
with io.open(summary_path, 'r', encoding='utf-8') as f:
summary_entries = list(yaml.safe_load_all(f))