ContinuableFailure stops execution

I’m trying to use BuiltIn.run_keyword() to execute and highlight threshold checking within a custom library. I need execution to continue if there is a failure, and thus I’m raising robot.api.ContinuableFailure. Here is a small example.

MyLibrary.py:

def __init__(self) -> None:
    self.ROBOT_LIBRARY_LISTENER = self
    self.output_directory = Path('.')
    
def _start_suite(self, name, _):
    try:
        self.robot_builtin = BuiltIn()
    except:
        warn('_start_suite listener function failed to execute')

def _check(self, pattern:str='Value Error of 1 should be less than 2'):
    # self.robot_builtin.run_keyword_and_continue_on_failure(pattern) # same problem
    self.robot_builtin.run_keyword(pattern)
    
@keyword('${check_name} of ${value} should be less than ${threshold}')
def _check_less_than(self, check_name, value, threshold):
    print(f'value: {value} should be less than {threshold}')
    if  value > threshold:
        raise ContinuableFailure('Threshold Exceeded')
    
def my_keyword(self):
    self._check('Value of 3 should be less than 2')
    info('this should be printed regardless')

Unfortunately the execution stops after the first error is raised, and the info() text is not printed in the above example. Maybe I am not using this exception correctly but I would really like to use this kind of _check() function in a for loop to check bounds on a number of values within my custom library’s keywords, and get all the way through the loop before exiting the keyword.

Is this possible?

Hello,

It seems like you’re on the right track with using ContinuableFailure to allow the execution to continue after a failure. However, the issue might be with how you’re calling the keyword. The run_keyword method will stop the execution if an error occurs, which is why you’re not seeing the info() message.

To ensure that the execution continues even after a failure, you should use the run_keyword_and_continue_on_failure method. This method is specifically designed to handle failures by logging them and continuing the execution. Here’s how you can modify your _check method:

from robot.api.deco import keyword
from robot.api import ContinuableFailure
from robot.libraries.BuiltIn import BuiltIn
from pathlib import Path

class MyLibrary:
def init(self) → None:
self.ROBOT_LIBRARY_LISTENER = self
self.output_directory = Path(‘.’)

def _start_suite(self, name, _):
    try:
        self.robot_builtin = BuiltIn()
    except:
        self.robot_builtin.warn('_start_suite listener function failed to execute')

def _check(self, pattern:str='Value Error of 1 should be less than 2'):
    self.robot_builtin.run_keyword_and_continue_on_failure(pattern)
    
@keyword('${check_name} of ${value} should be less than ${threshold}')
def _check_less_than(self, check_name, value, threshold):
    print(f'{check_name}: {value} should be less than {threshold}')
    if value > threshold:
        raise ContinuableFailure('Threshold Exceeded')
    
def my_keyword(self):
    self._check('Check Value of 3 should be less than 2')
    self.robot_builtin.log('this should be printed regardless')

In this code, I’ve replaced warn with self.robot_builtin.warn and info with self.robot_builtin.log to ensure they are properly called from the BuiltIn library. Also, I’ve changed the run_keyword call to run_keyword_and_continue_on_failure in the _check method.

Now, when you call my_keyword, it should execute the _check method, and if a ContinuableFailure is raised, it will log the failure and continue with the next line, which logs ‘this should be printed regardless’.

Remember to use the @keyword decorator from robot.api.deco to define your keywords, and ensure that your custom library is properly imported and used in your Robot Framework test suite.