Skip to content

Commit

Permalink
Support alias for test classes when using suite. (#467)
Browse files Browse the repository at this point in the history
The same test class can be run with different configs.
To report the same class run with different configs, we need to allow users to specify a suffix to differentiate the runs.
  • Loading branch information
xpconanfan authored Jul 18, 2018
1 parent 5e59f92 commit 6f084fc
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 12 deletions.
8 changes: 6 additions & 2 deletions mobly/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,12 @@ def __init__(self, configs):
configs: A config_parser.TestRunConfig object.
"""
self.tests = []
if not self.TAG:
self.TAG = self.__class__.__name__
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
# Set params.
self.log_path = configs.log_path
self.controller_configs = configs.controller_configs
Expand Down
4 changes: 4 additions & 0 deletions mobly/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ class TestRunConfig(object):
modules.
summary_writer: records.TestSummaryWriter, used to write elements to
the test result summary file.
test_class_name_suffix: string, suffix to append to the class name for
reporting. This is used for differentiating the same class
executed with different parameters in a suite.
"""

def __init__(self):
Expand All @@ -178,6 +181,7 @@ def __init__(self):
self.user_params = None
self.register_controller = None
self.summary_writer = None
self.test_class_name_suffix = None

def copy(self):
"""Returns a deep copy of the current config.
Expand Down
29 changes: 22 additions & 7 deletions mobly/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,14 @@ class _TestRunInfo(object):
run it with.
"""

def __init__(self, config, test_class, tests=None):
def __init__(self,
config,
test_class,
tests=None,
test_class_name_suffix=None):
self.config = config
self.test_class = test_class
self.test_class_name_suffix = test_class_name_suffix
self.tests = tests

def __init__(self, log_dir, test_bed_name):
Expand Down Expand Up @@ -329,7 +334,7 @@ def _teardown_logger(self):
logger.kill_test_logger(logging.getLogger())
self._log_path = None

def add_test_class(self, config, test_class, tests=None):
def add_test_class(self, config, test_class, tests=None, name_suffix=None):
"""Adds tests to the execution plan of this TestRunner.
Args:
Expand All @@ -338,6 +343,9 @@ def add_test_class(self, config, test_class, tests=None):
test_class: class, test class to execute.
tests: list of strings, optional list of test names within the
class to execute.
name_suffix: string, suffix to append to the class name for
reporting. This is used for differentiating the same class
executed with different parameters in a suite.
Raises:
Error: if the provided config has a log_path or test_bed_name which
Expand All @@ -356,7 +364,10 @@ class to execute.
(self._test_bed_name, config.test_bed_name))
self._test_run_infos.append(
TestRunner._TestRunInfo(
config=config, test_class=test_class, tests=tests))
config=config,
test_class=test_class,
tests=tests,
test_class_name_suffix=name_suffix))

def _run_test_class(self, config, test_class, tests=None):
"""Instantiates and executes a test class.
Expand All @@ -370,6 +381,7 @@ def _run_test_class(self, config, test_class, tests=None):
test_class: class, test class to execute.
tests: Optional list of test names within the class to execute.
"""

with test_class(config) as test_instance:
try:
cls_result = test_instance.run(tests)
Expand Down Expand Up @@ -402,9 +414,12 @@ def run(self):
test_config.register_controller = functools.partial(
self._register_controller, test_config)
test_config.summary_writer = summary_writer
test_config.test_class_name_suffix = test_run_info.test_class_name_suffix
try:
self._run_test_class(test_config, test_run_info.test_class,
test_run_info.tests)
self._run_test_class(
config=test_config,
test_class=test_run_info.test_class,
tests=test_run_info.tests)
except signals.TestAbortAll as e:
logging.warning(
'Abort all subsequent test classes. Reason: %s', e)
Expand Down Expand Up @@ -513,8 +528,8 @@ def _register_controller(self, config, module, required=True,
logging.warning('No optional debug info found for controller %s. '
'To provide it, implement get_info in this '
'controller module.', module_config_name)
logging.debug('Found %d objects for controller %s',
len(objects), module_config_name)
logging.debug('Found %d objects for controller %s', len(objects),
module_config_name)
destroy_func = module.destroy
self._controller_destructors[module_ref_name] = destroy_func
return objects
Expand Down
21 changes: 18 additions & 3 deletions tests/mobly/test_runner_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,13 @@ def test_run_two_test_classes(self, mock_get_all, mock_list_adb,
self.assertEqual(results['Requested'], 2)
self.assertEqual(results['Executed'], 2)
self.assertEqual(results['Passed'], 2)
# Tag of the test class defaults to the class name.
record1 = tr.results.executed[0]
record2 = tr.results.executed[1]
self.assertEqual(record1.test_class, 'Integration2Test')
self.assertEqual(record2.test_class, 'IntegrationTest')

def test_run_two_test_classes_different_configs(self):
def test_run_two_test_classes_different_configs_and_aliases(self):
"""Verifies that running more than one test class in one test run with
different configs works properly.
"""
Expand All @@ -272,15 +277,25 @@ def test_run_two_test_classes_different_configs(self):
config2 = config1.copy()
config2.user_params['icecream'] = 10
tr = test_runner.TestRunner(self.log_dir, self.test_bed_name)
tr.add_test_class(config1, integration_test.IntegrationTest)
tr.add_test_class(config2, integration_test.IntegrationTest)
tr.add_test_class(
config1,
integration_test.IntegrationTest,
name_suffix='FirstConfig')
tr.add_test_class(
config2,
integration_test.IntegrationTest,
name_suffix='SecondConfig')
tr.run()
results = tr.results.summary_dict()
self.assertEqual(results['Requested'], 2)
self.assertEqual(results['Executed'], 2)
self.assertEqual(results['Passed'], 1)
self.assertEqual(results['Failed'], 1)
self.assertEqual(tr.results.failed[0].details, '10 != 42')
record1 = tr.results.executed[0]
record2 = tr.results.executed[1]
self.assertEqual(record1.test_class, 'IntegrationTest_FirstConfig')
self.assertEqual(record2.test_class, 'IntegrationTest_SecondConfig')

def test_run_with_abort_all(self):
mock_test_config = self.base_mock_test_config.copy()
Expand Down

0 comments on commit 6f084fc

Please sign in to comment.