diff --git a/mobly/asserts.py b/mobly/asserts.py index e877e05f..014847bf 100644 --- a/mobly/asserts.py +++ b/mobly/asserts.py @@ -15,6 +15,7 @@ import re import unittest +from mobly import logger from mobly import signals # Have an instance of unittest.TestCase so we could reuse some logic @@ -23,6 +24,21 @@ _pyunit_proxy.maxDiff = None +def _add_key_frame(extras, action, details): + """Helper to inject key frame data into assertion extras.""" + key_frame_data = { + 'event_type': 'key_frame', + 'action': action, + 'timestamp': logger.get_log_line_timestamp(), + 'details': details, + } + if extras is None: + extras = {} + if isinstance(extras, dict): + extras['key_frame'] = key_frame_data + return extras + + def _call_unittest_assertion( assertion_method, *args, msg=None, extras=None, **kwargs ): @@ -47,6 +63,7 @@ def _call_unittest_assertion( # This raise statement is outside of the above except statement to # prevent Python3's exception message from having two tracebacks. if my_msg is not None: + extras = _add_key_frame(extras, assertion_method.__name__, msg) raise signals.TestFailure(my_msg, extras=extras) @@ -438,6 +455,7 @@ def fail(msg, extras=None): Raises: signals.TestFailure: Mark a test as failed. """ + extras = _add_key_frame(extras, 'fail', msg) raise signals.TestFailure(msg, extras) diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py index f3891335..070f9568 100755 --- a/tests/mobly/base_test_test.py +++ b/tests/mobly/base_test_test.py @@ -585,7 +585,7 @@ def test_something(self): self.assertEqual(actual_record.test_name, self.mock_test_name) self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) self.assertTrue(actual_record.end_time) - self.assertIsNone(actual_record.extras) + self.assertIn('key_frame', actual_record.extras) expected_summary = ( 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0' ) @@ -626,7 +626,7 @@ def test_something(self): actual_record = bt_cls.results.error[0] self.assertEqual(actual_record.test_name, self.mock_test_name) self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) - self.assertIsNone(actual_record.extras) + self.assertIn('key_frame', actual_record.extras) self.assertFalse(actual_record.extra_errors) self.assertTrue(actual_record.end_time) expected_summary = ( @@ -761,7 +761,7 @@ def test_something(self): actual_record = bt_cls.results.failed[0] self.assertEqual(actual_record.test_name, self.mock_test_name) self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) - self.assertIsNone(actual_record.extras) + self.assertIn('key_frame', actual_record.extras) expected_summary = ( 'Error 0, Executed 1, Failed 1, Passed 0, Requested 1, Skipped 0' ) @@ -935,7 +935,7 @@ def test_something(self): self.assertIn('on_fail', actual_record.extra_errors) self.assertEqual(actual_record.test_name, self.mock_test_name) self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION) - self.assertIsNone(actual_record.extras) + self.assertIn('key_frame', actual_record.extras) expected_summary = ( 'Error 0, Executed 1, Failed 1, Passed 0, Requested 1, Skipped 0' ) @@ -985,7 +985,7 @@ def test_something(self): actual_record.extra_errors['teardown_test'].details, MSG_EXPECTED_EXCEPTION, ) - self.assertIsNone(actual_record.extra_errors['teardown_test'].extras) + self.assertIn('key_frame', actual_record.extra_errors['teardown_test'].extras) expected_summary = ( 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0' ) @@ -1059,7 +1059,7 @@ def test_something(self): actual_record.extra_errors['teardown_test'].details, MSG_EXPECTED_EXCEPTION, ) - self.assertIsNone(actual_record.extra_errors['teardown_test'].extras) + self.assertIn('key_frame', actual_record.extra_errors['teardown_test'].extras) expected_summary = ( 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0' ) @@ -2006,7 +2006,7 @@ def test_func(self): actual_record = bt_cls.results.failed[0] self.assertEqual(actual_record.test_name, 'test_func') self.assertEqual(actual_record.details, 'failed from assert_true') - self.assertIsNone(actual_record.extras) + self.assertIn('key_frame', actual_record.extras) def test_unpack_userparams_required(self): """Missing a required param should raise an error."""