从Flask应用调用Robot Framework关键字报错RobotNotRunningError
解决Flask调用Robot Framework关键字时的RobotNotRunningError错误
问题背景
- 环境:Robot Framework 5.0.1、Python 3.9
- 现象:Python函数在Robot测试套件中调用正常,但通过Flask接口调用时,抛出
RobotNotRunningError('Cannot access execution context') - 相关代码:
Flask接口脚本:
Robot关键字库from flask import Flask, request from robot.libraries.BuiltIn import BuiltIn from robot.api.deco import keyword app = Flask(__name__) ... @app.get('/getAcctData') def get_acctData(): ROBOT_LISTENER_API_VERSION = 3 ROBOT_LIBRARY_SCOPE = 'TEST SUITE' endPoint= request.args.get('myKeyword') or 'get_defaultAcct' username = request.args.get('userid') or 'TEST_USER' password = request.args.get('password') or 'TEST_PW' BuiltIn().import_resource('/Users/S123/myProject/Tests/keywordsLibrary.robot') return(BuiltIn().run_keyword('endPoint',username, password))keywordsLibrary.robot:*** Settings *** Library ${EXECDIR}/Libraries/robot_test_app.py Library ${EXECDIR}/Libraries/basic.py Library OperatingSystem Library RequestsLibrary Library Collections *** Variables *** ${ACCT_API_BASE_URL}= https://acct-api-svc.saraTestOrg.com/api ${PAYLOADFile}= ${EXECDIR}/TestData/acctRequests_payload.txt *** Keywords *** SaraSampleKeyword ${randomreturn}= set variable hello from Sara sample Keyword [return] ${randomreturn} get_acct_api [Arguments] ${API_ENDPOINT} ${Client_ID} ${Cleint_Secret} [Documentation] call specific acct api end points ------ some code here - 完整堆栈追踪:
Traceback (most recent call last): File "/Users/S123/myProject/FlaskApp/app.py", line 22, in get_acctData BuiltIn().import_resource('/Users/S123/myProject/Tests/keywordsLibrary.robot') File "/usr/local/lib/python3.9/site-packages/robot/libraries/BuiltIn.py", line 722, in import_resource self._namespace.import_resource(path, self._variables) File "/usr/local/lib/python3.9/site-packages/robot/running/namespace.py", line 423, in import_resource self._import(resource, variables) File "/usr/local/lib/python3.9/site-packages/robot/running/namespace.py", line 436, in _import imported = importer.import_resource(source) File "/usr/local/lib/python3.9/site-packages/robot/running/importer.py", line 123, in import_resource return self._import_by_type(source, ResourceFile) File "/usr/local/lib/python3.9/site-packages/robot/running/importer.py", line 142, in _import_by_type return self._cached_import(source, lambda: self._import_from_source(source, type_)) File "/usr/local/lib/python3.9/site-packages/robot/running/importer.py", line 162, in _cached_import imported = import_func() File "/usr/local/lib/python3.9/site-packages/robot/running/importer.py", line 142, in <lambda> return self._cached_import(source, lambda: self._import_from_source(source, type_)) File "/usr/local/lib/python3.9/site-packages/robot/running/importer.py", line 169, in _import_from_source return type_(source, self._context).import_or_execute() File "/usr/local/lib/python3.9/site-packages/robot/running/resource.py", line 37, in __init__ self.variables = self._create_variables() File "/usr/local/lib/python3.9/site-packages/robot/running/resource.py", line 61, in _create_variables return Variables(self.data.variables, self._context.variables) File "/usr/local/lib/python3.9/site-packages/robot/running/context.py", line 142, in variables return self._variables File "/usr/local/lib/python3.9/site-packages/robot/utils/robottypes.py", line 128, in __get__ return instance.__dict__[self.name] KeyError: '_variables' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2095, in __call__ return self.wsgi_app(environ, start_response) File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2080, in wsgi_app response = self.handle_exception(e) File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2077, in wsgi_app response = self.full_dispatch_request() File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1525, in full_dispatch_request rv = self.handle_user_exception(e) File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1523, in full_dispatch_request rv = self.dispatch_request() File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1509, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) File "/Users/S123/myProject/FlaskApp/app.py", line 23, in get_acctData return(BuiltIn().run_keyword('endPoint',username, password)) File "/usr/local/lib/python3.9/site-packages/robot/libraries/BuiltIn.py", line 523, in run_keyword return self._namespace.run_keyword(name, args, kwargs) File "/usr/local/lib/python3.9/site-packages/robot/running/namespace.py", line 517, in run_keyword return self._run_keyword(self.get_keyword(name), args, kwargs) File "/usr/local/lib/python3.9/site-packages/robot/running/namespace.py", line 537, in _run_keyword return keyword.run(args, kwargs) File "/usr/local/lib/python3.9/site-packages/robot/running/keyword.py", line 109, in run return self._run(self._arguments.resolve(args, kwargs)) File "/usr/local/lib/python3.9/site-packages/robot/running/userkeyword.py", line 144, in _run self._scope.start_keyword(self.name, args) File "/usr/local/lib/python3.9/site-packages/robot/running/context.py", line 96, in start_keyword self._listener.start_keyword(self._create_keyword_info(name, args)) File "/usr/local/lib/python3.9/site-packages/robot/utils/robottypes.py", line 128, in __get__ return instance.__dict__[self.name] KeyError: '_context'
错误原因
Robot Framework的BuiltIn库依赖Robot执行上下文,只有在Robot测试运行时才会初始化这个上下文。Flask是独立的Web服务,运行时没有启动Robot的执行环境,直接调用BuiltIn()会因为找不到执行上下文报错。
解决方案
方案1:通过Robot完整执行环境调用关键字
创建临时Robot测试用例,通过robot.run()启动完整Robot环境执行关键字,适合快速验证现有关键字逻辑:
from flask import Flask, request import tempfile import os from robot import run app = Flask(__name__) @app.get('/getAcctData') def get_acctData(): end_point = request.args.get('myKeyword') or 'get_defaultAcct' username = request.args.get('userid') or 'TEST_USER' password = request.args.get('password') or 'TEST_PW' # 生成临时Robot测试文件 with tempfile.NamedTemporaryFile(mode='w', suffix='.robot', delete=False) as f: temp_test_path = f.name f.write(f""" *** Settings *** Resource /Users/S123/myProject/Tests/keywordsLibrary.robot *** Test Cases *** Call Target Keyword ${result}= {end_point} {username} {password} Log To Console ${result} """) # 运行Robot测试,关闭日志/报告输出以提升性能 run(temp_test_path, output=None, log=None, report=None) # 清理临时文件 os.unlink(temp_test_path) # 可根据实际需求从控制台输出或自定义存储方式提取关键字返回结果 return f"关键字执行完成"
方案2:重构逻辑,脱离Robot依赖
将关键字中的业务逻辑提取到独立Python模块,Flask和Robot测试分别调用该模块,是长期维护的最优方案:
- 提取业务逻辑到
acct_service.py:
# acct_service.py def get_acct_data(api_endpoint, client_id, client_secret): # 原get_acct_api关键字中的业务代码,比如API调用、数据处理等 return "处理后的账户数据"
- 修改Robot关键字库,调用Python模块:
*** Settings *** Library ${EXECDIR}/Libraries/acct_service.py ... 其他库保持不变 *** Keywords *** get_acct_api [Arguments] ${API_ENDPOINT} ${Client_ID} ${Cleint_Secret} [Documentation] call specific acct api end points ${result}= get_acct_data ${API_ENDPOINT} ${Client_ID} ${Cleint_Secret} [Return] ${result}
- Flask接口直接调用业务模块:
from flask import Flask, request from Libraries.acct_service import get_acct_data app = Flask(__name__) @app.get('/getAcctData') def get_acctData(): end_point = request.args.get('myKeyword') or 'get_defaultAcct' username = request.args.get('userid') or 'TEST_USER' password = request.args.get('password') or 'TEST_PW' # 直接调用业务逻辑函数 result = get_acct_data(end_point, username, password) return result
方案对比
- 方案1:无需修改现有Robot关键字,快速验证,但启动Robot环境有性能开销,结果捕获需额外处理
- 方案2:架构清晰、性能优异,便于后续维护,但需要重构现有关键字逻辑
内容的提问来源于stack exchange,提问作者Sarah
相关产品推荐
相关产品推荐

