我正在开发一个名为 ApxxRobotFrameworkApiPackage 的 Robot Framework 包,用于进行 API 测试。该包包含自定义关键字,其中之一名为 SendGETRequest,用于发送 GET 请求。
项目结构如下:
ApppRobotFrameworkApiPackage/
├── __init__.py
└── Resources/
└── robot_resources/
└── custom_keywords.robot
这些关键字应该从 init.py 文件中暴露出来。最终,该包将被上传到 Azure DevOps Artifact,并通过 pip install 安装到不同的测试项目中。但是目前关键字 "SendGETRequest" 在 init.py 文件中无法访问。
以下是 init.py 文件中代码的概要版本:
import sys
from robot.api import TestSuite
from robot.libraries.BuiltIn import BuiltIn
sys.path.append('/Users/samuelcheng/Documents/Atlantis-Robotframework-Package/ApppRobotFrameworkApiPackage/')
class ApppRobotFrameworkApiPackage:
def __init__(self, portal=None, useFiddlerProxies=False, *otherSettings):
"""
这是该包的初始化。
在导入包的瞬间,此部分代码将被执行。
其目的是基于使用的门户配置一些设置。
输入:
- Portal:这是应用程序运行的门户名称。
当前选项在变量 portalOptions 下。
如果测试人员希望在其他门户中使用此包,应将设置添加到此函数。
默认值为 None。
- useFiddlerProxies:这决定是否使用 Fiddler 代理。
在设置 API 测试时,Fiddler 非常有用,但由于目前(当前)在 Azure 中不可用,
在流水线运行时不应使用代理。
- otherSettings:这是可以提供其他配置设置的地方。
例如,用于测试的 __FiscaalNummer 和 __SelectedWerkgeverNaam。
"""
global proxies
global url
global cookiesTemplate
global headersTemplate
global endpointPreflight
portalOptions = ["test", "test", "KCC Inkijk"]
if useFiddlerProxies:
proxies = {'http': "127.0.0.1:8888", 'https': "127.0.0.1:8888"}
else:
proxies = None
if portal in portalOptions:
if portal == 'Werknemersportaal':
url = "https://test-netcore.otod.t-dc.ba.test.nl"
cookiesTemplate = {'(.AspNetCore.Antiforgery.[a-zA-Z0-9=_-]*)': None, 'EWSESSION-T': None,
'EWSESSION-T_S': None, 'XSRF-TOKEN': None}
headersTemplate = {'XSRF-TOKEN': None, 'X-XSRF-TOKEN': None,
'Content-Type': 'application/json;charset=UTF-8'}
endpointPreflight = "/kias/mijnbezwaar/api/bezwaarschriften/getcurrentbezwaarschrift"
# TODO: test url
# TODO: logout
elif portal == 'test':
url = "https://test.otod.t-dc.ba.test.nl"
cookiesTemplate = {'ASP.NET_SessionId': None, 'WerkgeverSamlAuthT': None, 'WerkgeverSamlAuthT1': None,
'__FiscaalNummer': otherSettings[0], '__SelectedWerkgeverNaam': otherSettings[1]}
endpointPreflight = "/bezwaarenberoep/api/bezwaar/getbezwaarschriften"
elif portal == "KCC Inkijk":
url = "https://test-netcore.otod.t-dc.ba.test.nl"
cookiesTemplate = {'(.AspNetCore.Antiforgery.[a-zA-Z0-9=_-]*)': None, 'KCCINKIJK': None,
'XSRF-TOKEN': None}
headersTemplate = {'X-XSRF-TOKEN': None, 'Content-Type': 'application/json;charset=UTF-8'}
else:
BuiltIn().log_to_console(
str(portal) + " 不是此包的有效门户。当前可用的门户为:" + str(portalOptions))
self._requests_library = None
# ---------------------------------------------------------------------------
# # 将 custom_keywords.robot 文件加载为测试套件
# self.suite = TestSuite()
# self.suite.resource.imports.resource = 'custom_keywords.robot'
# # 在包中暴露自定义关键字
# self.SendGETRequest = self.suite.resource.keywords["SendGETRequest"]
# # 这允许用户直接从包名导入并使用自定义关键字
# __all__ = [
# "ApppRobotFrameworkApiPackage", # 类名
# "SendGETRequest"
# ]
# ----------------------------------------------------------------------------
# # 使用库语法从 custom_keywords.robot 导入自定义关键字
# resource_path = "ApppRobotFrameworkApiPackage/custom_keywords.robot"
# TestSuite().resource.imports.library(resource_path)
# 将 custom_keywords.robot 文件加载为测试套件
self.suite = TestSuite()
# 使用库语法导入自定义关键字
resource_path = "ApppRobotFrameworkApiPackage/Resources/robot_resources/custom_keywords.robot"
self.suite.resource.imports.library(resource_path)
# 在包中暴露自定义关键字
self.SendGETRequest = self.suite.resource.keywords["SendGETRequest"]
BuiltIn().log_to_console("SendGETRequest 关键字:", self.SendGETRequest)
sys.stdout.flush()
# 这允许用户直接从包名导入并使用自定义关键字
__all__ = [
"ApppRobotFrameworkApiPackage", # 类名
"SendGETRequest"
]
def get_requests_library(self):
"""
由于 Requests Library 是一个具有状态的库,为确保在整个代码中继续使用相同的会话,
我们必须使用一个库实例。
首先检查是否已经有一个库实例(最初设置为 None)。
如果尚未创建实例,将创建并返回一个新实例。
否则,将返回已创建的库实例。
"""
if self._requests_library is None:
self._requests_library = BuiltIn().get_library_instance('RequestsLibrary')
return self._requests_library
custom_keywords.robot
*** Settings ***
Library BuiltIn
Library RequestsLibrary
*** Keywords ***
SendGETRequest
[Arguments] ${endpoint} ${headers}
${session} Create Session mysession endpoint=${endpoint} headers=${headers}
${response}= GET On Session mysession url=${endpoint} headers=${headers} expected_status=anything
Set Suite Variable ${response}
${status} ${response_body}= Run Keyword And Ignore Error Evaluate json.dumps(${response.json()})
Run Keyword If '${status}' == 'FAIL' Set Variable ${response_body} '{}'
Set Suite Variable ${response_body}
[Return] ${response}
自定义关键字 SendGETRequest 如何可以被访问?
从你提供的代码和描述中,你正在开发一个名为 ApxxRobotFrameworkApiPackage
的 Robot Framework 包,并尝试从该包中的 init.py
文件中导出自定义关键字 SendGETRequest
。在你的代码中,你已经尝试了几种方式来暴露这个关键字,但似乎还没有达到预期的结果。
根据你的代码,你可以尝试以下方法来确保你的自定义关键字 SendGETRequest
可以被访问:
更新 __all__
列表:
请确保在 __init__.py
文件中更新 __all__
列表,以包含你希望导出的所有类、函数和变量。在你的代码中,将以下代码添加到 __init__.py
文件中,以确保 SendGETRequest
被正确导出:
__all__ = [
"ApppRobotFrameworkApiPackage", # 类名
"SendGETRequest"
]
检查导入路径:
确保 custom_keywords.robot
文件的路径是正确的。在你的 init.py
文件中,你使用了以下代码来导入自定义关键字:
resource_path = "ApppRobotFrameworkApiPackage/Resources/robot_resources/custom_keywords.robot"
self.suite.resource.imports.library(resource_path)
确保路径是正确的,并且能够正确地找到 custom_keywords.robot
文件。
确认包名和导入路径:
确保你的包名和导入路径都是正确的。在你的 __init__.py
文件中,确保你正确地导入了你的自定义关键字类和函数,如下所示:
from .robot_resources import custom_keywords
检查包路径:
在你的 init.py
文件中,你使用了以下代码将包的路径添加到 sys.path
:
sys.path.append('/Users/samuelcheng/Documents/Atlantis-Robotframework-Package/ApppRobotFrameworkApiPackage/')
确保路径是正确的,并且能够正确地找到你的包。
检查 __init__.py
是否被正确调用:
确保 __init__.py
文件被正确调用。这可以通过在 __init__.py
文件中添加一些输出或打印语句来验证。确保你的自定义关键字类和函数被正确地初始化和导出。
引用chatgpt内容作答:
看起来你的代码中存在一些问题,导致自定义关键字 "SendGETRequest" 在 init.py 文件中无法访问。以下是你可以尝试的一些修复步骤:
1、修正包的初始化代码:
首先,你需要确保在初始化 ApppRobotFrameworkApiPackage 类时正确加载和暴露自定义关键字。你可以按照你注释中的第一种尝试,将以下代码添加到 init.py 文件中:
from robot.api import TestSuite
class ApppRobotFrameworkApiPackage:
def __init__(self, portal=None, useFiddlerProxies=False, *otherSettings):
# 初始化代码...
# 将 custom_keywords.robot 文件加载为测试套件
self.suite = TestSuite()
resource_path = "ApppRobotFrameworkApiPackage/Resources/robot_resources/custom_keywords.robot"
self.suite.resource.imports.library(resource_path)
# 在包中暴露自定义关键字
self.SendGETRequest = self.suite.resource.keywords["SendGETRequest"]
# 其他初始化代码...
然后,在类定义的末尾,添加以下代码以确保关键字可以直接从包中导入:
__all__ = [
"ApppRobotFrameworkApiPackage",
"SendGETRequest"
]
2、修正 custom_keywords.robot 文件:
确保 custom_keywords.robot 文件中的关键字定义是正确的。你的 SendGETRequest 关键字看起来是正确的。
3、在其他地方导入并使用关键字:
一旦你的包初始化和关键字暴露的问题解决了,你可以在其他测试项目中导入并使用这些关键字,就像使用任何其他库一样:
*** Settings ***
Library ApppRobotFrameworkApiPackage
*** Test Cases ***
Example Test
${response}= SendGETRequest /api/endpoint headers=${headers}
Log Response: ${response}
4、确认路径设置:
确保路径设置是正确的。在初始化函数中,你使用了硬编码的路径,这可能在不同环境中导致问题。最好使用相对路径,这样在不同的项目中也能正常工作。
通过按照这些步骤检查和修复你的代码,你应该能够正确暴露并访问自定义关键字 "SendGETRequest"。如果问题仍然存在,确保在初始化和导入的过程中没有发生其他错误。
【以下回答由 GPT 生成】
问题的关键在于如何正确地从 __init__.py
文件中导入和暴露自定义关键字。
以下是一种解决方案:
custom_keywords.robot
文件位于正确的位置。根据目录结构,它应该位于 ApppRobotFrameworkApiPackage/Resources/robot_resources/
。__init__.py
文件顶部添加以下行,将资源文件夹添加到 sys.path
中:import os
sys.path.append(os.path.join(os.path.dirname(__file__), "Resources/robot_resources"))
__init__.py
文件中导入并初始化自定义关键字。以 "SendGETRequest" 关键字为例,在 __init__
方法中添加以下代码:import custom_keywords
class ApppRobotFrameworkApiPackage:
def __init__(self, portal=None, useFiddlerProxies=False, *otherSettings):
# 其他代码...
custom_keywords.init_keywords()
custom_keywords.robot
文件中定义 "SendGETRequest" 关键字。请确保关键字函数以 def
关键字开头,并使用 @keyword
装饰器进行修饰。以下是一个简单的示例:from robot.api.deco import keyword
from robot.libraries.BuiltIn import BuiltIn
@keyword
def send_get_request(url):
# 发送 GET 请求的代码...
pass
def init_keywords():
# 初始化自定义关键字
BuiltIn().import_library(custom_keywords)
custom_keywords.robot
文件名与 import_library
方法中的参数相匹配。通过以上的解决方案,你应该能够从 __init__.py
文件中成功导入和初始化自定义关键字,并且关键字 "SendGETRequest" 应该可以在该文件中正常访问。
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:为了使自定义关键字SendGETRequest可以在包的初始化中被访问,您可以采取以下步骤:
1、 在init.py文件中,确保正确加载和导入custom_keywords.robot文件。您可以使用以下代码替换您目前注释掉的部分,代码如下:
# 将 custom_keywords.robot 文件加载为测试套件
self.suite = TestSuite()
self.suite.resource.imports.library("ApppRobotFrameworkApiPackage.Resources.robot_resources.custom_keywords")
# 在包中暴露自定义关键字
self.SendGETRequest = self.suite.resource.keywords["SendGETRequest"]
# 这允许用户直接从包名导入并使用自定义关键字
__all__ = [
"ApppRobotFrameworkApiPackage", # 类名
"SendGETRequest"
]
2、 确保custom_keywords.robot文件的路径正确。
根据您提供的项目结构,custom_keywords.robot
文件位于 Resources/robot_resources
文件夹下,因此在 __init__.py
文件中正确指定路径为 "ApppRobotFrameworkApiPackage.Resources.robot_resources.custom_keywords"
。
这样做将确保在初始化包时,关键字 "SendGETRequest" 可以被访问和使用。
另外,您还可以考虑以下改进:
sys.path.append()
的路径更改为相对路径,以避免依赖于绝对路径。custom_keywords.robot
文件中的 *** Keywords ***
部分,使用 Library
语句导入 BuiltIn
和 RequestsLibrary
库不是必需的,因为它们已经在 __init__.py
文件中导入。您可以删除这些 Library
语句。请注意,这里提供的解决方案是基于您提供的代码和项目结构。如果您的项目结构或其他配置有所不同,可能需要进行相应的调整。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
援引讯飞星火:
问题出在 __init__.py
文件中,你需要将暴露自定义关键字的代码放在 __init__.py
文件的末尾,而不是在类定义的中间。以下是修改后的 __init__.py
文件:
import sys
from robot.api import TestSuite
from robot.libraries.BuiltIn import BuiltIn
sys.path.append('/Users/samuelcheng/Documents/Atlantis-Robotframework-Package/ApppRobotFrameworkApiPackage/')
class ApppRobotFrameworkApiPackage:
# ... 省略其他代码 ...
def get_requests_library(self):
"""
由于 Requests Library 是一个具有状态的库,为确保在整个代码中继续使用相同的会话,
我们必须使用一个库实例。
首先检查是否已经有一个库实例(最初设置为 None)。
如果尚未创建实例,将创建并返回一个新实例。
否则,将返回已创建的库实例。
"""
if self._requests_library is None:
self._requests_library = BuiltIn().get_library_instance('RequestsLibrary')
return self._requests_library
# 将 custom_keywords.robot 文件加载为测试套件
self.suite = TestSuite()
# 使用库语法导入自定义关键字
resource_path = "ApppRobotFrameworkApiPackage/Resources/robot_resources/custom_keywords.robot"
self.suite.resource.imports.library(resource_path)
# 在包中暴露自定义关键字
self.SendGETRequest = self.suite.resource.keywords["SendGETRequest"]
BuiltIn().log_to_console("SendGETRequest 关键字:", self.SendGETRequest)
sys.stdout.flush()
# 这允许用户直接从包名导入并使用自定义关键字
__all__ = [
"ApppRobotFrameworkApiPackage", # 类名
"SendGETRequest"
]
这样,自定义关键字 SendGETRequest
应该可以被访问了。
from .Resources.robot_resources.custom_keywords import SendGETRequest
from robot.api import TestSuite
from robot.libraries.BuiltIn import BuiltIn
class ApppRobotFrameworkApiPackage:
def __init__(self, portal=None, useFiddlerProxies=False, *otherSettings):
# ... 你的初始化代码 ...
# 将 custom_keywords.robot 文件加载为测试套件
self.suite = TestSuite()
# 使用库语法导入自定义关键字
resource_path = "ApppRobotFrameworkApiPackage/Resources/robot_resources/custom_keywords.robot"
self.suite.resource.imports.library(resource_path)
# 在包中暴露自定义关键字
self.SendGETRequest = self.suite.resource.keywords["SendGETRequest"]
robot framework自定义以及使用关键字
可以参考下
使用 self.suite.resource.imports.resource(resource_path) 来导入资源文件
使用 self.suite.resource.keywords.create(“SendGETRequest”) 来创建一个关键字对象
试试呢
可以加入环境变量,引入这个资源。
参考结合GPT4.0、文心一言,如有帮助,恭请采纳。
需要确保你的Python环境可以找到requests库,并且你的测试环境可以找到test_library.py。
# test_cases.robot
*** Settings ***
Library test_library.py
*** Test Cases ***
Test GET Request
SendGETRequest https://example.com/api/endpoint {'Accept': 'application/json'}
然后定义一个名为"SendGETRequest"的关键字:
# test_library.py
from robot.libraries.BuiltIn import BuiltIn
from requests import Session
from requests.exceptions import ConnectionError
import json
class TestLibrary:
def __init__(self):
self._ BuiltIn = BuiltIn()
self.session = Session()
def SendGETRequest(self, endpoint, headers=None):
if headers is None:
headers = {}
try:
response = self.session.get(endpoint, headers=headers)
self._BuiltIn.set_suite_variable('response', response)
status = response.status_code
response_body = json.dumps(response.json()) if response.content else '{}'
self._BuiltIn.set_suite_variable('response_body', response_body)
return response
except ConnectionError:
self._BuiltIn.set_suite_variable('response', 'connection_error')
return 'connection_error'
用SendGETRequest关键字时,使用库的实例来访问它。在上述示例中,ApxxRobotFrameworkApiPackage是您的库,您将其实例化为${api},因此您可以通过${api.SendGETRequest}来调用关键字
结合GPT给出回答如下请题主参考
要解决自定义关键字初始化和访问性问题,你可以按照以下步骤进行:
创建一个名为 ApxxRobotFrameworkApiPackage 的文件夹,并在文件夹中创建一个名为 __init__.py
的文件,这将使该文件夹成为 Python 包。
在 __init__.py
文件中,你可以定义一个方法,该方法将初始化你的自定义关键字,例如 init_keywords()
。
在自定义关键字中导入该方法,并在自定义关键字之前调用该方法。
为了提高可访问性,你可以将 ApxxRobotFrameworkApiPackage
添加到你的 PYTHONPATH
环境变量中,这将使 Robot Framework 在运行时能够找到该包。
以下是 __init__.py
文件的示例代码:
from .keywords import SendGETRequ # 导入自定义关键字
def init_keywords():
# 初始化关键字
SendGETRequ()
以下是自定义关键字文件的示例代码:
from ApxxRobotFrameworkApiPackage import init_keywords
init_keywords() # 在关键字之前调用初始化方法
def SendGETRequ():
# 发送 GET 请求的代码
如果你已将 ApxxRobotFrameworkApiPackage
添加到 PYTHONPATH
中,那么在你的 Robot Framework 测试套件中,你只需要导入自定义关键字并使用它:
*** Settings ***
Library ApxxRobotFrameworkApiPackage.keywords
*** Test Cases ***
Example Test
Send GET Requ
在 Robot Framework 中,自定义关键字需要被定义在一个 .py 文件中,并且在该文件中使用 def 语句定义函数。然后,该 .py 文件需要在你的包目录下,并在 init.py 文件中导入并暴露出去。
在Robot Framework中,包可以用来组织和管理关键字。包中的关键字可以是Python类或函数。
在包中定义自定义关键字时,有两个主要问题需要解决:初始化问题和可访问性问题。
当我们定义自定义关键字时,有时需要在关键字的执行前完成一些初始化工作,例如连接数据库或打开文件等。我们可以使用类的__init__方法或者Python中的模块级别函数来完成这些初始化工作。
示例:
# MyLibrary.py
class MyLibrary:
def __init__(self):
self.db = Database()
self.file = open('myfile.txt', 'r')
def connect_to_database(self):
# Connect to database
pass
def read_file(self):
# Read file
pass
在上述示例中,我们在类的__init__方法中初始化了数据库连接和文件对象。这样,在我们调用MyLibrary中的其他关键字时,这些初始化工作已经完成了。
默认情况下,Robot Framework将自定义关键字路径添加到Python的sys.path中。这意味着我们可以在测试套件中使用自定义关键字。但是,我们不能在其他Python脚本中使用这些自定义关键字,因为它们不在Python的sys.path中。
解决这个问题的一种方法是将自定义关键字路径添加到Python的sys.path中。我们可以在测试套件的引入部分中使用类似于以下的代码:
*** Settings ***
Library path/to/MyLibrary.py
*** Variables ***
${DB_NAME} my_db
但是,这种方法有一个问题,那就是在测试套件中的所有测试用例中都需要将关键字路径添加到sys.path中。这很麻烦,并且可能会导致代码重复和维护问题。
另一种解决方法是使用Robot Framework的扩展API来动态添加关键字路径。我们可以在MyLibrary.py中添加以下代码:
# MyLibrary.py
import sys
import os
path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
if path not in sys.path:
sys.path.insert(0, path)
class MyLibrary:
def __init__(self):
self.db = Database()
self.file = open('myfile.txt', 'r')
def connect_to_database(self):
# Connect to database
pass
def read_file(self):
# Read file
pass
在上述示例中,我们将自定义关键字路径添加到sys.path中,并确保它只添加一次。
这样,我们就可以在其他Python脚本中引入MyLibrary.py,并使用其中的自定义关键字。
通过解决初始化问题和可访问性问题,我们可以更好地组织和管理Robot Framework中的自定义关键字,使其更加灵活和易于维护。
在init.py文件中,确保正确导入自定义关键字所在的模块,确保文件路径的正确性