Merge "Test runner can now gather info without running"
diff --git a/acts/framework/acts/base_test.py b/acts/framework/acts/base_test.py
index 2e70b03..d06aec4 100755
--- a/acts/framework/acts/base_test.py
+++ b/acts/framework/acts/base_test.py
@@ -267,6 +267,28 @@
             begin_time: Logline format timestamp taken when the test started.
         """
 
+    def _on_blocked(self, record):
+        """Proxy function to guarantee the base implementation of on_blocked
+        is called.
+
+        Args:
+            record: The records.TestResultRecord object for the blocked test
+                    case.
+        """
+        test_name = record.test_name
+        begin_time = logger.epoch_to_log_line_timestamp(record.begin_time)
+        self.log.info(RESULT_LINE_TEMPLATE, test_name, record.result)
+        self.log.info("Reason to block: %s", record.details)
+        self.on_blocked(test_name, begin_time)
+
+    def on_blocked(self, test_name, begin_time):
+        """A function that is executed upon a test begin skipped.
+
+        Args:
+            test_name: Name of the test that triggered this function.
+            begin_time: Logline format timestamp taken when the test started.
+        """
+
     def _on_exception(self, record):
         """Proxy function to guarantee the base implementation of on_exception
         is called.
@@ -374,6 +396,9 @@
             # This is a trigger test for generated tests, suppress reporting.
             is_generate_trigger = True
             self.results.requested.remove(test_name)
+        except signals.TestBlocked as e:
+            tr_record.test_blocked(e)
+            self._exec_procedure_func(self._on_blocked, tr_record)
         except Exception as e:
             self.log.error(traceback.format_exc())
             # Exception happened during test.
@@ -518,16 +543,51 @@
         """
         test_funcs = []
         for test_name in test_names:
-            if not test_name.startswith("test_"):
-                raise Error(("Test case name %s does not follow naming "
-                             "convention test_*, abort.") % test_name)
-            try:
-                test_funcs.append((test_name, getattr(self, test_name)))
-            except AttributeError:
-                raise Error("%s does not have test case %s." % (self.TAG,
-                                                                test_name))
+            test_funcs.append(self._get_test_func(test_name))
+
         return test_funcs
 
+    def _get_test_func(self, test_name):
+        """Obtain the actual function of test cases based on the test name.
+
+        Args:
+            test_name: String, The name of the test.
+
+        Returns:
+            A tuples of (string, function). String is the test case
+            name, function is the actual test case function.
+
+        Raises:
+            Error is raised if the test name does not follow
+            naming convention "test_*". This can only be caused by user input
+            here.
+        """
+        if not test_name.startswith("test_"):
+            raise Error(("Test case name %s does not follow naming "
+                         "convention test_*, abort.") % test_name)
+
+        try:
+            return test_name, getattr(self, test_name)
+        except:
+            raise Error("%s does not have test case %s." % (self.TAG,
+                                                            test_name))
+
+    def _block_all_test_cases(self, tests):
+        """
+        Block all passed in test cases.
+        Args:
+            tests: The tests to block.
+        """
+        for test_name, test_func in tests:
+            signal = signals.TestBlocked("Failed class setup")
+            record = records.TestResultRecord(test_name, self.TAG)
+            record.test_begin()
+            if hasattr(test_func, 'gather'):
+                signal.extras = test_func.gather()
+            record.test_blocked(signal)
+            self.results.add_record(record)
+            self._on_blocked(record)
+
     def run(self, test_names=None):
         """Runs test cases within a test class by the order they appear in the
         execution list.
@@ -560,24 +620,16 @@
         self.results.requested = test_names
         tests = self._get_test_funcs(test_names)
         # A TestResultRecord used for when setup_class fails.
-        class_record = records.TestResultRecord("setup_class", self.TAG)
-        class_record.test_begin()
         # Setup for the class.
         try:
             if self._setup_class() is False:
-                asserts.fail("Failed to setup %s." % self.TAG)
-        except signals.TestSkipClass as e:
-            class_record.test_skip(e)
-            self._exec_procedure_func(self._on_skip, class_record)
-            self._exec_func(self.teardown_class)
-            self.results.skip_class(class_record)
-            return self.results
+                self.log.error("Failed to setup %s.", self.TAG)
+                self._block_all_test_cases(tests)
+                return self.results
         except Exception as e:
             self.log.exception("Failed to setup %s.", self.TAG)
-            class_record.test_fail(e)
-            self._exec_procedure_func(self._on_fail, class_record)
             self._exec_func(self.teardown_class)
-            self.results.fail_class(class_record)
+            self._block_all_test_cases(tests)
             return self.results
         # Run tests in order.
         try:
diff --git a/acts/framework/acts/records.py b/acts/framework/acts/records.py
index 56eaf97..9b9a1c6 100644
--- a/acts/framework/acts/records.py
+++ b/acts/framework/acts/records.py
@@ -43,6 +43,7 @@
     TEST_RESULT_PASS = "PASS"
     TEST_RESULT_FAIL = "FAIL"
     TEST_RESULT_SKIP = "SKIP"
+    TEST_RESULT_BLOCKED = "BLOCKED"
     TEST_RESULT_UNKNOWN = "UNKNOWN"
 
 
@@ -124,6 +125,14 @@
         """
         self._test_end(TestResultEnums.TEST_RESULT_SKIP, e)
 
+    def test_blocked(self, e=None):
+        """To mark the test as blocked in this record.
+
+        Args:
+            e: An instance of acts.signals.Test
+        """
+        self._test_end(TestResultEnums.TEST_RESULT_BLOCKED, e)
+
     def test_unknown(self, e=None):
         """To mark the test as unknown in this record.
 
@@ -213,6 +222,7 @@
         self.executed = []
         self.passed = []
         self.skipped = []
+        self.blocked = []
         self.unknown = []
         self.controller_info = {}
 
@@ -263,14 +273,18 @@
         Args:
             record: A test record object to add.
         """
-        self.executed.append(record)
         if record.result == TestResultEnums.TEST_RESULT_FAIL:
+            self.executed.append(record)
             self.failed.append(record)
         elif record.result == TestResultEnums.TEST_RESULT_SKIP:
             self.skipped.append(record)
         elif record.result == TestResultEnums.TEST_RESULT_PASS:
+            self.executed.append(record)
             self.passed.append(record)
+        elif record.result == TestResultEnums.TEST_RESULT_BLOCKED:
+            self.blocked.append(record)
         else:
+            self.executed.append(record)
             self.unknown.append(record)
 
     def add_controller_info(self, name, info):
@@ -283,29 +297,11 @@
             return
         self.controller_info[name] = info
 
-    def fail_class(self, test_record):
-        """Add a record to indicate a test class setup has failed and no test
-        in the class was executed.
-
-        Args:
-            test_record: A TestResultRecord object for the test class.
-        """
-        self.executed.append(test_record)
-        self.failed.append(test_record)
-
-    def skip_class(self, test_record):
-        """Add a record to indicate a test class setup has skipped and no test
-        in the class was executed.
-
-        Args:
-            test_record: A TestResultRecord object for the test class.
-        """
-        self.skipped.append(test_record)
-
     @property
     def is_all_pass(self):
         """True if no tests failed or threw errors, False otherwise."""
-        num_of_failures = len(self.failed) + len(self.unknown)
+        num_of_failures = (
+            len(self.failed) + len(self.unknown) + len(self.blocked))
         if num_of_failures == 0:
             return True
         return False
@@ -366,5 +362,6 @@
         d["Passed"] = len(self.passed)
         d["Failed"] = len(self.failed)
         d["Skipped"] = len(self.skipped)
+        d["Blocked"] = len(self.blocked)
         d["Unknown"] = len(self.unknown)
         return d
diff --git a/acts/framework/acts/signals.py b/acts/framework/acts/signals.py
index e82fa95..49be989 100644
--- a/acts/framework/acts/signals.py
+++ b/acts/framework/acts/signals.py
@@ -77,6 +77,10 @@
     """Raised when a test has been skipped."""
 
 
+class TestBlocked(TestSignal):
+    """Raised when a test has been blocked from running."""
+
+
 class TestSkipClass(TestSignal):
     """Raised in setup_class when a whole test class should be skipped."""
 
diff --git a/acts/framework/acts/test_decorators.py b/acts/framework/acts/test_decorators.py
index b7763f5..20c1383 100644
--- a/acts/framework/acts/test_decorators.py
+++ b/acts/framework/acts/test_decorators.py
@@ -37,35 +37,9 @@
         **keyed_info: The key, value info to include in the extras for this
                       test.
     """
+
     def test_info_decoractor(func):
-        def func_wrapper(*args, **kwargs):
-            try:
-                result = func(*args, **kwargs)
-                if result or result is None:
-                    new_signal = signals.TestPass('')
-                else:
-                    new_signal = signals.TestFailure('')
-            except signals.TestSignal as signal:
-                new_signal = signal
-
-            if not isinstance(new_signal.extras, dict) and new_signal.extras:
-                raise ValueError('test_info can only append to signal data '
-                                 'that has a dict as the extra value.')
-            elif not new_signal.extras:
-                new_signal.extras = {}
-
-            if not predicate or predicate(args[0], args[1:], kwargs):
-                for k, v in keyed_info.items():
-                    if v and k not in new_signal.extras:
-                        new_signal.extras[k] = v
-                    elif v and k in new_signal.extras:
-                        if not isinstance(new_signal.extras[k], list):
-                            new_signal.extras[k] = [new_signal.extras[k]]
-                        new_signal.extras[k].append(v)
-
-            raise new_signal
-
-        return func_wrapper
+        return _TestInfoDecoratorFunc(func, predicate, keyed_info)
 
     return test_info_decoractor
 
@@ -86,6 +60,130 @@
         extra_environment_info: Extra info about the test tracker environment.
         predicate: A func that if false when called will ignore this info.
     """
-    return test_info(test_tracker_uuid=uuid,
-                     test_tracker_enviroment_info=extra_environment_info,
-                     predicate=predicate)
+    return test_info(
+        test_tracker_uuid=uuid,
+        test_tracker_enviroment_info=extra_environment_info,
+        predicate=predicate)
+
+
+class _TestInfoDecoratorFunc(object):
+    """Object that acts as a function decorator test info."""
+
+    def __init__(self, func, predicate, keyed_info):
+        self.func = func
+        self.predicate = predicate
+        self.keyed_info = keyed_info
+
+    def __get__(self, instance, owner):
+        """Called by Python to create a binding for an instance closure.
+
+        When called by Python this object will create a special binding for
+        that instance. That binding will know how to interact with this
+        specific decorator.
+        """
+        return _TestInfoBinding(self, instance)
+
+    def __call__(self, *args, **kwargs):
+        """
+        When called runs the underlying func and then attaches test info
+        to a signal.
+        """
+        try:
+            result = self.func(*args, **kwargs)
+
+            if result or result is None:
+                new_signal = signals.TestPass('')
+            else:
+                new_signal = signals.TestFailure('')
+        except signals.TestSignal as signal:
+            new_signal = signal
+
+        if not isinstance(new_signal.extras, dict) and new_signal.extras:
+            raise ValueError('test_info can only append to signal data '
+                             'that has a dict as the extra value.')
+        elif not new_signal.extras:
+            new_signal.extras = {}
+
+        gathered_extras = self._gather_local_info(*args, **kwargs)
+        for k, v in gathered_extras.items():
+            if k not in new_signal.extras:
+                new_signal.extras[k] = v
+            else:
+                if not isinstance(new_signal.extras[k], list):
+                    new_signal.extras[k] = [new_signal.extras[k]]
+
+                new_signal.extras[k].insert(0, v)
+
+        raise new_signal
+
+    def gather(self, *args, **kwargs):
+        """
+        Gathers the info from this decorator without invoking the underlying
+        function. This will also gather all child info if the underlying func
+        has that ability.
+
+        Returns: A dictionary of info.
+        """
+        if hasattr(self.func, 'gather'):
+            extras = self.func.gather(*args, **kwargs)
+        else:
+            extras = {}
+
+        self._gather_local_info(*args, gather_into=extras, **kwargs)
+
+        return extras
+
+    def _gather_local_info(self, *args, gather_into=None, **kwargs):
+        """Gathers info from this decorator and ignores children.
+
+        Args:
+            gather_into: Gathers into a dictionary that already exists.
+
+        Returns: The dictionary with gathered info in it.
+        """
+        if gather_into is None:
+            extras = {}
+        else:
+            extras = gather_into
+        if not self.predicate or self.predicate(args, kwargs):
+            for k, v in self.keyed_info.items():
+                if v and k not in extras:
+                    extras[k] = v
+                elif v and k in extras:
+                    if not isinstance(extras[k], list):
+                        extras[k] = [extras[k]]
+                    extras[k].insert(0, v)
+
+        return extras
+
+
+class _TestInfoBinding(object):
+    """
+    When Python creates an instance of an object it creates a binding object
+    for each closure that contains what the instance variable should be when
+    called. This object is a similar binding for _TestInfoDecoratorFunc.
+    When Python tries to create a binding of a _TestInfoDecoratorFunc it
+    will return one of these objects to hold the instance for that closure.
+    """
+
+    def __init__(self, target, instance):
+        """
+        Args:
+            target: The target for creating a binding to.
+            instance: The instance to bind the target with.
+        """
+        self.target = target
+        self.instance = instance
+
+    def __call__(self, *args, **kwargs):
+        """
+        When this object is called it will call the target with the bound
+        instance.
+        """
+        return self.target(self.instance, *args, **kwargs)
+
+    def gather(self, *args, **kwargs):
+        """
+        Will gather the target with the bound instance.
+        """
+        return self.target.gather(self.instance, *args, **kwargs)
diff --git a/acts/framework/tests/acts_base_class_test.py b/acts/framework/tests/acts_base_class_test.py
index a6d8144..1093946 100755
--- a/acts/framework/tests/acts_base_class_test.py
+++ b/acts/framework/tests/acts_base_class_test.py
@@ -53,10 +53,9 @@
     def test_current_test_case_name(self):
         class MockBaseTest(base_test.BaseTestClass):
             def test_func(self):
-                asserts.assert_true(
-                    self.current_test_name == "test_func",
-                    ("Got "
-                     "unexpected test name %s.") % self.current_test_name)
+                asserts.assert_true(self.current_test_name == "test_func", (
+                    "Got "
+                    "unexpected test name %s.") % self.current_test_name)
 
         bt_cls = MockBaseTest(self.mock_test_cls_configs)
         bt_cls.run(test_names=["test_func"])
@@ -175,18 +174,16 @@
                 # This should not execute because setup_class failed.
                 never_call()
 
-            def on_fail(self, test_name, begin_time):
+            def on_blocked(self, test_name, begin_time):
                 call_check("haha")
 
         bt_cls = MockBaseTest(self.mock_test_cls_configs)
         bt_cls.run()
-        actual_record = bt_cls.results.failed[0]
-        self.assertEqual(actual_record.test_name, "setup_class")
-        self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
-        self.assertIsNone(actual_record.extras)
+        actual_record = bt_cls.results.blocked[0]
+        self.assertEqual(actual_record.test_name, "test_something")
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 1, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 0")
+            "Blocked 1, ControllerInfo {}, Executed 0, Failed 0, Passed 0,"
+            " Requested 1, Skipped 0, Unknown 0")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
         call_check.assert_called_once_with("haha")
 
@@ -206,8 +203,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_setup_test_fail_by_test_signal(self):
@@ -226,8 +223,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 1, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 0")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 1, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 0")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_setup_test_fail_by_return_False(self):
@@ -247,8 +244,8 @@
         self.assertEqual(actual_record.details, expected_msg)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 1, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 0")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 1, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 0")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_teardown_test_assert_fail(self):
@@ -266,8 +263,8 @@
         self.assertIsNone(actual_record.details)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_teardown_test_raise_exception(self):
@@ -287,8 +284,8 @@
         expected_extra_error = {"teardown_test": MSG_EXPECTED_EXCEPTION}
         self.assertEqual(actual_record.extra_errors, expected_extra_error)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_teardown_test_executed_if_test_pass(self):
@@ -309,8 +306,8 @@
         self.assertIsNone(actual_record.details)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 1, Requested 1, "
-            "Skipped 0, Unknown 0")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 1, "
+            "Requested 1, Skipped 0, Unknown 0")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_teardown_test_executed_if_setup_test_fails(self):
@@ -334,8 +331,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_teardown_test_executed_if_test_fails(self):
@@ -356,8 +353,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_on_exception_executed_if_teardown_test_fails(self):
@@ -381,8 +378,8 @@
         self.assertIsNone(actual_record.details)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_on_fail_executed_if_test_fails(self):
@@ -403,8 +400,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 1, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 0")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 1, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 0")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_on_fail_executed_if_test_setup_fails_by_exception(self):
@@ -428,8 +425,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_on_fail_executed_if_test_setup_fails_by_return_False(self):
@@ -454,8 +451,8 @@
                          'Setup for test_something failed.')
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 1, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 0")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 1, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 0")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_failure_to_call_procedure_function_is_recorded(self):
@@ -474,8 +471,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_failure_in_procedure_functions_is_recorded(self):
@@ -497,8 +494,8 @@
         self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
         self.assertIsNone(actual_record.extras)
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_both_teardown_and_test_body_raise_exceptions(self):
@@ -518,8 +515,8 @@
         self.assertEqual(actual_record.extra_errors["teardown_test"],
                          "Details=This is an expected exception., Extras=None")
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_explicit_pass_but_teardown_test_raises_an_exception(self):
@@ -542,8 +539,8 @@
         self.assertEqual(actual_record.extra_errors["teardown_test"],
                          "Details=This is an expected exception., Extras=None")
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_on_pass_raise_exception(self):
@@ -564,8 +561,8 @@
         self.assertEqual(actual_record.extra_errors,
                          {'_on_pass': MSG_EXPECTED_EXCEPTION})
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_on_fail_raise_exception(self):
@@ -586,8 +583,8 @@
         self.assertEqual(actual_record.extra_errors,
                          {'_on_fail': MSG_EXPECTED_EXCEPTION})
         expected_summary = (
-            "ControllerInfo {}, Executed 1, Failed 0, Passed 0, Requested 1, "
-            "Skipped 0, Unknown 1")
+            "Blocked 0, ControllerInfo {}, Executed 1, Failed 0, Passed 0, "
+            "Requested 1, Skipped 0, Unknown 1")
         self.assertEqual(bt_cls.results.summary_str(), expected_summary)
 
     def test_abort_class(self):
@@ -608,8 +605,8 @@
         self.assertEqual(bt_cls.results.failed[0].details,
                          MSG_EXPECTED_EXCEPTION)
         self.assertEqual(bt_cls.results.summary_str(), (
-            "ControllerInfo {}, Executed 2, Failed 1, Passed 1, Requested 3, "
-            "Skipped 0, Unknown 0"))
+            "Blocked 0, ControllerInfo {}, Executed 2, Failed 1, Passed 1, "
+            "Requested 3, Skipped 0, Unknown 0"))
 
     def test_uncaught_exception(self):
         class MockBaseTest(base_test.BaseTestClass):
diff --git a/acts/framework/tests/acts_records_test.py b/acts/framework/tests/acts_records_test.py
index afaa5ef..24ba656 100755
--- a/acts/framework/tests/acts_records_test.py
+++ b/acts/framework/tests/acts_records_test.py
@@ -188,42 +188,6 @@
         with self.assertRaisesRegexp(TypeError, expected_msg):
             tr1 += "haha"
 
-    def test_result_fail_class_with_test_signal(self):
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record1.test_pass(s)
-        tr = records.TestResult()
-        tr.add_record(record1)
-        s = signals.TestFailure(self.details, self.float_extra)
-        record2 = records.TestResultRecord("SomeTest", s)
-        tr.fail_class(record2)
-        self.assertEqual(len(tr.passed), 1)
-        self.assertEqual(len(tr.failed), 1)
-        self.assertEqual(len(tr.executed), 2)
-
-    def test_result_fail_class_with_special_error(self):
-        """Call TestResult.fail_class with an error class that requires more
-        than one arg to instantiate.
-        """
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        s = signals.TestPass(self.details, self.float_extra)
-        record1.test_pass(s)
-        tr = records.TestResult()
-        tr.add_record(record1)
-
-        class SpecialError(Exception):
-            def __init__(self, arg1, arg2):
-                self.msg = "%s %s" % (arg1, arg2)
-
-        se = SpecialError("haha", 42)
-        record2 = records.TestResultRecord("SomeTest", se)
-        tr.fail_class(record2)
-        self.assertEqual(len(tr.passed), 1)
-        self.assertEqual(len(tr.failed), 1)
-        self.assertEqual(len(tr.executed), 2)
-
     def test_is_all_pass(self):
         s = signals.TestPass(self.details, self.float_extra)
         record1 = records.TestResultRecord(self.tn)
@@ -253,17 +217,6 @@
         tr.add_record(record2)
         self.assertFalse(tr.is_all_pass)
 
-    def test_is_all_pass_with_fail_class(self):
-        """Verifies that is_all_pass yields correct value when fail_class is
-        used.
-        """
-        record1 = records.TestResultRecord(self.tn)
-        record1.test_begin()
-        record1.test_fail(Exception("haha"))
-        tr = records.TestResult()
-        tr.fail_class(record1)
-        self.assertFalse(tr.is_all_pass)
-
 
 if __name__ == "__main__":
     unittest.main()
\ No newline at end of file