def acquire_resources_and_run(self, node, func, func_type=TestFunctionType.TEST):
        """
        Tries to acquire resources for a function and run it, reporting
        appropriately to the TestLogger. Takes care of returning nodes to the work
        provider if resources cannot be locked.

        :param node: The WorkNode containing the function you wish to run.
        :param func: The function you wish to execute
        :param func_type: The TestFunctionType of the function
        :return: True if the function was successfully run, False otherwise
        """
        instance = node.get_test_class_instance()

        # Check for failed execution groups
        if WorkerThread.has_failed_ex_groups(node.test_class, func, node.test_env, self.work_provider):
            self.logger.skippingTestFunction(instance, func, func_type, thread_num=self.thread_num)
            
            #AB - still want to call teardown when threads has failed
            if func_type == TestFunctionType.TEARDOWN:
                func(instance)
                node.test_class_is_torndown = True
            
            return True

        # Try to lock this function's resources
        func_resources = getattr(func, 'resources', [])
        func_resources_locked = self.work_provider.lock_resources(func_resources)
        if not func_resources_locked:
            self.work_provider.release_resources(node.class_resources)
            self.work_provider.add_nodes(node)
            return False

        # Execute the function
        self.logger.runningTestFunction(instance, func, func_type, thread_num=self.thread_num)
        try:
            func(instance)
        except:
            e = sys.exc_info()[0]
            tb = traceback.format_exc()
            self.work_provider.add_failed_ex_groups(
                WorkerThread.get_ex_groups(node.test_class, func),
                node.test_env
            )
            self.logger.foundException(instance, func, e, tb, func_type, thread_num=self.thread_num)

        #AB - additional logging options
        if instance.details != None:
            self.logger.logDetails(instance, func, instance.details, thread_num=self.thread_num)
            instance.clearLog()

        # Cleanup
        if func_type == TestFunctionType.SETUP:
            node.test_class_is_setup = True
        elif func_type == TestFunctionType.TEARDOWN:
            node.test_class_is_torndown = True
        else:
            node.test_funcs.remove(func)
        self.logger.finishedTestFunction(instance, func, func_type, thread_num=self.thread_num)
        self.work_provider.release_resources(func_resources)
        return True
    def run_tests(self):
        """Runs the tests that have been added to this TestRunner and reports the
        results to the given TestLogger."""
        self.logger.startingTests()
        workers = []

        for i in range(len(self.work_providers)):
            work_provider = self.work_providers[i]
            worker = WorkerThread(work_provider, self.logger, thread_num=i)
            worker.start()
            workers.append(worker)

        for worker in workers:
            worker.join()
        return self.logger.finishedTests()
    def run_tests_for_node(self, node):
        """Takes a WorkNode and runs the tests it contains. If some of the node's 
        resources are in use, the node may be returned to the work_provider."""
        # Try to get a lock on the class resources
        resources_locked = self.work_provider.lock_resources(
            node.class_resources)
        if not resources_locked:
            self.work_provider.add_nodes(node)
            return

        cls = node.test_class
        instance = node.get_test_class_instance()

        # if this node contains only one function, check for failed execution groups
        # and don't instatiate the class or call setup
        if len(node.test_funcs) == 1:
            func = node.test_funcs[0]
            if WorkerThread.has_failed_ex_groups(cls, func, node.test_env,
                                                 self.work_provider):
                self.logger.skippingTestFunction(instance,
                                                 func,
                                                 thread_num=self.thread_num)
                self.work_provider.release_resources(node.class_resources)
                return

        # Try to call the class's setup method
        if not node.test_class_is_setup:
            if hasattr(cls, 'setup') and callable(cls.setup):
                success = self.acquire_resources_and_run(
                    node, cls.setup, TestFunctionType.SETUP)
                if not success:
                    return

        # Run all the test functions
        for func in list(
                node.test_funcs
        ):  # copy the list so we don't remove items while iterating
            success = self.acquire_resources_and_run(node, func)
            if not success:
                return

        # Try to call the class's teardown method
        if not node.test_class_is_torndown:
            if hasattr(cls, 'teardown') and callable(cls.teardown):
                success = self.acquire_resources_and_run(
                    node, cls.teardown, TestFunctionType.TEARDOWN)
                if not success:
                    return

        self.work_provider.release_resources(node.class_resources)
Exemple #4
0
    def test_has_failed_ex_groups(self):
        wp = WorkProvider()
        env = {'env': 'env'}

        # Same class, no failed ex groups
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth1, env,
                                              wp))
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth2, env,
                                              wp))

        # Same class, with failed class ex groups
        wp.add_failed_ex_groups([1], env)

        self.assertTrue(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth1, env,
                                              wp))
        self.assertTrue(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth2, env,
                                              wp))

        # Same class, no ex groups, with wp.failed_ex_groups reset
        wp = WorkProvider()

        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth1, env,
                                              wp))
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth2, env,
                                              wp))

        # Same class, with one method having a failed ex_group
        wp.add_failed_ex_groups([2], env)

        self.assertTrue(
            WorkerThread.has_failed_ex_groups(Fixture2, Fixture2.meth1, env,
                                              wp))
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture2, Fixture2.meth2, env,
                                              wp))
    def test_has_failed_ex_groups(self):
        wp = WorkProvider()
        env = { 'env': 'env' }

        # Same class, no failed ex groups
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth1, env, wp)
        )
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth2, env, wp)
        )

        # Same class, with failed class ex groups
        wp.add_failed_ex_groups([1], env)

        self.assertTrue(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth1, env, wp)
        )
        self.assertTrue(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth2, env, wp)
        )

        # Same class, no ex groups, with wp.failed_ex_groups reset
        wp = WorkProvider()

        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth1, env, wp)
        )
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture1, Fixture1.meth2, env, wp)
        )

        # Same class, with one method having a failed ex_group
        wp.add_failed_ex_groups([2], env)

        self.assertTrue(
            WorkerThread.has_failed_ex_groups(Fixture2, Fixture2.meth1, env, wp)
        )
        self.assertFalse(
            WorkerThread.has_failed_ex_groups(Fixture2, Fixture2.meth2, env, wp)
        )
    def run_tests_for_node(self, node):
        """Takes a WorkNode and runs the tests it contains. If some of the node's 
        resources are in use, the node may be returned to the work_provider."""
        # Try to get a lock on the class resources
        resources_locked = self.work_provider.lock_resources(node.class_resources)
        if not resources_locked:
            self.work_provider.add_nodes(node)
            return

        cls = node.test_class
        instance = node.get_test_class_instance()

        # if this node contains only one function, check for failed execution groups
        # and don't instatiate the class or call setup
        if len(node.test_funcs) == 1:
            func = node.test_funcs[0]
            if WorkerThread.has_failed_ex_groups(cls, func, node.test_env, self.work_provider):
                self.logger.skippingTestFunction(instance, func, thread_num=self.thread_num)
                self.work_provider.release_resources(node.class_resources)
                return

        # Try to call the class's setup method
        if not node.test_class_is_setup:
            if hasattr(cls, 'setup') and callable(cls.setup):
                success = self.acquire_resources_and_run(node, cls.setup, TestFunctionType.SETUP)
                if not success:
                    return

        # Run all the test functions
        for func in list(node.test_funcs): # copy the list so we don't remove items while iterating
            success = self.acquire_resources_and_run(node, func)
            if not success:
                return


        # Try to call the class's teardown method
        if not node.test_class_is_torndown:
            if hasattr(cls, 'teardown') and callable(cls.teardown):
                success = self.acquire_resources_and_run(node, cls.teardown, TestFunctionType.TEARDOWN)
                if not success:
                    return

        self.work_provider.release_resources(node.class_resources)
    def run_tests(self):
        """Runs the tests that have been added to this TestRunner and reports the
        results to the given TestLogger."""
        self.logger.startingTests()
        workers = []

        for i in range(len(self.work_providers)):
            work_provider = self.work_providers[i]
            worker = WorkerThread(work_provider, self.logger, thread_num=i)
            worker.start()
            workers.append(worker)

        for worker in workers:
            worker.join()
        return self.logger.finishedTests()
Exemple #8
0
    def test_get_ex_groups(self):
        self.assertEqual([1], WorkerThread.get_ex_groups(Fixture1))
        self.assertEqual([], WorkerThread.get_ex_groups(Fixture1.meth1))
        self.assertEqual([], WorkerThread.get_ex_groups(Fixture1.meth2))
        self.assertEqual([2], WorkerThread.get_ex_groups(Fixture1.meth3))

        self.assertEqual([], WorkerThread.get_ex_groups(Fixture2))
        self.assertEqual([2], WorkerThread.get_ex_groups(Fixture2.meth1))
        self.assertEqual([3, 4],
                         sorted(WorkerThread.get_ex_groups(Fixture2.meth2)))
        self.assertEqual([], WorkerThread.get_ex_groups(Fixture2.meth3))

        # class and method
        self.assertEqual([1],
                         WorkerThread.get_ex_groups(Fixture1, Fixture1.meth1))

        # class and method, each have an execution group
        self.assertEqual(
            [1, 2], sorted(WorkerThread.get_ex_groups(Fixture1,
                                                      Fixture1.meth3)))

        # two methods
        self.assertEqual([2],
                         WorkerThread.get_ex_groups(Fixture1.meth2,
                                                    Fixture1.meth3))

        # two classes
        self.assertEqual([1], WorkerThread.get_ex_groups(Fixture1, Fixture2))

        # class and method with multiple groups
        self.assertEqual(
            [1, 3, 4],
            sorted(WorkerThread.get_ex_groups(Fixture1, Fixture2.meth2)))
    def test_get_ex_groups(self):
        self.assertEqual([1], WorkerThread.get_ex_groups(Fixture1))
        self.assertEqual([], WorkerThread.get_ex_groups(Fixture1.meth1))
        self.assertEqual([], WorkerThread.get_ex_groups(Fixture1.meth2))
        self.assertEqual([2], WorkerThread.get_ex_groups(Fixture1.meth3))

        self.assertEqual([], WorkerThread.get_ex_groups(Fixture2))
        self.assertEqual([2], WorkerThread.get_ex_groups(Fixture2.meth1))
        self.assertEqual([3, 4], sorted(WorkerThread.get_ex_groups(Fixture2.meth2)))
        self.assertEqual([], WorkerThread.get_ex_groups(Fixture2.meth3))

        # class and method
        self.assertEqual([1], WorkerThread.get_ex_groups(Fixture1, Fixture1.meth1))

        # class and method, each have an execution group
        self.assertEqual(
            [1, 2],
            sorted(WorkerThread.get_ex_groups(Fixture1, Fixture1.meth3))
        )

        # two methods
        self.assertEqual(
            [2], 
            WorkerThread.get_ex_groups(Fixture1.meth2, Fixture1.meth3)
        )

        # two classes
        self.assertEqual([1], WorkerThread.get_ex_groups(Fixture1, Fixture2))

        # class and method with multiple groups
        self.assertEqual(
            [1, 3, 4], 
            sorted(WorkerThread.get_ex_groups(Fixture1, Fixture2.meth2))
        )
    def acquire_resources_and_run(self,
                                  node,
                                  func,
                                  func_type=TestFunctionType.TEST):
        """
        Tries to acquire resources for a function and run it, reporting
        appropriately to the TestLogger. Takes care of returning nodes to the work
        provider if resources cannot be locked.

        :param node: The WorkNode containing the function you wish to run.
        :param func: The function you wish to execute
        :param func_type: The TestFunctionType of the function
        :return: True if the function was successfully run, False otherwise
        """
        instance = node.get_test_class_instance()

        # Check for failed execution groups
        if WorkerThread.has_failed_ex_groups(node.test_class, func,
                                             node.test_env,
                                             self.work_provider):
            self.logger.skippingTestFunction(instance,
                                             func,
                                             func_type,
                                             thread_num=self.thread_num)

            #AB - still want to call teardown when threads has failed
            if func_type == TestFunctionType.TEARDOWN:
                func(instance)
                node.test_class_is_torndown = True

            return True

        # Try to lock this function's resources
        func_resources = getattr(func, 'resources', [])
        func_resources_locked = self.work_provider.lock_resources(
            func_resources)
        if not func_resources_locked:
            self.work_provider.release_resources(node.class_resources)
            self.work_provider.add_nodes(node)
            return False

        # Execute the function
        self.logger.runningTestFunction(instance,
                                        func,
                                        func_type,
                                        thread_num=self.thread_num)
        try:
            func(instance)
        except:
            e = sys.exc_info()[0]
            tb = traceback.format_exc()
            self.work_provider.add_failed_ex_groups(
                WorkerThread.get_ex_groups(node.test_class, func),
                node.test_env)
            self.logger.foundException(instance,
                                       func,
                                       e,
                                       tb,
                                       func_type,
                                       thread_num=self.thread_num)

        #AB - additional logging options
        if instance.details != None:
            self.logger.logDetails(instance,
                                   func,
                                   instance.details,
                                   thread_num=self.thread_num)
            instance.clearLog()

        # Cleanup
        if func_type == TestFunctionType.SETUP:
            node.test_class_is_setup = True
        elif func_type == TestFunctionType.TEARDOWN:
            node.test_class_is_torndown = True
        else:
            node.test_funcs.remove(func)
        self.logger.finishedTestFunction(instance,
                                         func,
                                         func_type,
                                         thread_num=self.thread_num)
        self.work_provider.release_resources(func_resources)
        return True